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

Collapse All | Expand All

(-)src/org/eclipse/jface/internal/databinding/swt/ListObservableValue.java (-109 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bug 198904
12
 *******************************************************************************/
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.core.databinding.observable.Diffs;
16
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.widgets.Event;
19
import org.eclipse.swt.widgets.List;
20
import org.eclipse.swt.widgets.Listener;
21
22
/**
23
 * @since 3.2
24
 * 
25
 */
26
public class ListObservableValue extends AbstractSWTObservableValue {
27
28
	private final List list;
29
30
	private boolean updating = false;
31
32
	private String currentValue;
33
34
	private Listener listener;
35
36
	/**
37
	 * @param list
38
	 */
39
	public ListObservableValue(List list) {
40
		super(list);
41
		this.list = list;
42
		this.currentValue = (String) doGetValue();
43
44
		if ((list.getStyle() & SWT.MULTI) > 0)
45
			throw new IllegalArgumentException(
46
					"SWT.SINGLE support only for a List selection"); //$NON-NLS-1$
47
48
		listener = new Listener() {
49
50
			public void handleEvent(Event event) {
51
				if (!updating) {
52
					Object oldValue = currentValue;
53
					currentValue = (String) doGetValue();
54
					fireValueChange(Diffs.createValueDiff(oldValue,
55
							currentValue));
56
				}
57
			}
58
59
		};
60
		list.addListener(SWT.Selection, listener);
61
	}
62
63
	public void doSetValue(Object value) {
64
		String oldValue = null;
65
		if (list.getSelection() != null && list.getSelection().length > 0)
66
			oldValue = list.getSelection()[0];
67
		try {
68
			updating = true;
69
			String items[] = list.getItems();
70
			int index = -1;
71
			if (items != null && value != null) {
72
				for (int i = 0; i < items.length; i++) {
73
					if (value.equals(items[i])) {
74
						index = i;
75
						break;
76
					}
77
				}
78
				list.select(index); // -1 will not "unselect"
79
			}
80
			currentValue = (String) value;
81
		} finally {
82
			updating = false;
83
		}
84
		fireValueChange(Diffs.createValueDiff(oldValue, value));
85
	}
86
87
	public Object doGetValue() {
88
		int index = list.getSelectionIndex();
89
		if (index >= 0)
90
			return list.getItem(index);
91
		return null;
92
	}
93
94
	public Object getValueType() {
95
		return String.class;
96
	}
97
98
	/*
99
	 * (non-Javadoc)
100
	 *
101
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
102
	 */
103
	public synchronized void dispose() {
104
		super.dispose();
105
		if (listener != null && !list.isDisposed()) {
106
			list.removeListener(SWT.Selection, listener);
107
		}
108
	}
109
}
(-)src/org/eclipse/jface/internal/databinding/swt/CComboSingleSelectionObservableValue.java (-81 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bug 198904
12
 *******************************************************************************/
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.swt.custom.CCombo;
17
import org.eclipse.swt.events.SelectionEvent;
18
import org.eclipse.swt.events.SelectionListener;
19
20
/**
21
 * @since 1.0
22
 *
23
 */
24
public class CComboSingleSelectionObservableValue extends
25
		SingleSelectionObservableValue {
26
27
	private SelectionListener selectionListener;
28
29
	/**
30
	 * @param combo
31
	 */
32
	public CComboSingleSelectionObservableValue(CCombo combo) {
33
		super(combo);
34
	}
35
	
36
	/**
37
	 * @param realm
38
	 * @param combo
39
	 */
40
	public CComboSingleSelectionObservableValue(Realm realm, CCombo combo) {
41
		super(realm, combo);
42
	}
43
44
	private CCombo getCCombo() {
45
		return (CCombo) getWidget();
46
	}
47
48
	protected void doAddSelectionListener(final Runnable runnable) {
49
		selectionListener = new SelectionListener() {
50
			public void widgetDefaultSelected(SelectionEvent e) {
51
				runnable.run();
52
			}
53
54
			public void widgetSelected(SelectionEvent e) {
55
				runnable.run();
56
			}
57
		};
58
		getCCombo().addSelectionListener(selectionListener);
59
	}
60
61
	protected int doGetSelectionIndex() {
62
		return getCCombo().getSelectionIndex();
63
	}
64
65
	protected void doSetSelectionIndex(int index) {
66
		getCCombo().setText(getCCombo().getItem(index));
67
	}
68
69
	/*
70
	 * (non-Javadoc)
71
	 *
72
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
73
	 */
74
	public synchronized void dispose() {
75
		super.dispose();
76
		if (selectionListener != null && !getCCombo().isDisposed()) {
77
			getCCombo().removeSelectionListener(selectionListener);
78
		}
79
80
	}
81
}
(-)src/org/eclipse/jface/internal/databinding/swt/ShellObservableValue.java (-74 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 207844)
10
 *     IBM Corporation - initial API and implementation
11
 *     Brad Reynolds - initial API and implementation
12
 *     Matthew Hall - bug 212235
13
 *******************************************************************************/
14
package org.eclipse.jface.internal.databinding.swt;
15
16
import org.eclipse.core.databinding.observable.Diffs;
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
20
import org.eclipse.swt.widgets.Shell;
21
22
/**
23
 * An {@link IObservableValue} that tracks the text of a Shell.
24
 * 
25
 * @since 1.2
26
 */
27
public class ShellObservableValue extends AbstractSWTObservableValue {
28
29
	private final Shell shell;
30
31
	/**
32
	 * Constructs a ShellObservableValue which tracks the text of the given
33
	 * Shell.
34
	 * 
35
	 * @param shell
36
	 *            the shell to track
37
	 */
38
	public ShellObservableValue(Shell shell) {
39
		super(shell);
40
		this.shell = shell;
41
	}
42
43
	/**
44
	 * Constructs a ShellObservableValue belonging to the given realm, which
45
	 * tracks the text of the given shell.
46
	 * 
47
	 * @param realm
48
	 *            the realm of the constructed observable
49
	 * @param shell
50
	 *            the shell to track
51
	 */
52
	public ShellObservableValue(Realm realm, Shell shell) {
53
		super(realm, shell);
54
		this.shell = shell;
55
	}
56
57
	protected void doSetValue(final Object value) {
58
		String oldValue = shell.getText();
59
		String newValue = value == null ? "" : value.toString(); //$NON-NLS-1$
60
		shell.setText(newValue);
61
62
		if (!newValue.equals(oldValue)) {
63
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));
64
		}
65
	}
66
67
	protected Object doGetValue() {
68
		return shell.getText();
69
	}
70
71
	public Object getValueType() {
72
		return String.class;
73
	}
74
}
(-)src/org/eclipse/jface/internal/databinding/swt/CComboObservableList.java (-51 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jface.internal.databinding.swt;
12
13
import org.eclipse.jface.databinding.swt.SWTObservables;
14
import org.eclipse.swt.custom.CCombo;
15
16
/**
17
 * @since 3.2
18
 * 
19
 */
20
public class CComboObservableList extends SWTObservableList {
21
22
	private final CCombo ccombo;
23
24
	/**
25
	 * @param ccombo
26
	 */
27
	public CComboObservableList(CCombo ccombo) {
28
		super(SWTObservables.getRealm(ccombo.getDisplay()));
29
		this.ccombo = ccombo;
30
	}
31
32
	protected int getItemCount() {
33
		return ccombo.getItemCount();
34
	}
35
36
	protected void setItems(String[] newItems) {
37
		ccombo.setItems(newItems);
38
	}
39
40
	protected String[] getItems() {
41
		return ccombo.getItems();
42
	}
43
44
	protected String getItem(int index) {
45
		return ccombo.getItem(index);
46
	}
47
48
	protected void setItem(int index, String string) {
49
		ccombo.setItem(index, string);
50
	}
51
}
(-)src/org/eclipse/jface/internal/databinding/swt/ScaleObservableValue.java (-150 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Peter Centgraf - bug 175763
11
 *******************************************************************************/
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.runtime.Assert;
17
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
18
import org.eclipse.swt.events.SelectionAdapter;
19
import org.eclipse.swt.events.SelectionEvent;
20
import org.eclipse.swt.events.SelectionListener;
21
import org.eclipse.swt.widgets.Scale;
22
23
/**
24
 * @since 1.0
25
 * 
26
 */
27
public class ScaleObservableValue extends AbstractSWTObservableValue {
28
29
	private final Scale scale;
30
31
	private final String attribute;
32
33
	private boolean updating = false;
34
35
	private int currentSelection;
36
	
37
	private SelectionListener listener;
38
39
	/**
40
	 * @param scale
41
	 * @param attribute
42
	 */
43
	public ScaleObservableValue(Scale scale, String attribute) {
44
		super(scale);
45
		this.scale = scale;
46
		this.attribute = attribute;
47
		init();
48
	}
49
	
50
	/**
51
	 * @param realm
52
	 * @param scale
53
	 * @param attribute
54
	 */
55
	public ScaleObservableValue(Realm realm, Scale scale, String attribute) {
56
		super(realm, scale);
57
		this.scale = scale;
58
		this.attribute = attribute;
59
		init();
60
	}
61
	
62
	private void init() {		
63
		if (attribute.equals(SWTProperties.SELECTION)) {
64
			currentSelection = scale.getSelection();
65
			scale.addSelectionListener(listener = new SelectionAdapter() {
66
				public void widgetSelected(SelectionEvent e) {
67
					if (!updating) {
68
						int newSelection = ScaleObservableValue.this.scale
69
						.getSelection();
70
						notifyIfChanged(currentSelection, newSelection);
71
						currentSelection = newSelection;
72
					}
73
				}
74
			});
75
		} else if (!attribute.equals(SWTProperties.MIN)
76
				&& !attribute.equals(SWTProperties.MAX)) {
77
			throw new IllegalArgumentException(
78
					"Attribute name not valid: " + attribute); //$NON-NLS-1$
79
		}
80
	}
81
82
	public void doSetValue(final Object value) {
83
		int oldValue;
84
		int newValue;
85
		try {
86
			updating = true;
87
			newValue = ((Integer) value).intValue();
88
			if (attribute.equals(SWTProperties.SELECTION)) {
89
				oldValue = scale.getSelection();
90
				scale.setSelection(newValue);
91
				currentSelection = newValue;
92
			} else if (attribute.equals(SWTProperties.MIN)) {
93
				oldValue = scale.getMinimum();
94
				scale.setMinimum(newValue);
95
			} else if (attribute.equals(SWTProperties.MAX)) {
96
				oldValue = scale.getMaximum();
97
				scale.setMaximum(newValue);
98
			} else {
99
				Assert.isTrue(false, "invalid attribute name:" + attribute); //$NON-NLS-1$
100
				return;
101
			}
102
			
103
			notifyIfChanged(oldValue, newValue);
104
		} finally {
105
			updating = false;
106
		}
107
	}
108
109
	public Object doGetValue() {
110
		int value = 0;
111
		if (attribute.equals(SWTProperties.SELECTION)) {
112
			value = scale.getSelection();
113
		} else if (attribute.equals(SWTProperties.MIN)) {
114
			value = scale.getMinimum();
115
		} else if (attribute.equals(SWTProperties.MAX)) {
116
			value = scale.getMaximum();
117
		}
118
		return new Integer(value);
119
	}
120
121
	public Object getValueType() {
122
		return Integer.TYPE;
123
	}
124
125
	/**
126
	 * @return attribute being observed
127
	 */
128
	public String getAttribute() {
129
		return attribute;
130
	}
131
	
132
	/* (non-Javadoc)
133
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
134
	 */
135
	public synchronized void dispose() {
136
		super.dispose();
137
		
138
		if (listener != null && !scale.isDisposed()) {
139
			scale.removeSelectionListener(listener);
140
		}
141
		listener = null;
142
	}
143
	
144
	private void notifyIfChanged(int oldValue, int newValue) {
145
		if (oldValue != newValue) {
146
			fireValueChange(Diffs.createValueDiff(new Integer(oldValue),
147
					new Integer(newValue)));
148
		}
149
	}
150
}
(-)src/org/eclipse/jface/internal/databinding/swt/CComboObservableValue.java (-166 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bug 198904
12
 *     Matthew Hall - bug 118516
13
 *     Eric Rizzo - bug 134884
14
 *******************************************************************************/
15
package org.eclipse.jface.internal.databinding.swt;
16
17
import org.eclipse.core.databinding.observable.Diffs;
18
import org.eclipse.core.databinding.observable.Realm;
19
import org.eclipse.core.runtime.Assert;
20
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
21
import org.eclipse.swt.custom.CCombo;
22
import org.eclipse.swt.events.ModifyEvent;
23
import org.eclipse.swt.events.ModifyListener;
24
25
/**
26
 * @since 3.2
27
 * 
28
 */
29
public class CComboObservableValue extends AbstractSWTObservableValue {
30
31
	/**
32
	 * 
33
	 */
34
35
	private final CCombo ccombo;
36
37
	private final String attribute;
38
39
	private boolean updating = false;
40
41
	private String currentValue;
42
43
	private ModifyListener modifyListener;
44
45
	/**
46
	 * @param ccombo
47
	 * @param attribute
48
	 */
49
	public CComboObservableValue(CCombo ccombo, String attribute) {
50
		super(ccombo);
51
		this.ccombo = ccombo;
52
		this.attribute = attribute;
53
		init();
54
	}
55
56
	/**
57
	 * @param realm
58
	 * @param ccombo
59
	 * @param attribute
60
	 */
61
	public CComboObservableValue(Realm realm, CCombo ccombo, String attribute) {
62
		super(realm, ccombo);
63
		this.ccombo = ccombo;
64
		this.attribute = attribute;
65
		init();
66
	}
67
	
68
	private void init() {		
69
		if (attribute.equals(SWTProperties.SELECTION)
70
				|| attribute.equals(SWTProperties.TEXT)) {
71
			this.currentValue = ccombo.getText();
72
			modifyListener = new ModifyListener() {
73
74
				public void modifyText(ModifyEvent e) {
75
					if (!updating) {
76
						String oldValue = currentValue;
77
						currentValue = CComboObservableValue.this.ccombo
78
								.getText();
79
						
80
						notifyIfChanged(oldValue, currentValue);
81
					}
82
				}
83
			};
84
			ccombo.addModifyListener(modifyListener);
85
		} else
86
			throw new IllegalArgumentException();
87
	}
88
89
	public void doSetValue(final Object value) {
90
		String oldValue = ccombo.getText();
91
		try {
92
			updating = true;
93
			if (attribute.equals(SWTProperties.TEXT)) {
94
				String stringValue = value != null ? value.toString() : ""; //$NON-NLS-1$
95
				ccombo.setText(stringValue);
96
			} else if (attribute.equals(SWTProperties.SELECTION)) {
97
				String items[] = ccombo.getItems();
98
				int index = -1;
99
				if (value == null) {
100
					ccombo.select(-1);
101
				} else if (items != null) {
102
					for (int i = 0; i < items.length; i++) {
103
						if (value.equals(items[i])) {
104
							index = i;
105
							break;
106
						}
107
					}
108
					if (index == -1) {
109
						ccombo.setText((String) value);
110
					} else {
111
						ccombo.select(index); // -1 will not "unselect"
112
					}
113
				}
114
			}
115
		} finally {
116
			updating = false;
117
			currentValue = ccombo.getText();
118
		}
119
		
120
		notifyIfChanged(oldValue, currentValue);
121
	}
122
123
	public Object doGetValue() {
124
		if (attribute.equals(SWTProperties.TEXT))
125
			return ccombo.getText();
126
127
		Assert.isTrue(attribute.equals(SWTProperties.SELECTION),
128
				"unexpected attribute: " + attribute); //$NON-NLS-1$
129
		// The problem with a ccombo, is that it changes the text and
130
		// fires before it update its selection index
131
		return ccombo.getText();
132
	}
133
134
	public Object getValueType() {
135
		Assert.isTrue(attribute.equals(SWTProperties.TEXT)
136
				|| attribute.equals(SWTProperties.SELECTION),
137
				"unexpected attribute: " + attribute); //$NON-NLS-1$
138
		return String.class;
139
	}
140
141
	/**
142
	 * @return attribute being observed
143
	 */
144
	public String getAttribute() {
145
		return attribute;
146
	}
147
148
	/*
149
	 * (non-Javadoc)
150
	 *
151
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
152
	 */
153
	public synchronized void dispose() {
154
		super.dispose();
155
156
		if (modifyListener != null && !ccombo.isDisposed()) {
157
			ccombo.removeModifyListener(modifyListener);
158
		}
159
	}
160
	
161
	private void notifyIfChanged(String oldValue, String newValue) {
162
		if (!oldValue.equals(newValue)) {
163
			fireValueChange(Diffs.createValueDiff(oldValue, ccombo.getText()));			
164
		}
165
	}
166
}
(-)src/org/eclipse/jface/internal/databinding/swt/TableSingleSelectionObservableValue.java (-80 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bug 198904
12
 *******************************************************************************/
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.swt.events.SelectionEvent;
17
import org.eclipse.swt.events.SelectionListener;
18
import org.eclipse.swt.widgets.Table;
19
20
/**
21
 * @since 1.0
22
 * 
23
 */
24
public class TableSingleSelectionObservableValue extends
25
		SingleSelectionObservableValue {
26
27
	private SelectionListener selectionListener;
28
29
	/**
30
	 * @param table
31
	 */
32
	public TableSingleSelectionObservableValue(Table table) {
33
		super(table);
34
	}
35
	
36
	/**
37
	 * @param realm
38
	 * @param table
39
	 */
40
	public TableSingleSelectionObservableValue(Realm realm, Table table) {
41
		super(realm, table);
42
	}
43
44
	private Table getTable() {
45
		return (Table) getWidget();
46
	}
47
48
	protected void doAddSelectionListener(final Runnable runnable) {
49
		selectionListener = new SelectionListener() {
50
			public void widgetDefaultSelected(SelectionEvent e) {
51
				runnable.run();
52
			}
53
54
			public void widgetSelected(SelectionEvent e) {
55
				runnable.run();
56
			}
57
		};
58
		getTable().addSelectionListener(selectionListener);
59
	}
60
61
	protected int doGetSelectionIndex() {
62
		return getTable().getSelectionIndex();
63
	}
64
65
	protected void doSetSelectionIndex(int index) {
66
		getTable().setSelection(index);
67
	}
68
69
	/*
70
	 * (non-Javadoc)
71
	 *
72
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
73
	 */
74
	public synchronized void dispose() {
75
		super.dispose();
76
		if (selectionListener != null && !getTable().isDisposed()) {
77
			getTable().removeSelectionListener(selectionListener);
78
		}
79
	}
80
}
(-)src/org/eclipse/jface/internal/databinding/swt/SWTObservableList.java (-193 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 208858
11
 *******************************************************************************/
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import java.util.ArrayList;
15
import java.util.Arrays;
16
import java.util.Collection;
17
import java.util.List;
18
19
import org.eclipse.core.databinding.BindingException;
20
import org.eclipse.core.databinding.observable.Diffs;
21
import org.eclipse.core.databinding.observable.ObservableTracker;
22
import org.eclipse.core.databinding.observable.Realm;
23
import org.eclipse.core.databinding.observable.list.AbstractObservableList;
24
25
/**
26
 * Abstract base class of CComboObservableList, ComboObservableList, and
27
 * ListObservableList.
28
 * 
29
 * @since 3.2
30
 * 
31
 */
32
public abstract class SWTObservableList extends AbstractObservableList {
33
34
	/**
35
	 * 
36
	 */
37
	public SWTObservableList() {
38
		super();
39
	}
40
41
	/**
42
	 * @param realm
43
	 */
44
	public SWTObservableList(Realm realm) {
45
		super(realm);
46
	}
47
48
	public void add(int index, Object element) {
49
		int size = doGetSize();
50
		if (index < 0 || index > size)
51
			index = size;
52
		String[] newItems = new String[size + 1];
53
		System.arraycopy(getItems(), 0, newItems, 0, index);
54
		newItems[index] = (String) element;
55
		System.arraycopy(getItems(), index, newItems, index + 1, size - index);
56
		setItems(newItems);
57
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index,
58
				true, element)));
59
	}
60
61
	public int doGetSize() {
62
		return getItemCount();
63
	}
64
65
	public Object get(int index) {
66
		getterCalled();
67
		return getItem(index);
68
	}
69
70
	public Object getElementType() {
71
		return String.class;
72
	}
73
74
	/**
75
	 * @param index
76
	 * @return the item at the given index
77
	 */
78
	protected abstract String getItem(int index);
79
80
	/**
81
	 * @return the item count
82
	 */
83
	protected abstract int getItemCount();
84
85
	/**
86
	 * @return the items
87
	 */
88
	protected abstract String[] getItems();
89
90
	private void getterCalled() {
91
		ObservableTracker.getterCalled(this);
92
	}
93
94
	public Object remove(int index) {
95
		getterCalled();
96
		int size = doGetSize();
97
		if (index < 0 || index > size - 1)
98
			throw new BindingException(
99
					"Request to remove an element out of the collection bounds"); //$NON-NLS-1$
100
101
		String[] newItems = new String[size - 1];
102
		String oldElement = getItem(index);
103
		if (newItems.length > 0) {
104
			System.arraycopy(getItems(), 0, newItems, 0, index);
105
			if (size - 1 > index) {
106
				System.arraycopy(getItems(), index + 1, newItems, index, size
107
						- index - 1);
108
			}
109
		}
110
		setItems(newItems);
111
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index,
112
				false, oldElement)));
113
		return oldElement;
114
	}
115
116
	public Object set(int index, Object element) {
117
		String oldElement = getItem(index);
118
		setItem(index, (String) element);
119
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index,
120
				false, oldElement), Diffs.createListDiffEntry(index, true,
121
				element)));
122
		return oldElement;
123
	}
124
125
	public Object move(int oldIndex, int newIndex) {
126
		checkRealm();
127
		if (oldIndex == newIndex)
128
			return get(oldIndex);
129
		int size = doGetSize();
130
		if (oldIndex < 0 || oldIndex >= size)
131
			throw new IndexOutOfBoundsException(
132
					"oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$
133
		if (newIndex < 0 || newIndex >= size)
134
			throw new IndexOutOfBoundsException(
135
					"newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$
136
137
		String[] items = getItems();
138
		String[] newItems = new String[size];
139
		String element = items[oldIndex];
140
		if (newItems.length > 0) {
141
			System.arraycopy(items, 0, newItems, 0, size);
142
			if (oldIndex < newIndex) {
143
				System.arraycopy(items, oldIndex + 1, newItems, oldIndex,
144
						newIndex - oldIndex);
145
			} else {
146
				System.arraycopy(items, newIndex, newItems, newIndex + 1,
147
						oldIndex - newIndex);
148
			}
149
			newItems[newIndex] = element;
150
		}
151
		setItems(newItems);
152
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(oldIndex,
153
				false, element), Diffs.createListDiffEntry(newIndex, true,
154
				element)));
155
		return element;
156
	}
157
158
	public boolean removeAll(Collection c) {
159
		checkRealm();
160
		List oldItems = Arrays.asList(getItems());
161
		List newItems = new ArrayList(oldItems);
162
		boolean removedAll = newItems.removeAll(c);
163
		if (removedAll) {
164
			setItems((String[]) newItems.toArray(new String[newItems.size()]));
165
			fireListChange(Diffs.computeListDiff(oldItems, newItems));
166
		}
167
		return removedAll;
168
	}
169
170
	public boolean retainAll(Collection c) {
171
		checkRealm();
172
		List oldItems = Arrays.asList(getItems());
173
		List newItems = new ArrayList(oldItems);
174
		boolean retainedAll = newItems.retainAll(c);
175
		if (retainedAll) {
176
			setItems((String[]) newItems.toArray(new String[newItems.size()]));
177
			fireListChange(Diffs.computeListDiff(oldItems, newItems));
178
		}
179
		return retainedAll;
180
	}
181
182
	/**
183
	 * @param index
184
	 * @param string
185
	 */
186
	protected abstract void setItem(int index, String string);
187
188
	/**
189
	 * @param newItems
190
	 */
191
	protected abstract void setItems(String[] newItems);
192
193
}
(-)src/org/eclipse/jface/internal/databinding/swt/TextEditableObservableValue.java (-75 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
17
import org.eclipse.swt.widgets.Text;
18
19
/**
20
 * Observable value for the editable property of a Text.
21
 * 
22
 * @since 1.1
23
 */
24
public class TextEditableObservableValue extends AbstractSWTObservableValue {
25
	private Text text;
26
	
27
	/**
28
	 * @param text
29
	 */
30
	public TextEditableObservableValue(Text text) {
31
		super(text);	
32
		this.text = text;
33
	}
34
	
35
	/**
36
	 * @param realm
37
	 * @param text
38
	 */
39
	public TextEditableObservableValue(Realm realm, Text text) {
40
		super(realm, text);
41
		this.text = text;
42
	}
43
44
	/* (non-Javadoc)
45
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#doGetValue()
46
	 */
47
	protected Object doGetValue() {
48
		return (text.getEditable()) ? Boolean.TRUE : Boolean.FALSE;
49
	}
50
	
51
	/* (non-Javadoc)
52
	 * @see org.eclipse.core.databinding.observable.value.IObservableValue#getValueType()
53
	 */
54
	public Object getValueType() {
55
		return Boolean.TYPE;
56
	}
57
	
58
	/* (non-Javadoc)
59
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#doSetValue(java.lang.Object)
60
	 */
61
	protected void doSetValue(Object value) {
62
		if (value == null) {
63
			throw new IllegalArgumentException("Parameter value was null."); //$NON-NLS-1$
64
		}
65
		
66
		Boolean oldValue = new Boolean(text.getEditable());
67
		Boolean newValue = (Boolean) value;
68
		
69
		text.setEditable(newValue.booleanValue());
70
		
71
		if (!oldValue.equals(newValue)) {
72
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));
73
		}
74
	}
75
}
(-)src/org/eclipse/jface/internal/databinding/swt/ComboObservableList.java (-51 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jface.internal.databinding.swt;
12
13
import org.eclipse.jface.databinding.swt.SWTObservables;
14
import org.eclipse.swt.widgets.Combo;
15
16
/**
17
 * @since 3.2
18
 * 
19
 */
20
public class ComboObservableList extends SWTObservableList {
21
22
	private final Combo combo;
23
24
	/**
25
	 * @param combo
26
	 */
27
	public ComboObservableList(Combo combo) {
28
		super(SWTObservables.getRealm(combo.getDisplay()));
29
		this.combo = combo;
30
	}
31
32
	protected int getItemCount() {
33
		return combo.getItemCount();
34
	}
35
36
	protected void setItems(String[] newItems) {
37
		combo.setItems(newItems);
38
	}
39
40
	protected String[] getItems() {
41
		return combo.getItems();
42
	}
43
44
	protected String getItem(int index) {
45
		return combo.getItem(index);
46
	}
47
48
	protected void setItem(int index, String string) {
49
		combo.setItem(index, string);
50
	}
51
}
(-)src/org/eclipse/jface/internal/databinding/swt/ItemObservableValue.java (-61 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jface.internal.databinding.swt;
12
13
import org.eclipse.core.databinding.observable.Diffs;
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
16
import org.eclipse.swt.widgets.Item;
17
18
/**
19
 * @since 3.5
20
 * 
21
 */
22
public class ItemObservableValue extends AbstractSWTObservableValue {
23
24
	private final Item item;
25
26
	/**
27
	 * @param item
28
	 */
29
	public ItemObservableValue(Item item) {
30
		super(item);
31
		this.item = item;
32
	}
33
	
34
	/**
35
	 * @param realm
36
	 * @param item
37
	 */
38
	public ItemObservableValue(Realm realm, Item item) {
39
		super(realm, item);
40
		this.item = item;
41
	}
42
43
	public void doSetValue(final Object value) {
44
		String oldValue = item.getText();
45
		String newValue = value == null ? "" : value.toString(); //$NON-NLS-1$
46
		item.setText(newValue);
47
		
48
		if (!newValue.equals(oldValue)) {
49
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));
50
		}
51
	}
52
53
	public Object doGetValue() {
54
		return item.getText();
55
	}
56
57
	public Object getValueType() {
58
		return String.class;
59
	}
60
61
}
(-)src/org/eclipse/jface/internal/databinding/swt/TextObservableValue.java (-198 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds (bug 135446)
11
 *     Brad Reynolds - bug 164653
12
 *******************************************************************************/
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.core.databinding.observable.Diffs;
16
import org.eclipse.core.databinding.observable.IObservable;
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.jface.databinding.swt.SWTObservables;
19
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTVetoableValue;
20
import org.eclipse.swt.SWT;
21
import org.eclipse.swt.events.VerifyEvent;
22
import org.eclipse.swt.events.VerifyListener;
23
import org.eclipse.swt.widgets.Event;
24
import org.eclipse.swt.widgets.Listener;
25
import org.eclipse.swt.widgets.Text;
26
27
/**
28
 * {@link IObservable} implementation that wraps a {@link Text} widget. The time
29
 * at which listeners should be notified about changes to the text is specified
30
 * 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
 * last value set using doSetValue(). Regardless of the update event type a
40
 * value changing event will fire on verify to enable vetoing of changes.</dd>
41
 * </dl>
42
 * 
43
 * @since 1.0
44
 */
45
public class TextObservableValue extends AbstractSWTVetoableValue {
46
47
	/**
48
	 * {@link Text} widget that this is being observed.
49
	 */
50
	private final Text text;
51
52
	/**
53
	 * Flag to track when the model is updating the widget. When
54
	 * <code>true</code> the handlers for the SWT events should not process
55
	 * the event as this would cause an infinite loop.
56
	 */
57
	private boolean updating = false;
58
59
	/**
60
	 * SWT event that on firing this observable will fire change events to its
61
	 * listeners.
62
	 */
63
	private final int updateEventType;
64
65
	/**
66
	 * Valid types for the {@link #updateEventType}.
67
	 */
68
	private static final int[] validUpdateEventTypes = new int[] { SWT.Modify,
69
			SWT.FocusOut, SWT.None };
70
71
	/**
72
	 * Previous value of the Text.
73
	 */
74
	private String oldValue;
75
76
	private Listener updateListener = new Listener() {
77
		public void handleEvent(Event event) {
78
			if (!updating) {
79
				String newValue = text.getText();
80
81
				if (!newValue.equals(oldValue)) {
82
					fireValueChange(Diffs.createValueDiff(oldValue, newValue));					
83
					oldValue = newValue;
84
				}
85
			}
86
		}
87
	};
88
89
	private VerifyListener verifyListener;
90
91
	/**
92
	 * Constructs a new instance bound to the given <code>text</code> widget
93
	 * and configured to fire change events to its listeners at the time of the
94
	 * <code>updateEventType</code>.
95
	 * 
96
	 * @param text
97
	 * @param updateEventType
98
	 *            SWT event constant as to what SWT event to update the model in
99
	 *            response to. Appropriate values are: <code>SWT.Modify</code>,
100
	 *            <code>SWT.FocusOut</code>, <code>SWT.None</code>.
101
	 * @throws IllegalArgumentException
102
	 *             if <code>updateEventType</code> is an incorrect type.
103
	 */
104
	public TextObservableValue(final Text text, int updateEventType) {
105
		this(SWTObservables.getRealm(text.getDisplay()), text, updateEventType);
106
	}
107
	
108
	/**
109
	 * Constructs a new instance.
110
	 * 
111
	 * @param realm can not be <code>null</code>
112
	 * @param text
113
	 * @param updateEventType
114
	 */
115
	public TextObservableValue(final Realm realm, Text text, int updateEventType) {
116
		super(realm, text);
117
		
118
		boolean eventValid = false;
119
		for (int i = 0; !eventValid && i < validUpdateEventTypes.length; i++) {
120
			eventValid = (updateEventType == validUpdateEventTypes[i]);
121
		}
122
		if (!eventValid) {
123
			throw new IllegalArgumentException(
124
					"UpdateEventType [" + updateEventType + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
125
		}
126
		this.text = text;
127
		this.updateEventType = updateEventType;
128
		if (updateEventType != SWT.None) {
129
			text.addListener(updateEventType, updateListener);
130
		}
131
		
132
		oldValue = text.getText();
133
		
134
		verifyListener = new VerifyListener() {
135
			public void verifyText(VerifyEvent e) {
136
				if (!updating) {
137
					String currentText = TextObservableValue.this.text
138
							.getText();
139
					String newText = currentText.substring(0, e.start) + e.text
140
							+ currentText.substring(e.end);
141
					if (!fireValueChanging(Diffs.createValueDiff(currentText,
142
							newText))) {
143
						e.doit = false;
144
					}
145
				}
146
			}
147
		};
148
		text.addVerifyListener(verifyListener);
149
	}
150
151
	/**
152
	 * Sets the bound {@link Text Text's} text to the passed <code>value</code>.
153
	 * 
154
	 * @param value
155
	 *            new value, String expected
156
	 * @see org.eclipse.core.databinding.observable.value.AbstractVetoableValue#doSetApprovedValue(java.lang.Object)
157
	 * @throws ClassCastException
158
	 *             if the value is anything other than a String
159
	 */
160
	protected void doSetApprovedValue(final Object value) {
161
		try {
162
			updating = true;
163
			text.setText(value == null ? "" : value.toString()); //$NON-NLS-1$
164
			oldValue = text.getText();
165
		} finally {
166
			updating = false;
167
		}
168
	}
169
170
	/**
171
	 * Returns the current value of the {@link Text}.
172
	 * 
173
	 * @see org.eclipse.core.databinding.observable.value.AbstractVetoableValue#doGetValue()
174
	 */
175
	public Object doGetValue() {
176
		return oldValue = text.getText();
177
	}
178
179
	/**
180
	 * Returns the type of the value from {@link #doGetValue()}, i.e.
181
	 * String.class
182
	 * 
183
	 * @see org.eclipse.core.databinding.observable.value.IObservableValue#getValueType()
184
	 */
185
	public Object getValueType() {
186
		return String.class;
187
	}
188
189
	public synchronized void dispose() {
190
		if (!text.isDisposed()) {
191
			if (updateEventType != SWT.None) {
192
				text.removeListener(updateEventType, updateListener);
193
			}
194
			text.removeVerifyListener(verifyListener);
195
		}
196
		super.dispose();
197
	}
198
}
(-)src/org/eclipse/jface/internal/databinding/swt/SpinnerObservableValue.java (-151 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bug 198904
12
 *     Matthew Hall - bug 118516
13
 *******************************************************************************/
14
package org.eclipse.jface.internal.databinding.swt;
15
16
import org.eclipse.core.databinding.observable.Diffs;
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.runtime.Assert;
19
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
20
import org.eclipse.swt.events.ModifyEvent;
21
import org.eclipse.swt.events.ModifyListener;
22
import org.eclipse.swt.widgets.Spinner;
23
24
/**
25
 * @since 1.0
26
 * 
27
 */
28
public class SpinnerObservableValue extends AbstractSWTObservableValue {
29
30
	private final Spinner spinner;
31
32
	private final String attribute;
33
34
	private boolean updating = false;
35
36
	private int currentSelection;
37
38
	private ModifyListener modifyListener;
39
40
	/**
41
	 * @param spinner
42
	 * @param attribute
43
	 */
44
	public SpinnerObservableValue(Spinner spinner, String attribute) {
45
		super(spinner);
46
		this.spinner = spinner;
47
		this.attribute = attribute;
48
		init();
49
	}
50
	
51
	/**
52
	 * @param realm
53
	 * @param spinner
54
	 * @param attribute
55
	 */
56
	public SpinnerObservableValue(Realm realm, Spinner spinner, String attribute) {
57
		super(realm, spinner);
58
		this.spinner = spinner;
59
		this.attribute = attribute;
60
		init();
61
	}
62
	
63
	private void init() {		
64
		if (attribute.equals(SWTProperties.SELECTION)) {
65
			currentSelection = spinner.getSelection();
66
			modifyListener = new ModifyListener() {
67
				public void modifyText(ModifyEvent e) {
68
					if (!updating) {
69
						int newSelection = SpinnerObservableValue.this.spinner
70
						.getSelection();
71
						notifyIfChanged(currentSelection, newSelection);
72
						currentSelection = newSelection;
73
					}
74
				}
75
			};
76
			spinner.addModifyListener(modifyListener);
77
		} else if (!attribute.equals(SWTProperties.MIN)
78
				&& !attribute.equals(SWTProperties.MAX)) {
79
			throw new IllegalArgumentException(
80
					"Attribute name not valid: " + attribute); //$NON-NLS-1$
81
		}
82
	}
83
84
	public void doSetValue(final Object value) {
85
		int oldValue;
86
		int newValue;
87
		try {
88
			updating = true;
89
			newValue = ((Integer) value).intValue();
90
			if (attribute.equals(SWTProperties.SELECTION)) {
91
				oldValue = spinner.getSelection();
92
				spinner.setSelection(newValue);
93
				currentSelection = newValue;
94
			} else if (attribute.equals(SWTProperties.MIN)) {
95
				oldValue = spinner.getMinimum();
96
				spinner.setMinimum(newValue);
97
			} else if (attribute.equals(SWTProperties.MAX)) {
98
				oldValue = spinner.getMaximum();
99
				spinner.setMaximum(newValue);
100
			} else {
101
				Assert.isTrue(false, "invalid attribute name:" + attribute); //$NON-NLS-1$
102
				return;
103
			}
104
			notifyIfChanged(oldValue, newValue);
105
		} finally {
106
			updating = false;
107
		}
108
	}
109
110
	public Object doGetValue() {
111
		int value = 0;
112
		if (attribute.equals(SWTProperties.SELECTION)) {
113
			value = spinner.getSelection();
114
		} else if (attribute.equals(SWTProperties.MIN)) {
115
			value = spinner.getMinimum();
116
		} else if (attribute.equals(SWTProperties.MAX)) {
117
			value = spinner.getMaximum();
118
		}
119
		return new Integer(value);
120
	}
121
122
	public Object getValueType() {
123
		return Integer.TYPE;
124
	}
125
126
	/**
127
	 * @return attribute being observed
128
	 */
129
	public String getAttribute() {
130
		return attribute;
131
	}
132
133
	/*
134
	 * (non-Javadoc)
135
	 *
136
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
137
	 */
138
	public synchronized void dispose() {
139
		super.dispose();
140
		if (modifyListener != null && !spinner.isDisposed()) {
141
			spinner.removeModifyListener(modifyListener);
142
		}
143
	}
144
	
145
	private void notifyIfChanged(int oldValue, int newValue) {
146
		if (oldValue != newValue) {
147
			fireValueChange(Diffs.createValueDiff(new Integer(oldValue),
148
					new Integer(newValue)));
149
		}
150
	}
151
}
(-)src/org/eclipse/jface/internal/databinding/swt/ListObservableList.java (-51 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jface.internal.databinding.swt;
12
13
import org.eclipse.jface.databinding.swt.SWTObservables;
14
import org.eclipse.swt.widgets.List;
15
16
/**
17
 * @since 3.2
18
 * 
19
 */
20
public class ListObservableList extends SWTObservableList {
21
22
	private final List list;
23
24
	/**
25
	 * @param list
26
	 */
27
	public ListObservableList(List list) {
28
		super(SWTObservables.getRealm(list.getDisplay()));
29
		this.list = list;
30
	}
31
32
	protected int getItemCount() {
33
		return list.getItemCount();
34
	}
35
36
	protected void setItems(String[] newItems) {
37
		list.setItems(newItems);
38
	}
39
40
	protected String[] getItems() {
41
		return list.getItems();
42
	}
43
44
	protected String getItem(int index) {
45
		return list.getItem(index);
46
	}
47
48
	protected void setItem(int index, String string) {
49
		list.setItem(index, string);
50
	}
51
}
(-)src/org/eclipse/jface/internal/databinding/swt/ItemTooltipObservableValue.java (-104 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jface.internal.databinding.swt;
12
13
import org.eclipse.core.databinding.observable.Diffs;
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
16
import org.eclipse.swt.custom.CTabItem;
17
import org.eclipse.swt.widgets.Item;
18
import org.eclipse.swt.widgets.TabItem;
19
import org.eclipse.swt.widgets.TableColumn;
20
import org.eclipse.swt.widgets.ToolItem;
21
import org.eclipse.swt.widgets.TrayItem;
22
import org.eclipse.swt.widgets.TreeColumn;
23
24
/**
25
 * @since 3.5
26
 * 
27
 */
28
public class ItemTooltipObservableValue extends AbstractSWTObservableValue {
29
30
	private final Item item;
31
32
	/**
33
	 * @param item
34
	 */
35
	public ItemTooltipObservableValue(Item item) {
36
		super(item);
37
		this.item = item;
38
	}
39
	
40
	/**
41
	 * @param realm
42
	 * @param item
43
	 */
44
	public ItemTooltipObservableValue(Realm realm, Item item) {
45
		super(realm, item);
46
		this.item = item;
47
	}
48
49
	public void doSetValue(final Object value) {
50
		String oldValue = (String) doGetValue();
51
52
		String newValue = value == null ? "" : value.toString(); //$NON-NLS-1$
53
		if (item instanceof CTabItem) {
54
			((CTabItem)item).setToolTipText(newValue);
55
		}
56
		else if (item instanceof TabItem) {
57
			((TabItem)item).setToolTipText(newValue);
58
		}
59
		else if (item instanceof TableColumn) {
60
			((TableColumn)item).setToolTipText(newValue);
61
		}
62
		else if (item instanceof ToolItem) {
63
			((ToolItem)item).setToolTipText(newValue);
64
		}
65
		else if (item instanceof TrayItem) {
66
			((TrayItem)item).setToolTipText(newValue);
67
		}
68
		else if (item instanceof TreeColumn) {
69
			((TreeColumn)item).setToolTipText(newValue);
70
		}
71
		
72
		if (!newValue.equals(oldValue)) {
73
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));
74
		}
75
	}
76
77
	public Object doGetValue() {
78
		if (item instanceof CTabItem) {
79
			return ((CTabItem)item).getToolTipText();
80
		}
81
		else if (item instanceof TabItem) {
82
			return ((TabItem)item).getToolTipText();
83
		}
84
		else if (item instanceof TableColumn) {
85
			return ((TableColumn)item).getToolTipText();
86
		}
87
		else if (item instanceof ToolItem) {
88
			return ((ToolItem)item).getToolTipText();
89
		}
90
		else if (item instanceof TrayItem) {
91
			return ((TrayItem)item).getToolTipText();
92
		}
93
		else if (item instanceof TreeColumn) {
94
			return ((TreeColumn)item).getToolTipText();
95
		}
96
		
97
		return null;
98
	}
99
100
	public Object getValueType() {
101
		return String.class;
102
	}
103
104
}
(-)src/org/eclipse/jface/internal/databinding/swt/SWTProperties.java (-97 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Matt Carter - bug 170668
11
 *     Brad Reynolds - bug 170848
12
 *******************************************************************************/
13
package org.eclipse.jface.internal.databinding.swt;
14
15
/**
16
 * Constants used to describe properties of SWT controls.
17
 * 
18
 * @since 1.0
19
 *
20
 */
21
public interface SWTProperties {
22
23
	/**
24
	 * Applies to Control
25
	 */
26
	public static final String ENABLED = "enabled"; //$NON-NLS-1$
27
	/**
28
	 * Applies to Control
29
	 */
30
	public static final String VISIBLE = "visible"; //$NON-NLS-1$
31
	/**
32
	 * Applies to Control
33
	 */
34
	public static final String TOOLTIP_TEXT = "tooltip"; //$NON-NLS-1$	
35
	/**
36
	 * Applies to
37
	 */
38
	public static final String ITEMS = "items"; //$NON-NLS-1$
39
	/**
40
	 * Applies to Spinner
41
	 */
42
	public static final String MAX = "max"; //$NON-NLS-1$
43
	/**
44
	 * Applies to Spinner
45
	 */
46
	public static final String MIN = "min"; //$NON-NLS-1$
47
	/**
48
	 * Applies to Spinner, Button
49
	 */
50
	public static final String SELECTION = "selection"; //$NON-NLS-1$
51
	/**
52
	 * Applies to Spinner, Button
53
	 */
54
	public static final String SELECTION_INDEX = "index"; //$NON-NLS-1$
55
	/**
56
	 * Applies to Text, Label, Combo
57
	 */
58
	public static final String TEXT = "text"; //$NON-NLS-1$
59
	
60
	/**
61
	 * Applies to Label, CLabel.
62
	 */
63
	public static final String IMAGE = "image"; //$NON-NLS-1$
64
	/**
65
	 * Applies to Control
66
	 */
67
	public static final String FOREGROUND = "foreground"; //$NON-NLS-1$
68
	/**
69
	 * Applies to Control
70
	 */
71
	public static final String BACKGROUND = "background"; //$NON-NLS-1$
72
	/**
73
	 * Applies to Control
74
	 */
75
	public static final String FONT = "font"; //$NON-NLS-1$
76
	
77
	/**
78
	 * Applies to Control 
79
	 */
80
	public static final String SIZE = "size";  //$NON-NLS-1$
81
	
82
	/**
83
	 * Applies to Control
84
	 */
85
	public static final String LOCATION = "location"; //$NON-NLS-1$
86
	
87
	/**
88
	 * Applies to Control
89
	 */
90
	public static final String FOCUS = "focus"; //$NON-NLS-1$
91
	
92
	/**
93
	 * Applies to Control
94
	 */
95
	public static final String BOUNDS = "bounds"; //$NON-NLS-1$
96
97
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlObservableValue.java (-283 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Matt Carter - bug 170668
12
 *     Brad Reynolds - bug 170848
13
 *******************************************************************************/
14
package org.eclipse.jface.internal.databinding.swt;
15
16
import java.util.HashMap;
17
import java.util.Map;
18
19
import org.eclipse.core.databinding.observable.Diffs;
20
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
22
import org.eclipse.jface.util.Util;
23
import org.eclipse.swt.events.ControlEvent;
24
import org.eclipse.swt.events.ControlListener;
25
import org.eclipse.swt.events.FocusEvent;
26
import org.eclipse.swt.events.FocusListener;
27
import org.eclipse.swt.graphics.Color;
28
import org.eclipse.swt.graphics.Font;
29
import org.eclipse.swt.graphics.Point;
30
import org.eclipse.swt.graphics.Rectangle;
31
import org.eclipse.swt.widgets.Control;
32
33
/**
34
 * @since 1.0
35
 * 
36
 */
37
public class ControlObservableValue extends AbstractSWTObservableValue {
38
39
	private final Control control;
40
41
	private final String attribute;
42
43
	private Object valueType;
44
	
45
	private FocusListener focusListener;
46
47
	private ControlListener controlListener;
48
49
	private Boolean currentFocus;
50
51
	private Point currentPoint;
52
53
	private Rectangle currentBounds;
54
55
	private boolean updating;
56
57
	
58
	private static final Map SUPPORTED_ATTRIBUTES = new HashMap();
59
	static {
60
		SUPPORTED_ATTRIBUTES.put(SWTProperties.ENABLED, Boolean.TYPE);
61
		SUPPORTED_ATTRIBUTES.put(SWTProperties.VISIBLE, Boolean.TYPE);
62
		SUPPORTED_ATTRIBUTES.put(SWTProperties.TOOLTIP_TEXT, String.class);
63
		SUPPORTED_ATTRIBUTES.put(SWTProperties.FOREGROUND, Color.class);
64
		SUPPORTED_ATTRIBUTES.put(SWTProperties.BACKGROUND, Color.class);
65
		SUPPORTED_ATTRIBUTES.put(SWTProperties.FONT, Font.class);
66
		SUPPORTED_ATTRIBUTES.put(SWTProperties.LOCATION, Point.class);
67
		SUPPORTED_ATTRIBUTES.put(SWTProperties.SIZE, Point.class);
68
		SUPPORTED_ATTRIBUTES.put(SWTProperties.FOCUS, Boolean.class);
69
		SUPPORTED_ATTRIBUTES.put(SWTProperties.BOUNDS, Rectangle.class);
70
	}
71
	
72
	/**
73
	 * @param control
74
	 * @param attribute
75
	 */
76
	public ControlObservableValue(Control control, String attribute) {
77
		super(control);
78
		this.control = control;
79
		this.attribute = attribute;
80
		if (SUPPORTED_ATTRIBUTES.keySet().contains(attribute)) {
81
			this.valueType = SUPPORTED_ATTRIBUTES.get(attribute); 
82
		} else {
83
			throw new IllegalArgumentException();
84
		}
85
		
86
		init();
87
	}
88
	
89
	/**
90
	 * @param realm 
91
	 * @param control
92
	 * @param attribute
93
	 */
94
	public ControlObservableValue(Realm realm, Control control, String attribute) {
95
		super(realm, control);
96
		this.control = control;
97
		this.attribute = attribute;
98
		if (SUPPORTED_ATTRIBUTES.keySet().contains(attribute)) {
99
			this.valueType = SUPPORTED_ATTRIBUTES.get(attribute); 
100
		} else {
101
			throw new IllegalArgumentException();
102
		}
103
		
104
		init();
105
	}
106
107
	private void init() {
108
		if (SWTProperties.SIZE.equals(attribute)
109
				|| SWTProperties.LOCATION.equals(attribute)
110
				|| SWTProperties.BOUNDS.equals(attribute)) {
111
			this.currentPoint = SWTProperties.SIZE.equals(attribute) ? control
112
					.getSize() : control.getLocation();
113
114
			controlListener = new ControlListener() {
115
116
				public void controlMoved(ControlEvent e) {
117
					if (SWTProperties.LOCATION.equals(attribute)) {
118
						if (!updating) {
119
							Point oldValue = currentPoint;
120
							currentPoint = control.getLocation();
121
122
							notifyIfChanged(oldValue, currentPoint);
123
						}
124
					} else if (SWTProperties.BOUNDS.equals(attribute)) {
125
						if (!updating) {
126
							Rectangle oldValue = currentBounds;
127
							currentBounds = control.getBounds();
128
129
							notifyIfChanged(oldValue, currentBounds);
130
						}
131
					}
132
				}
133
134
				public void controlResized(ControlEvent e) {
135
					if (SWTProperties.LOCATION.equals(attribute)) {
136
						if (!updating) {
137
							Point oldValue = currentPoint;
138
							currentPoint = control.getSize();
139
140
							notifyIfChanged(oldValue, currentPoint);
141
						}
142
					} else if (SWTProperties.BOUNDS.equals(attribute)) {
143
						if (!updating) {
144
							Rectangle oldValue = currentBounds;
145
							currentBounds = control.getBounds();
146
147
							notifyIfChanged(oldValue, currentBounds);
148
						}
149
					}
150
				}
151
			};
152
			control.addControlListener(controlListener);
153
		} else if (SWTProperties.FOCUS.equals(attribute)) {
154
			this.currentFocus = control == control.getDisplay()
155
					.getFocusControl() ? Boolean.TRUE : Boolean.FALSE;
156
			focusListener = new FocusListener() {
157
158
				public void focusGained(FocusEvent e) {
159
					if (!updating) {
160
						Boolean oldValue = currentFocus;
161
						currentFocus = Boolean.TRUE;
162
						notifyIfChanged(oldValue, currentFocus);
163
					}
164
				}
165
166
				public void focusLost(FocusEvent e) {
167
					if (!updating) {
168
						Boolean oldValue = currentFocus;
169
						currentFocus = Boolean.FALSE;
170
						notifyIfChanged(oldValue, currentFocus);
171
					}
172
				}
173
			};
174
			control.addFocusListener(focusListener);
175
		}
176
	}
177
	
178
	public void doSetValue(Object value) {
179
		Object oldValue = doGetValue();
180
		
181
		if (SWTProperties.SIZE.equals(attribute)) {
182
			try {
183
				updating = true;
184
				control.setSize((Point) value);
185
			} finally {
186
				updating = false;
187
				currentPoint = control.getSize();
188
			}
189
		} else if (SWTProperties.LOCATION.equals(attribute)) {
190
			try {
191
				updating = true;
192
				control.setLocation((Point) value);
193
			} finally {
194
				updating = false;
195
				currentPoint = control.getLocation();
196
			}
197
		} else if (SWTProperties.FOCUS.equals(attribute)) {
198
			try {
199
				updating = true;
200
				if (Boolean.TRUE.equals(value)) {
201
					currentFocus = control.setFocus() ? Boolean.TRUE
202
							: Boolean.FALSE;
203
				} else {
204
					// TODO Not possible force the focus to leave the control
205
					// Maybe focus should the move to the Shell containing the
206
					// control
207
					this.currentFocus = control == control.getDisplay()
208
							.getFocusControl() ? Boolean.TRUE : Boolean.FALSE;
209
				}
210
			} finally {
211
				updating = false;
212
			}
213
		} else if (SWTProperties.BOUNDS.equals(attribute)) {
214
			try {
215
				updating = true;
216
				control.setBounds((Rectangle) value);
217
			} finally {
218
				updating = false;
219
				currentBounds = control.getBounds();
220
			}
221
		} else if (attribute.equals(SWTProperties.ENABLED)) {
222
			control.setEnabled(((Boolean) value).booleanValue());
223
		} else if (attribute.equals(SWTProperties.VISIBLE)) {
224
			control.setVisible(((Boolean) value).booleanValue());
225
		} else if (attribute.equals(SWTProperties.TOOLTIP_TEXT)) {
226
			control.setToolTipText((String) value);
227
		} else if (attribute.equals(SWTProperties.FOREGROUND)) {
228
			control.setForeground((Color) value);
229
		} else if (attribute.equals(SWTProperties.BACKGROUND)) {
230
			control.setBackground((Color) value);
231
		} else if (attribute.equals(SWTProperties.FONT)) {
232
			control.setFont((Font) value);
233
		}
234
		
235
		notifyIfChanged(oldValue, value);
236
	}
237
238
	public Object doGetValue() {
239
		if (attribute.equals(SWTProperties.ENABLED)) {
240
			return control.getEnabled() ? Boolean.TRUE : Boolean.FALSE;
241
		}
242
		if (attribute.equals(SWTProperties.VISIBLE)) {
243
			return control.getVisible() ? Boolean.TRUE : Boolean.FALSE;
244
		}
245
		if (attribute.equals(SWTProperties.TOOLTIP_TEXT)) {
246
			return control.getToolTipText();			
247
		}
248
		if (attribute.equals(SWTProperties.FOREGROUND))	 {
249
			return control.getForeground();
250
		}
251
		if (attribute.equals(SWTProperties.BACKGROUND)) {
252
			return control.getBackground();
253
		}
254
		if (attribute.equals(SWTProperties.FONT)) {
255
			return control.getFont();
256
		}
257
		if (SWTProperties.SIZE.equals(attribute)) {
258
			return control.getSize();
259
		}
260
		if (SWTProperties.LOCATION.equals(attribute)) {
261
			return control.getLocation();
262
		}
263
		if (SWTProperties.FOCUS.equals(attribute)) {
264
			return control == control.getDisplay().getFocusControl() ? Boolean.TRUE
265
					: Boolean.FALSE;
266
		}
267
		if (SWTProperties.BOUNDS.equals(attribute)) {
268
			return control.getBounds();
269
		}
270
		
271
		return null;
272
	}
273
274
	public Object getValueType() {
275
		return valueType;
276
	}
277
	
278
	private void notifyIfChanged(Object oldValue, Object newValue) {
279
		if (!Util.equals(oldValue, newValue)) {
280
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));			
281
		}
282
	}
283
}
(-)src/org/eclipse/jface/internal/databinding/swt/CLabelObservableValue.java (-62 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *******************************************************************************/
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
17
import org.eclipse.swt.custom.CLabel;
18
19
/**
20
 * @since 1.0
21
 * 
22
 */
23
public class CLabelObservableValue extends AbstractSWTObservableValue {
24
25
	private final CLabel label;
26
27
	/**
28
	 * @param label
29
	 */
30
	public CLabelObservableValue(CLabel label) {
31
		super(label);
32
		this.label = label;
33
	}
34
	
35
	/**
36
	 * @param realm
37
	 * @param label
38
	 */
39
	public CLabelObservableValue(Realm realm, CLabel label) {
40
		super(realm, label);
41
		this.label = label;
42
	}
43
44
	public void doSetValue(final Object value) {
45
		String oldValue = label.getText();
46
		String newValue = value == null ? "" : value.toString();  //$NON-NLS-1$
47
		label.setText(newValue);
48
49
		if (!newValue.equals(oldValue)) {
50
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));
51
		}
52
	}
53
54
	public Object doGetValue() {
55
		return label.getText();
56
	}
57
58
	public Object getValueType() {
59
		return String.class;
60
	}
61
62
}
(-)src/org/eclipse/jface/internal/databinding/swt/SWTObservableValueDecorator.java (-1 / +1 lines)
Lines 6-12 Link Here
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Matthew Hall - initial API and implementation (bug 245647)
9
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
10
 ******************************************************************************/
11
11
12
package org.eclipse.jface.internal.databinding.swt;
12
package org.eclipse.jface.internal.databinding.swt;
(-)src/org/eclipse/jface/internal/databinding/swt/SingleSelectionObservableValue.java (-103 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *******************************************************************************/
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
17
import org.eclipse.swt.widgets.Control;
18
19
/**
20
 * @since 1.0
21
 * 
22
 */
23
abstract public class SingleSelectionObservableValue extends
24
		AbstractSWTObservableValue {
25
26
	private boolean updating = false;
27
28
	private int currentSelection;
29
30
	/**
31
	 * @param control
32
	 *            the control
33
	 */
34
	public SingleSelectionObservableValue(Control control) {
35
		super(control);
36
		init();
37
	}
38
	
39
	/**
40
	 * @param realm
41
	 * @param control
42
	 */
43
	public SingleSelectionObservableValue(Realm realm, Control control) {
44
		super(realm, control);
45
		init();
46
	}
47
	
48
	private void init() {		
49
		currentSelection = doGetSelectionIndex();
50
		doAddSelectionListener(new Runnable(){
51
			public void run() {
52
				if (!updating) {
53
					int newSelection = doGetSelectionIndex();
54
					notifyIfChanged(currentSelection, newSelection);
55
					currentSelection = newSelection;
56
				}
57
			}
58
		});
59
	}
60
61
	/**
62
	 * @param runnable
63
	 */
64
	protected abstract void doAddSelectionListener(Runnable runnable);
65
66
	public void doSetValue(Object value) {
67
		try {
68
			updating = true;
69
			int intValue = ((Integer) value).intValue();
70
			doSetSelectionIndex(intValue);
71
			notifyIfChanged(currentSelection, intValue);
72
			currentSelection = intValue;
73
		} finally {
74
			updating = false;
75
		}
76
	}
77
78
	/**
79
	 * @param intValue
80
	 *            the selection index
81
	 */
82
	protected abstract void doSetSelectionIndex(int intValue);
83
84
	public Object doGetValue() {
85
		return new Integer(doGetSelectionIndex());
86
	}
87
88
	/**
89
	 * @return the selection index
90
	 */
91
	protected abstract int doGetSelectionIndex();
92
93
	public Object getValueType() {
94
		return Integer.TYPE;
95
	}
96
97
	private void notifyIfChanged(int oldValue, int newValue) {
98
		if (oldValue != newValue) {
99
			fireValueChange(Diffs.createValueDiff(new Integer(
100
					oldValue), new Integer(newValue)));
101
		}
102
	}
103
}
(-)src/org/eclipse/jface/internal/databinding/swt/ButtonObservableValue.java (-110 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bug 198904
12
 *******************************************************************************/
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.core.databinding.observable.Diffs;
16
import org.eclipse.core.databinding.observable.Realm;
17
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
18
import org.eclipse.swt.SWT;
19
import org.eclipse.swt.widgets.Button;
20
import org.eclipse.swt.widgets.Event;
21
import org.eclipse.swt.widgets.Listener;
22
23
/**
24
 * @since 1.0
25
 * 
26
 */
27
public class ButtonObservableValue extends AbstractSWTObservableValue {
28
29
	private final Button button;
30
31
	private boolean selectionValue;
32
33
	private Listener updateListener = new Listener() {
34
		public void handleEvent(Event event) {
35
			boolean oldSelectionValue = selectionValue;
36
			selectionValue = button.getSelection();
37
						
38
			notifyIfChanged(oldSelectionValue, selectionValue);
39
		}
40
	};
41
42
	/**
43
	 * @param button
44
	 */
45
	public ButtonObservableValue(Button button) {
46
		super(button);
47
		this.button = button;
48
		init();
49
	}
50
	
51
	/**
52
	 * @param realm
53
	 * @param button
54
	 */
55
	public ButtonObservableValue(Realm realm, Button button) {
56
		super(realm, button);
57
		this.button = button;
58
		init();
59
	}
60
	
61
	private void init() {
62
		button.addListener(SWT.Selection, updateListener);
63
		button.addListener(SWT.DefaultSelection, updateListener);
64
		this.selectionValue = button.getSelection();
65
	}
66
67
	public void doSetValue(final Object value) {
68
		boolean oldSelectionValue = selectionValue;
69
		selectionValue = value == null ? false : ((Boolean) value)
70
				.booleanValue();
71
		
72
		button.setSelection(selectionValue);
73
		notifyIfChanged(oldSelectionValue, selectionValue);
74
	}
75
76
	public Object doGetValue() {
77
		return button.getSelection() ? Boolean.TRUE : Boolean.FALSE;
78
	}
79
80
	public Object getValueType() {
81
		return Boolean.TYPE;
82
	}
83
	
84
	/*
85
	 * (non-Javadoc)
86
	 *
87
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
88
	 */
89
	public synchronized void dispose() {
90
		super.dispose();
91
92
		if (!button.isDisposed()) {
93
			button.removeListener(SWT.Selection, updateListener);
94
			button.removeListener(SWT.DefaultSelection, updateListener);
95
		}
96
	}
97
98
	/**
99
	 * Notifies consumers with a value change event only if a change occurred.
100
	 * 
101
	 * @param oldValue
102
	 * @param newValue
103
	 */
104
	private void notifyIfChanged(boolean oldValue, boolean newValue) {
105
		if (oldValue != newValue) {
106
			fireValueChange(Diffs.createValueDiff(oldValue ? Boolean.TRUE : Boolean.FALSE,
107
					newValue ? Boolean.TRUE : Boolean.FALSE));
108
		}		
109
	}
110
}
(-)src/org/eclipse/jface/internal/databinding/swt/ComboObservableValue.java (-155 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bug 198904
12
 *     Matthew Hall - bug 118516
13
 *******************************************************************************/
14
package org.eclipse.jface.internal.databinding.swt;
15
16
import org.eclipse.core.databinding.observable.Diffs;
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.runtime.Assert;
19
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
20
import org.eclipse.swt.events.ModifyEvent;
21
import org.eclipse.swt.events.ModifyListener;
22
import org.eclipse.swt.widgets.Combo;
23
24
/**
25
 * @since 3.2
26
 * 
27
 */
28
public class ComboObservableValue extends AbstractSWTObservableValue {
29
30
	private final Combo combo;
31
	private final String attribute;
32
	private boolean updating = false;
33
	private String currentValue;
34
	private ModifyListener modifyListener;
35
36
	/**
37
	 * @param combo
38
	 * @param attribute
39
	 */
40
	public ComboObservableValue(Combo combo, String attribute) {
41
		super(combo);
42
		this.combo = combo;
43
		this.attribute = attribute;
44
		init();
45
	}
46
		
47
	/**
48
	 * @param realm
49
	 * @param combo
50
	 * @param attribute
51
	 */
52
	public ComboObservableValue(Realm realm, Combo combo, String attribute) {
53
		super(realm, combo);
54
		this.combo = combo;
55
		this.attribute = attribute;
56
		init();
57
	}
58
	
59
	private void init() {		
60
		if (attribute.equals(SWTProperties.SELECTION)
61
				|| attribute.equals(SWTProperties.TEXT)) {
62
			this.currentValue = combo.getText();
63
			modifyListener = new ModifyListener() {
64
65
				public void modifyText(ModifyEvent e) {
66
					if (!updating) {
67
						String oldValue = currentValue;
68
						currentValue = ComboObservableValue.this.combo
69
								.getText();
70
						
71
						notifyIfChanged(oldValue, currentValue);
72
					}
73
				}
74
			};
75
			combo.addModifyListener(modifyListener);
76
		} else
77
			throw new IllegalArgumentException();
78
	}
79
80
	public void doSetValue(final Object value) {
81
		String oldValue = combo.getText();
82
		try {
83
			updating = true;
84
			if (attribute.equals(SWTProperties.TEXT)) {
85
				String stringValue = value != null ? value.toString() : ""; //$NON-NLS-1$
86
				combo.setText(stringValue);
87
			} else if (attribute.equals(SWTProperties.SELECTION)) {
88
				String items[] = combo.getItems();
89
				int index = -1;
90
				if (items != null && value != null) {
91
					for (int i = 0; i < items.length; i++) {
92
						if (value.equals(items[i])) {
93
							index = i;
94
							break;
95
						}
96
					}
97
					if (index == -1) {
98
						combo.setText((String) value);
99
					} else {
100
						combo.select(index); // -1 will not "unselect"
101
					}
102
				}
103
			}
104
		} finally {
105
			updating = false;
106
			currentValue = combo.getText();
107
		}
108
		
109
		notifyIfChanged(oldValue, currentValue);
110
	}
111
112
	public Object doGetValue() {
113
		if (attribute.equals(SWTProperties.TEXT))
114
			return combo.getText();
115
116
		Assert.isTrue(attribute.equals(SWTProperties.SELECTION),
117
				"unexpected attribute: " + attribute); //$NON-NLS-1$
118
		// The problem with a ccombo, is that it changes the text and
119
		// fires before it update its selection index
120
		return combo.getText();
121
	}
122
123
	public Object getValueType() {
124
		Assert.isTrue(attribute.equals(SWTProperties.TEXT)
125
				|| attribute.equals(SWTProperties.SELECTION),
126
				"unexpected attribute: " + attribute); //$NON-NLS-1$
127
		return String.class;
128
	}
129
130
	/**
131
	 * @return attribute being observed
132
	 */
133
	public String getAttribute() {
134
		return attribute;
135
	}
136
137
	/*
138
	 * (non-Javadoc)
139
	 *
140
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
141
	 */
142
	public synchronized void dispose() {
143
		super.dispose();
144
145
		if (modifyListener != null && !combo.isDisposed()) {
146
			combo.removeModifyListener(modifyListener);
147
		}
148
	}
149
	
150
	private void notifyIfChanged(String oldValue, String newValue) {
151
		if (!oldValue.equals(newValue)) {
152
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));
153
		}
154
	}
155
}
(-)src/org/eclipse/jface/internal/databinding/swt/LabelObservableValue.java (-62 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *******************************************************************************/
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
17
import org.eclipse.swt.widgets.Label;
18
19
/**
20
 * @since 3.3
21
 * 
22
 */
23
public class LabelObservableValue extends AbstractSWTObservableValue {
24
25
	private final Label label;
26
27
	/**
28
	 * @param label
29
	 */
30
	public LabelObservableValue(Label label) {
31
		super(label);
32
		this.label = label;
33
	}
34
	
35
	/**
36
	 * @param realm
37
	 * @param label
38
	 */
39
	public LabelObservableValue(Realm realm, Label label) {
40
		super(realm, label);
41
		this.label = label;
42
	}
43
44
	public void doSetValue(final Object value) {
45
		String oldValue = label.getText();
46
		String newValue = value == null ? "" : value.toString(); //$NON-NLS-1$
47
		label.setText(newValue);
48
		
49
		if (!newValue.equals(oldValue)) {
50
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));
51
		}
52
	}
53
54
	public Object doGetValue() {
55
		return label.getText();
56
	}
57
58
	public Object getValueType() {
59
		return String.class;
60
	}
61
62
}
(-)src/org/eclipse/jface/internal/databinding/swt/ComboSingleSelectionObservableValue.java (-71 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bugs 198903, 198904
12
 *******************************************************************************/
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.swt.events.SelectionEvent;
16
import org.eclipse.swt.events.SelectionListener;
17
import org.eclipse.swt.widgets.Combo;
18
19
/**
20
 * @since 1.0
21
 *
22
 */
23
public class ComboSingleSelectionObservableValue extends
24
		SingleSelectionObservableValue {
25
26
	private SelectionListener selectionListener;
27
28
	/**
29
	 * @param combo
30
	 */
31
	public ComboSingleSelectionObservableValue(Combo combo) {
32
		super(combo);
33
	}
34
35
	private Combo getCombo() {
36
		return (Combo) getWidget();
37
	}
38
39
	protected void doAddSelectionListener(final Runnable runnable) {
40
		selectionListener = new SelectionListener() {
41
			public void widgetDefaultSelected(SelectionEvent e) {
42
				runnable.run();
43
			}
44
45
			public void widgetSelected(SelectionEvent e) {
46
				runnable.run();
47
			}
48
		};
49
		getCombo().addSelectionListener(selectionListener);
50
	}
51
52
	protected int doGetSelectionIndex() {
53
		return getCombo().getSelectionIndex();
54
	}
55
56
	protected void doSetSelectionIndex(int index) {
57
		getCombo().select(index);
58
	}
59
60
	/*
61
	 * (non-Javadoc)
62
	 *
63
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
64
	 */
65
	public synchronized void dispose() {
66
		super.dispose();
67
		if (selectionListener != null && !getCombo().isDisposed()) {
68
			getCombo().removeSelectionListener(selectionListener);
69
		}
70
	}
71
}
(-)src/org/eclipse/jface/internal/databinding/swt/ListSingleSelectionObservableValue.java (-71 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Ashley Cambrell - bug 198904
12
 *******************************************************************************/
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.swt.events.SelectionEvent;
16
import org.eclipse.swt.events.SelectionListener;
17
import org.eclipse.swt.widgets.List;
18
19
/**
20
 * @since 1.0
21
 * 
22
 */
23
public class ListSingleSelectionObservableValue extends
24
		SingleSelectionObservableValue {
25
26
	private SelectionListener selectionListener;
27
28
	/**
29
	 * @param combo
30
	 */
31
	public ListSingleSelectionObservableValue(List combo) {
32
		super(combo);
33
	}
34
35
	private List getList() {
36
		return (List) getWidget();
37
	}
38
39
	protected void doAddSelectionListener(final Runnable runnable) {
40
		selectionListener = new SelectionListener() {
41
			public void widgetDefaultSelected(SelectionEvent e) {
42
				runnable.run();
43
			}
44
45
			public void widgetSelected(SelectionEvent e) {
46
				runnable.run();
47
			}
48
		};
49
		getList().addSelectionListener(selectionListener);
50
	}
51
52
	protected int doGetSelectionIndex() {
53
		return getList().getSelectionIndex();
54
	}
55
56
	protected void doSetSelectionIndex(int index) {
57
		getList().setSelection(index);
58
	}
59
60
	/*
61
	 * (non-Javadoc)
62
	 *
63
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
64
	 */
65
	public synchronized void dispose() {
66
		super.dispose();
67
		if (selectionListener != null && !getList().isDisposed()) {
68
			getList().removeSelectionListener(selectionListener);
69
		}
70
	}
71
}
(-)src/org/eclipse/jface/databinding/viewers/ViewersObservables.java (-76 / +43 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 206839, 124684, 239302, 245647
10
 *     Matthew Hall - bug 206839, 124684, 239302, 245647, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.databinding.viewers;
13
package org.eclipse.jface.databinding.viewers;
Lines 16-32 Link Here
16
import org.eclipse.core.databinding.observable.list.IObservableList;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
17
import org.eclipse.core.databinding.observable.set.IObservableSet;
17
import org.eclipse.core.databinding.observable.set.IObservableSet;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.jface.databinding.swt.SWTObservables;
20
import org.eclipse.jface.internal.databinding.swt.SWTDelayedObservableValueDecorator;
21
import org.eclipse.jface.internal.databinding.viewers.CheckableCheckedElementsObservableSet;
22
import org.eclipse.jface.internal.databinding.viewers.CheckboxViewerCheckedElementsObservableSet;
23
import org.eclipse.jface.internal.databinding.viewers.SelectionProviderMultipleSelectionObservableList;
24
import org.eclipse.jface.internal.databinding.viewers.SelectionProviderSingleSelectionObservableValue;
25
import org.eclipse.jface.internal.databinding.viewers.ViewerFiltersObservableSet;
26
import org.eclipse.jface.internal.databinding.viewers.ViewerInputObservableValue;
27
import org.eclipse.jface.internal.databinding.viewers.ViewerMultipleSelectionObservableList;
28
import org.eclipse.jface.internal.databinding.viewers.ViewerObservableValueDecorator;
19
import org.eclipse.jface.internal.databinding.viewers.ViewerObservableValueDecorator;
29
import org.eclipse.jface.internal.databinding.viewers.ViewerSingleSelectionObservableValue;
30
import org.eclipse.jface.viewers.CheckboxTableViewer;
20
import org.eclipse.jface.viewers.CheckboxTableViewer;
31
import org.eclipse.jface.viewers.CheckboxTreeViewer;
21
import org.eclipse.jface.viewers.CheckboxTreeViewer;
32
import org.eclipse.jface.viewers.ICheckable;
22
import org.eclipse.jface.viewers.ICheckable;
Lines 34-40 Link Here
34
import org.eclipse.jface.viewers.IStructuredSelection;
24
import org.eclipse.jface.viewers.IStructuredSelection;
35
import org.eclipse.jface.viewers.StructuredViewer;
25
import org.eclipse.jface.viewers.StructuredViewer;
36
import org.eclipse.jface.viewers.Viewer;
26
import org.eclipse.jface.viewers.Viewer;
37
import org.eclipse.swt.widgets.Display;
38
27
39
/**
28
/**
40
 * Factory methods for creating observables for JFace viewers
29
 * Factory methods for creating observables for JFace viewers
Lines 42-47 Link Here
42
 * @since 1.1
31
 * @since 1.1
43
 */
32
 */
44
public class ViewersObservables {
33
public class ViewersObservables {
34
	private static Object checkNull(Object obj) {
35
		if (obj == null)
36
			throw new IllegalArgumentException();
37
		return obj;
38
	}
39
45
	/**
40
	/**
46
	 * Returns an observable which delays notification of value change events
41
	 * Returns an observable which delays notification of value change events
47
	 * from <code>observable</code> until <code>delay</code> milliseconds have
42
	 * from <code>observable</code> until <code>delay</code> milliseconds have
Lines 65-75 Link Here
65
	 */
60
	 */
66
	public static IViewerObservableValue observeDelayedValue(int delay,
61
	public static IViewerObservableValue observeDelayedValue(int delay,
67
			IViewerObservableValue observable) {
62
			IViewerObservableValue observable) {
68
		Viewer viewer = observable.getViewer();
63
		return new ViewerObservableValueDecorator(Observables
69
		return new ViewerObservableValueDecorator(
64
				.observeDelayedValue(delay, observable), observable.getViewer());
70
				new SWTDelayedObservableValueDecorator(Observables
71
						.observeDelayedValue(delay, observable), viewer
72
						.getControl()), viewer);
73
	}
65
	}
74
66
75
	/**
67
	/**
Lines 85-110 Link Here
85
	 */
77
	 */
86
	public static IObservableValue observeSingleSelection(
78
	public static IObservableValue observeSingleSelection(
87
			ISelectionProvider selectionProvider) {
79
			ISelectionProvider selectionProvider) {
88
		if (selectionProvider instanceof Viewer) {
80
		return ViewerProperties.singleSelection().observe(
89
			return observeSingleSelection((Viewer) selectionProvider);
81
				checkNull(selectionProvider));
90
		}
91
		return new SelectionProviderSingleSelectionObservableValue(
92
				SWTObservables.getRealm(Display.getDefault()),
93
				selectionProvider);
94
	}
82
	}
95
83
96
	/**
84
	/**
97
	 * Returns an observable list that tracks the current selection of the
85
	 * Returns an observable list that tracks the current selection of the given
98
	 * given selection provider. Assumes that the selection provider provides
86
	 * selection provider. Assumes that the selection provider provides
99
	 * selections of type {@link IStructuredSelection}. Note that the
87
	 * selections of type {@link IStructuredSelection}. Note that the observable
100
	 * observable list will not honor the full contract of
88
	 * list will not honor the full contract of <code>java.util.List</code> in
101
	 * <code>java.util.List</code> in that it may delete or reorder elements
89
	 * that it may delete or reorder elements based on what the selection
102
	 * based on what the selection provider returns from
90
	 * provider returns from {@link ISelectionProvider#getSelection()} after
103
	 * {@link ISelectionProvider#getSelection()} after having called
91
	 * having called
104
	 * {@link ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)}
92
	 * {@link ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)}
105
	 * based on the requested change to the observable list. The affected
93
	 * based on the requested change to the observable list. The affected
106
	 * methods are <code>add</code>, <code>addAll</code>, and
94
	 * methods are <code>add</code>, <code>addAll</code>, and <code>set</code>.
107
	 * <code>set</code>.
108
	 * 
95
	 * 
109
	 * @param selectionProvider
96
	 * @param selectionProvider
110
	 * @return the observable value tracking the (multi) selection of the given
97
	 * @return the observable value tracking the (multi) selection of the given
Lines 114-125 Link Here
114
	 */
101
	 */
115
	public static IObservableList observeMultiSelection(
102
	public static IObservableList observeMultiSelection(
116
			ISelectionProvider selectionProvider) {
103
			ISelectionProvider selectionProvider) {
117
		if (selectionProvider instanceof Viewer) {
104
		return ViewerProperties.multipleSelection().observe(
118
			return observeMultiSelection((Viewer) selectionProvider);
105
				checkNull(selectionProvider));
119
		}
120
		return new SelectionProviderMultipleSelectionObservableList(
121
				SWTObservables.getRealm(Display.getDefault()),
122
				selectionProvider, Object.class);
123
	}
106
	}
124
107
125
	/**
108
	/**
Lines 136-158 Link Here
136
	 * @since 1.2
119
	 * @since 1.2
137
	 */
120
	 */
138
	public static IViewerObservableValue observeSingleSelection(Viewer viewer) {
121
	public static IViewerObservableValue observeSingleSelection(Viewer viewer) {
139
		return new ViewerSingleSelectionObservableValue(
122
		return (IViewerObservableValue) ViewerProperties.singleSelection()
140
				SWTObservables.getRealm(Display.getDefault()),
123
				.observe(checkNull(viewer));
141
				viewer);
142
	}
124
	}
143
	
125
144
	/**
126
	/**
145
	 * Returns an observable list that tracks the current selection of the
127
	 * Returns an observable list that tracks the current selection of the given
146
	 * given viewer. Assumes that the viewer provides
128
	 * viewer. Assumes that the viewer provides selections of type
147
	 * selections of type {@link IStructuredSelection}. Note that the
129
	 * {@link IStructuredSelection}. Note that the observable list will not
148
	 * observable list will not honor the full contract of
130
	 * honor the full contract of <code>java.util.List</code> in that it may
149
	 * <code>java.util.List</code> in that it may delete or reorder elements
131
	 * delete or reorder elements based on what the viewer returns from
150
	 * based on what the viewer returns from
151
	 * {@link ISelectionProvider#getSelection()} after having called
132
	 * {@link ISelectionProvider#getSelection()} after having called
152
	 * {@link ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)}
133
	 * {@link ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)}
153
	 * based on the requested change to the observable list. The affected
134
	 * based on the requested change to the observable list. The affected
154
	 * methods are <code>add</code>, <code>addAll</code>, and
135
	 * methods are <code>add</code>, <code>addAll</code>, and <code>set</code>.
155
	 * <code>set</code>.
156
	 * 
136
	 * 
157
	 * @param viewer
137
	 * @param viewer
158
	 * @return the observable value tracking the (multi) selection of the given
138
	 * @return the observable value tracking the (multi) selection of the given
Lines 160-172 Link Here
160
	 * 
140
	 * 
161
	 * @since 1.2
141
	 * @since 1.2
162
	 */
142
	 */
163
	public static IViewerObservableList observeMultiSelection(
143
	public static IViewerObservableList observeMultiSelection(Viewer viewer) {
164
			Viewer viewer) {
144
		return (IViewerObservableList) ViewerProperties.multipleSelection()
165
		return new ViewerMultipleSelectionObservableList(
145
				.observe(checkNull(viewer));
166
				SWTObservables.getRealm(Display.getDefault()),
167
				viewer, Object.class);
168
	}
146
	}
169
	
147
170
	/**
148
	/**
171
	 * Returns an observable value that tracks the input of the given viewer.
149
	 * Returns an observable value that tracks the input of the given viewer.
172
	 * <p>
150
	 * <p>
Lines 179-186 Link Here
179
	 * @since 1.2
157
	 * @since 1.2
180
	 */
158
	 */
181
	public static IObservableValue observeInput(Viewer viewer) {
159
	public static IObservableValue observeInput(Viewer viewer) {
182
		return new ViewerInputObservableValue(SWTObservables.getRealm(viewer
160
		return ViewerProperties.input().observe(checkNull(viewer));
183
				.getControl().getDisplay()), viewer);
184
	}
161
	}
185
162
186
	/**
163
	/**
Lines 197-212 Link Here
197
	 */
174
	 */
198
	public static IObservableSet observeCheckedElements(ICheckable checkable,
175
	public static IObservableSet observeCheckedElements(ICheckable checkable,
199
			Object elementType) {
176
			Object elementType) {
200
		if (checkable instanceof CheckboxTableViewer) {
177
		return ViewerProperties.checkedElements(elementType).observe(
201
			return observeCheckedElements((CheckboxTableViewer) checkable,
178
				checkNull(checkable));
202
					elementType);
203
		}
204
		if (checkable instanceof CheckboxTreeViewer) {
205
			return observeCheckedElements((CheckboxTreeViewer) checkable,
206
					elementType);
207
		}
208
		return new CheckableCheckedElementsObservableSet(SWTObservables
209
				.getRealm(Display.getDefault()), checkable, elementType);
210
	}
179
	}
211
180
212
	/**
181
	/**
Lines 224-232 Link Here
224
	 */
193
	 */
225
	public static IViewerObservableSet observeCheckedElements(
194
	public static IViewerObservableSet observeCheckedElements(
226
			CheckboxTableViewer viewer, Object elementType) {
195
			CheckboxTableViewer viewer, Object elementType) {
227
		return new CheckboxViewerCheckedElementsObservableSet(SWTObservables
196
		return (IViewerObservableSet) ViewerProperties.checkedElements(
228
				.getRealm(viewer.getControl().getDisplay()), viewer,
197
				elementType).observe(checkNull(viewer));
229
				elementType);
230
	}
198
	}
231
199
232
	/**
200
	/**
Lines 244-252 Link Here
244
	 */
212
	 */
245
	public static IViewerObservableSet observeCheckedElements(
213
	public static IViewerObservableSet observeCheckedElements(
246
			CheckboxTreeViewer viewer, Object elementType) {
214
			CheckboxTreeViewer viewer, Object elementType) {
247
		return new CheckboxViewerCheckedElementsObservableSet(SWTObservables
215
		return (IViewerObservableSet) ViewerProperties.checkedElements(
248
				.getRealm(viewer.getControl().getDisplay()), viewer,
216
				elementType).observe(checkNull(viewer));
249
				elementType);
250
	}
217
	}
251
218
252
	/**
219
	/**
Lines 267-273 Link Here
267
	 * @since 1.3
234
	 * @since 1.3
268
	 */
235
	 */
269
	public static IViewerObservableSet observeFilters(StructuredViewer viewer) {
236
	public static IViewerObservableSet observeFilters(StructuredViewer viewer) {
270
		return new ViewerFiltersObservableSet(SWTObservables.getRealm(viewer
237
		return (IViewerObservableSet) ViewerProperties.filters().observe(
271
				.getControl().getDisplay()), viewer);
238
				checkNull(viewer));
272
	}
239
	}
273
}
240
}
(-)src/org/eclipse/jface/internal/databinding/internal/swt/LinkObservableValue.java (-47 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Michael Krauter, Catuno GmbH 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
 *     Michael Krauter, Catuno GmbH - initial API and implementation (bug 180223)
10
 *******************************************************************************/
11
package org.eclipse.jface.internal.databinding.internal.swt;
12
13
import org.eclipse.core.databinding.observable.Diffs;
14
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
15
import org.eclipse.swt.widgets.Link;
16
17
/**
18
 * @since 1.2
19
 * 
20
 */
21
public class LinkObservableValue extends AbstractSWTObservableValue {
22
23
	private final Link link;
24
25
	/**
26
	 * @param link
27
	 */
28
	public LinkObservableValue(Link link) {
29
		super(link);
30
		this.link = link;
31
	}
32
33
	public void doSetValue(final Object value) {
34
		String oldValue = link.getText();
35
		link.setText(value == null ? "" : value.toString()); //$NON-NLS-1$
36
		fireValueChange(Diffs.createValueDiff(oldValue, link.getText()));
37
	}
38
39
	public Object doGetValue() {
40
		return link.getText();
41
	}
42
43
	public Object getValueType() {
44
		return String.class;
45
	}
46
47
}
(-)src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderMultipleSelectionObservableList.java (-111 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Peter Centgraf 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
 *     Peter Centgraf - initial API and implementation, bug 124683
10
 *     Boris Bokowski, IBM Corporation - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import java.util.ArrayList;
15
import java.util.Collections;
16
import java.util.List;
17
18
import org.eclipse.core.databinding.observable.Diffs;
19
import org.eclipse.core.databinding.observable.Realm;
20
import org.eclipse.core.databinding.observable.list.ListDiff;
21
import org.eclipse.core.databinding.observable.list.WritableList;
22
import org.eclipse.jface.viewers.ISelection;
23
import org.eclipse.jface.viewers.ISelectionChangedListener;
24
import org.eclipse.jface.viewers.ISelectionProvider;
25
import org.eclipse.jface.viewers.IStructuredSelection;
26
import org.eclipse.jface.viewers.SelectionChangedEvent;
27
import org.eclipse.jface.viewers.StructuredSelection;
28
29
/**
30
 * Observes multiple-selection of an {@link ISelectionProvider}.
31
 * 
32
 * @since 1.2
33
 */
34
public class SelectionProviderMultipleSelectionObservableList extends
35
		WritableList {
36
37
	protected ISelectionProvider selectionProvider;
38
	protected boolean handlingSelection;
39
	protected boolean updating;
40
	protected SelectionListener selectionListener = new SelectionListener();
41
42
	class SelectionListener implements ISelectionChangedListener {
43
		public void selectionChanged(SelectionChangedEvent event) {
44
			if (updating) {
45
				return;
46
			}
47
			handlingSelection = true;
48
			try {
49
				updateWrappedList(new ArrayList(getSelectionList(event.getSelection())));
50
			} finally {
51
				handlingSelection = false;
52
			}
53
		}
54
	}
55
56
	/**
57
	 * Create a new observable list based on the current selection of the given
58
	 * selection provider. Assumes that the selection provider provides
59
	 * structured selections.
60
	 * 
61
	 * @param realm
62
	 * @param selectionProvider
63
	 * @param elementType
64
	 */
65
	public SelectionProviderMultipleSelectionObservableList(Realm realm,
66
			ISelectionProvider selectionProvider, Object elementType) {
67
		super(realm, new ArrayList(getSelectionList(selectionProvider)), elementType);
68
		this.selectionProvider = selectionProvider;
69
		selectionProvider.addSelectionChangedListener(selectionListener);
70
	}
71
72
	protected void fireListChange(ListDiff diff) {
73
		if (handlingSelection) {
74
			super.fireListChange(diff);
75
		} else {
76
			// this is a bit of a hack - we are changing the diff to match the order
77
			// of elements returned by the selection provider after we've set the
78
			// selection.
79
			updating = true;
80
			try {
81
				List oldList = getSelectionList(selectionProvider);
82
				selectionProvider
83
						.setSelection(new StructuredSelection(wrappedList));
84
				wrappedList = new ArrayList(getSelectionList(selectionProvider));
85
				super.fireListChange(Diffs.computeListDiff(oldList, wrappedList));
86
			} finally {
87
				updating = false;
88
			}
89
		}
90
	}
91
92
	protected static List getSelectionList(ISelectionProvider selectionProvider) {
93
		if (selectionProvider == null) {
94
			throw new IllegalArgumentException();
95
		}
96
		return getSelectionList(selectionProvider.getSelection());
97
	}
98
99
	protected static List getSelectionList(ISelection sel) {
100
		if (sel instanceof IStructuredSelection) {
101
			return ((IStructuredSelection) sel).toList();
102
		}
103
		return Collections.EMPTY_LIST;
104
	}
105
106
	public synchronized void dispose() {
107
		selectionProvider.removeSelectionChangedListener(selectionListener);
108
		selectionProvider = null;
109
		super.dispose();
110
	}
111
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerMultipleSelectionObservableList.java (-47 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 137877
11
 *     Brad Reynolds - bug 164653
12
 *     Brad Reynolds - bug 147515
13
 *     Ashley Cambrell - bug 198906
14
 *******************************************************************************/
15
16
package org.eclipse.jface.internal.databinding.viewers;
17
18
import org.eclipse.core.databinding.observable.Realm;
19
import org.eclipse.jface.databinding.viewers.IViewerObservableList;
20
import org.eclipse.jface.viewers.Viewer;
21
22
/**
23
 * Observes single selection of a <code>Viewer</code>.
24
 * 
25
 * @since 1.2
26
 */
27
public class ViewerMultipleSelectionObservableList extends
28
		SelectionProviderMultipleSelectionObservableList implements
29
		IViewerObservableList {
30
31
	private Viewer viewer;
32
33
	/**
34
	 * @param realm
35
	 * @param viewer
36
	 * @param elementType
37
	 */
38
	public ViewerMultipleSelectionObservableList(Realm realm, Viewer viewer,
39
			Object elementType) {
40
		super(realm, viewer, elementType);
41
		this.viewer = viewer;
42
	}
43
44
	public Viewer getViewer() {
45
		return viewer;
46
	}
47
}
(-)src/org/eclipse/jface/internal/databinding/viewers/CheckboxViewerCheckedElementsObservableSet.java (-90 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 124684)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import java.util.Arrays;
15
import java.util.Set;
16
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.jface.databinding.viewers.IViewerObservableSet;
19
import org.eclipse.jface.viewers.CheckboxTableViewer;
20
import org.eclipse.jface.viewers.CheckboxTreeViewer;
21
import org.eclipse.jface.viewers.StructuredViewer;
22
import org.eclipse.jface.viewers.Viewer;
23
24
/**
25
 * An observable set that tracks the checked elements in a CheckboxTableViewer
26
 * or CheckboxTreeViewer
27
 * 
28
 * @since 1.2
29
 */
30
public class CheckboxViewerCheckedElementsObservableSet extends
31
		CheckableCheckedElementsObservableSet implements IViewerObservableSet {
32
	private StructuredViewer viewer;
33
34
	/**
35
	 * Constructs a new instance on the given realm and checkable.
36
	 * 
37
	 * @param realm
38
	 *            the observable's realm
39
	 * @param viewer
40
	 *            the CheckboxTableViewer viewer to track.
41
	 * @param elementType
42
	 *            type of elements in the set
43
	 */
44
	public CheckboxViewerCheckedElementsObservableSet(Realm realm,
45
			CheckboxTableViewer viewer, Object elementType) {
46
		super(realm, viewer, elementType, createElementSet(viewer));
47
		this.viewer = viewer;
48
	}
49
50
	/**
51
	 * Constructs a new instance on the given realm and checkable.
52
	 * 
53
	 * @param realm
54
	 *            the observable's realm
55
	 * @param viewer
56
	 *            the CheckboxTreeViewer viewer to track.
57
	 * @param elementType
58
	 *            type of elements in the set
59
	 */
60
	public CheckboxViewerCheckedElementsObservableSet(Realm realm,
61
			CheckboxTreeViewer viewer, Object elementType) {
62
		super(realm, viewer, elementType, createElementSet(viewer));
63
		this.viewer = viewer;
64
	}
65
66
	Set createDiffSet() {
67
		return ViewerElementSet.withComparer(viewer.getComparer());
68
	}
69
70
	private static Set createElementSet(CheckboxTableViewer viewer) {
71
		Set set = ViewerElementSet.withComparer(viewer.getComparer());
72
		set.addAll(Arrays.asList(viewer.getCheckedElements()));
73
		return set;
74
	}
75
76
	private static Set createElementSet(CheckboxTreeViewer viewer) {
77
		Set set = ViewerElementSet.withComparer(viewer.getComparer());
78
		set.addAll(Arrays.asList(viewer.getCheckedElements()));
79
		return set;
80
	}
81
82
	public Viewer getViewer() {
83
		return viewer;
84
	}
85
86
	public synchronized void dispose() {
87
		viewer = null;
88
		super.dispose();
89
	}
90
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerFiltersObservableSet.java (-174 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 239302)
10
 *******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import java.util.Arrays;
15
import java.util.Collection;
16
import java.util.Collections;
17
import java.util.HashSet;
18
import java.util.Iterator;
19
import java.util.Set;
20
21
import org.eclipse.core.databinding.observable.Diffs;
22
import org.eclipse.core.databinding.observable.Realm;
23
import org.eclipse.core.databinding.observable.set.ObservableSet;
24
import org.eclipse.jface.databinding.viewers.IViewerObservableSet;
25
import org.eclipse.jface.viewers.StructuredViewer;
26
import org.eclipse.jface.viewers.Viewer;
27
import org.eclipse.jface.viewers.ViewerFilter;
28
29
/**
30
 * An observable set that tracks the filters of the given viewer. Note that this
31
 * set will not track changes that are made using direct API on StructuredViewer
32
 * (by calling
33
 * {@link StructuredViewer#addFilter(org.eclipse.jface.viewers.ViewerFilter)
34
 * addFilter()},
35
 * {@link StructuredViewer#removeFilter(org.eclipse.jface.viewers.ViewerFilter)
36
 * removeFilter()}, or
37
 * {@link StructuredViewer#setFilters(org.eclipse.jface.viewers.ViewerFilter[])
38
 * setFilters()}) -- it is assumed that filters are only changed through the
39
 * set.
40
 * 
41
 * @since 1.2
42
 */
43
public class ViewerFiltersObservableSet extends ObservableSet implements
44
		IViewerObservableSet {
45
46
	private StructuredViewer viewer;
47
48
	/**
49
	 * @param realm
50
	 * @param viewer
51
	 */
52
	public ViewerFiltersObservableSet(Realm realm, StructuredViewer viewer) {
53
		super(realm, new HashSet(Arrays.asList(viewer.getFilters())),
54
				ViewerFilter.class);
55
		this.viewer = viewer;
56
	}
57
58
	public Viewer getViewer() {
59
		return viewer;
60
	}
61
62
	private void replaceFilters() {
63
		viewer.getControl().setRedraw(false);
64
		try {
65
			viewer.setFilters((ViewerFilter[]) wrappedSet
66
					.toArray(new ViewerFilter[wrappedSet.size()]));
67
		} finally {
68
			viewer.getControl().setRedraw(true);
69
		}
70
	}
71
72
	private void addFilter(ViewerFilter filter) {
73
		viewer.getControl().setRedraw(false);
74
		try {
75
			viewer.addFilter(filter);
76
		} finally {
77
			viewer.getControl().setRedraw(true);
78
		}
79
	}
80
81
	private void removeFilter(ViewerFilter filter) {
82
		viewer.getControl().setRedraw(false);
83
		try {
84
			viewer.removeFilter(filter);
85
		} finally {
86
			viewer.getControl().setRedraw(true);
87
		}
88
	}
89
90
	public boolean add(Object element) {
91
		checkRealm();
92
		boolean added = wrappedSet.add(element);
93
		if (added) {
94
			addFilter((ViewerFilter) element);
95
			fireSetChange(Diffs.createSetDiff(Collections.singleton(element),
96
					Collections.EMPTY_SET));
97
		}
98
		return added;
99
	}
100
101
	public boolean addAll(Collection c) {
102
		getterCalled();
103
		Set additions = new HashSet();
104
		Iterator it = c.iterator();
105
		while (it.hasNext()) {
106
			Object element = it.next();
107
			if (wrappedSet.add(element)) {
108
				additions.add(element);
109
			}
110
		}
111
		if (additions.size() > 0) {
112
			replaceFilters();
113
			fireSetChange(Diffs.createSetDiff(additions, Collections.EMPTY_SET));
114
			return true;
115
		}
116
		return false;
117
	}
118
119
	public void clear() {
120
		getterCalled();
121
		Set removes = new HashSet(wrappedSet);
122
		wrappedSet.clear();
123
		replaceFilters();
124
		fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removes));
125
	}
126
127
	public boolean remove(Object o) {
128
		getterCalled();
129
		boolean removed = wrappedSet.remove(o);
130
		if (removed) {
131
			removeFilter((ViewerFilter) o);
132
			fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
133
					Collections.singleton(o)));
134
		}
135
		return removed;
136
	}
137
138
	public boolean removeAll(Collection c) {
139
		getterCalled();
140
		Set removes = new HashSet();
141
		Iterator it = c.iterator();
142
		while (it.hasNext()) {
143
			Object element = it.next();
144
			if (wrappedSet.remove(element)) {
145
				removes.add(element);
146
			}
147
		}
148
		if (removes.size() > 0) {
149
			replaceFilters();
150
			fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removes));
151
			return true;
152
		}
153
		return false;
154
	}
155
156
	public boolean retainAll(Collection c) {
157
		getterCalled();
158
		Set removes = new HashSet();
159
		Iterator it = wrappedSet.iterator();
160
		while (it.hasNext()) {
161
			Object element = it.next();
162
			if (!c.contains(element)) {
163
				it.remove();
164
				removes.add(element);
165
			}
166
		}
167
		if (removes.size() > 0) {
168
			replaceFilters();
169
			fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removes));
170
			return true;
171
		}
172
		return false;
173
	}
174
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerSingleSelectionObservableValue.java (-45 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 137877
11
 *     Brad Reynolds - bug 164653
12
 *     Brad Reynolds - bug 147515
13
 *     Ashley Cambrell - bug 198906
14
 *******************************************************************************/
15
16
package org.eclipse.jface.internal.databinding.viewers;
17
18
import org.eclipse.core.databinding.observable.Realm;
19
import org.eclipse.jface.databinding.viewers.IViewerObservableValue;
20
import org.eclipse.jface.viewers.Viewer;
21
22
/**
23
 * Observes single selection of a <code>Viewer</code>.
24
 * 
25
 * @since 1.2
26
 */
27
public class ViewerSingleSelectionObservableValue extends
28
		SelectionProviderSingleSelectionObservableValue implements
29
		IViewerObservableValue {
30
31
	private Viewer viewer;
32
33
	/**
34
	 * @param realm
35
	 * @param viewer
36
	 */
37
	public ViewerSingleSelectionObservableValue(Realm realm, Viewer viewer) {
38
		super(realm, viewer);
39
		this.viewer = viewer;
40
	}
41
42
	public Viewer getViewer() {
43
		return viewer;
44
	}
45
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerInputObservableValue.java (-73 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 206839)
10
 *******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
17
import org.eclipse.jface.util.Util;
18
import org.eclipse.jface.viewers.Viewer;
19
20
/**
21
 * Observes the input of a <code>Viewer</code>.
22
 * <p>
23
 * This observer is blind to changes in the viewer's input unless its
24
 * {@link #setValue(Object)} method is called directly.
25
 * 
26
 * @since 1.2
27
 */
28
public class ViewerInputObservableValue extends AbstractObservableValue {
29
30
  private final Viewer viewer;
31
32
  /**
33
   * Constructs a new instance associated with the provided <code>viewer</code>.
34
   * 
35
   * @param realm
36
   * @param viewer
37
   */
38
  public ViewerInputObservableValue( Realm realm, Viewer viewer ) {
39
    super( realm );
40
    if ( viewer == null ) {
41
      throw new IllegalArgumentException( "The 'viewer' parameter is null." ); //$NON-NLS-1$
42
    }
43
44
    this.viewer = viewer;
45
  }
46
47
  /**
48
   * Sets the input to the provided <code>value</code>. Value change events are
49
   * fired after input is set in the viewer.
50
   * 
51
   * @param value object to set as input
52
   */
53
  protected void doSetValue( final Object value ) {
54
    Object oldValue = doGetValue();
55
    viewer.setInput( value );
56
    if ( !Util.equals( oldValue, value ) ) {
57
      fireValueChange( Diffs.createValueDiff( oldValue, value ) );
58
    }
59
  }
60
61
  /**
62
   * Retrieves the current input.
63
   * 
64
   * @return the current input
65
   */
66
  protected Object doGetValue() {
67
    return viewer.getInput();
68
  }
69
70
  public Object getValueType() {
71
    return null;
72
  }
73
}
(-)src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderSingleSelectionObservableValue.java (-147 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 137877
11
 *     Brad Reynolds - bug 164653
12
 *     Brad Reynolds - bug 147515
13
 *     Ashley Cambrell - bug 198906
14
 *******************************************************************************/
15
16
package org.eclipse.jface.internal.databinding.viewers;
17
18
import org.eclipse.core.databinding.observable.Diffs;
19
import org.eclipse.core.databinding.observable.Realm;
20
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
21
import org.eclipse.jface.util.Util;
22
import org.eclipse.jface.viewers.ISelection;
23
import org.eclipse.jface.viewers.ISelectionChangedListener;
24
import org.eclipse.jface.viewers.ISelectionProvider;
25
import org.eclipse.jface.viewers.IStructuredSelection;
26
import org.eclipse.jface.viewers.SelectionChangedEvent;
27
import org.eclipse.jface.viewers.StructuredSelection;
28
29
/**
30
 * Observes single selection of an <code>ISelectionProvider</code>.
31
 *
32
 * @since 1.1
33
 */
34
public class SelectionProviderSingleSelectionObservableValue extends
35
		AbstractObservableValue {
36
37
	private final ISelectionProvider selectionProvider;
38
39
	private boolean updating = false;
40
41
	private Object currentSelection;
42
43
	private ISelectionChangedListener selectionChangedListener;
44
45
	/**
46
	 * Constructs a new instance associated with the provided
47
	 * <code>selectionProvider</code>. In order to initialize itself properly
48
	 * the constructor invokes {@link #doGetValue()}. This could be dangerous
49
	 * for subclasses, see {@link #doGetValue()} for an explanation.
50
	 *
51
	 * @param realm
52
	 *
53
	 * @param selectionProvider
54
	 * @see #doGetValue()
55
	 */
56
	public SelectionProviderSingleSelectionObservableValue(Realm realm,
57
			ISelectionProvider selectionProvider) {
58
		super(realm);
59
		if (selectionProvider == null) {
60
			throw new IllegalArgumentException(
61
					"The 'selectionProvider' parameter is null."); //$NON-NLS-1$
62
		}
63
64
		this.selectionProvider = selectionProvider;
65
		this.currentSelection = doGetValue();
66
67
		selectionChangedListener = new ISelectionChangedListener() {
68
			public void selectionChanged(SelectionChangedEvent event) {
69
				if (!updating) {
70
					Object oldSelection = currentSelection;
71
					currentSelection = doGetValue();
72
					fireValueChange(Diffs.createValueDiff(oldSelection,
73
							currentSelection));
74
				}
75
			}
76
		};
77
		selectionProvider.addSelectionChangedListener(selectionChangedListener);
78
	}
79
80
	/**
81
	 * Sets the selection to the provided <code>value</code>. Value change
82
	 * events are fired after selection is set in the selection provider.
83
	 *
84
	 * @param value
85
	 *            object to set as selected, <code>null</code> if wanting to
86
	 *            remove selection
87
	 */
88
	public void doSetValue(final Object value) {
89
		try {
90
			updating = true;
91
92
			Object oldSelection = currentSelection;
93
			selectionProvider
94
					.setSelection(value == null ? StructuredSelection.EMPTY
95
							: new StructuredSelection(value));
96
			currentSelection = doGetValue();
97
			if (!Util.equals(oldSelection, currentSelection)) {
98
				fireValueChange(Diffs.createValueDiff(oldSelection,
99
						currentSelection));
100
			}
101
		} finally {
102
			updating = false;
103
		}
104
	}
105
106
	/**
107
	 * Retrieves the current selection.
108
	 * <p>
109
	 * If a subclass overrides this method it must not depend upon the subclass
110
	 * to have been fully initialized before this method is invoked.
111
	 * <code>doGetValue()</code> is invoked by the
112
	 * {@link #SelectionProviderSingleSelectionObservableValue(Realm, ISelectionProvider) constructor}
113
	 * which means the subclass's constructor will not have fully executed
114
	 * before this method is invoked.
115
	 * </p>
116
	 *
117
	 * @return selection will be an instance of
118
	 *         <code>IStructuredSelection</code> if a selection exists,
119
	 *         <code>null</code> if no selection
120
	 * @see #SelectionProviderSingleSelectionObservableValue(Realm,
121
	 *      ISelectionProvider)
122
	 */
123
	protected Object doGetValue() {
124
		ISelection selection = selectionProvider.getSelection();
125
		if (selection instanceof IStructuredSelection) {
126
			IStructuredSelection sel = (IStructuredSelection) selection;
127
			return sel.getFirstElement();
128
		}
129
130
		return null;
131
	}
132
133
	public Object getValueType() {
134
		return null;
135
	}
136
137
	/*
138
	 * (non-Javadoc)
139
	 *
140
	 * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#dispose()
141
	 */
142
	public synchronized void dispose() {
143
		selectionProvider
144
				.removeSelectionChangedListener(selectionChangedListener);
145
		super.dispose();
146
	}
147
}
(-)src/org/eclipse/jface/internal/databinding/viewers/CheckableCheckedElementsObservableSet.java (-219 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 124684)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.Set;
19
20
import org.eclipse.core.databinding.observable.Diffs;
21
import org.eclipse.core.databinding.observable.Realm;
22
import org.eclipse.core.databinding.observable.set.AbstractObservableSet;
23
import org.eclipse.core.runtime.Assert;
24
import org.eclipse.jface.viewers.CheckStateChangedEvent;
25
import org.eclipse.jface.viewers.ICheckStateListener;
26
import org.eclipse.jface.viewers.ICheckable;
27
28
/**
29
 * 
30
 * @since 1.2
31
 */
32
public class CheckableCheckedElementsObservableSet extends
33
		AbstractObservableSet {
34
	private ICheckable checkable;
35
	private Set wrappedSet;
36
	private Object elementType;
37
	private ICheckStateListener listener;
38
39
	/**
40
	 * Constructs a new instance on the given realm and checkable.
41
	 * 
42
	 * @param realm
43
	 *            the observable's realm
44
	 * @param checkable
45
	 *            the ICheckable to track
46
	 * @param elementType
47
	 *            type of elements in the set
48
	 */
49
	public CheckableCheckedElementsObservableSet(Realm realm,
50
			ICheckable checkable, Object elementType) {
51
		this(realm, checkable, elementType, new HashSet());
52
	}
53
54
	/**
55
	 * Constructs a new instance of the given realm, and checkable,
56
	 * 
57
	 * @param realm
58
	 *            the observable's realm
59
	 * @param checkable
60
	 *            the ICheckable to track
61
	 * @param elementType
62
	 *            type of elements in the set
63
	 * @param wrappedSet
64
	 *            the set being wrapped
65
	 */
66
	public CheckableCheckedElementsObservableSet(Realm realm,
67
			ICheckable checkable, Object elementType, final Set wrappedSet) {
68
		super(realm);
69
		Assert.isNotNull(checkable, "Checkable cannot be null"); //$NON-NLS-1$
70
		Assert.isNotNull(wrappedSet, "Wrapped set cannot be null"); //$NON-NLS-1$
71
		this.checkable = checkable;
72
		this.wrappedSet = wrappedSet;
73
		this.elementType = elementType;
74
75
		listener = new ICheckStateListener() {
76
			public void checkStateChanged(CheckStateChangedEvent event) {
77
				Object element = event.getElement();
78
				if (event.getChecked()) {
79
					if (wrappedSet.add(element))
80
						fireSetChange(Diffs.createSetDiff(Collections
81
								.singleton(element), Collections.EMPTY_SET));
82
				} else {
83
					if (wrappedSet.remove(element))
84
						fireSetChange(Diffs.createSetDiff(
85
								Collections.EMPTY_SET, Collections
86
										.singleton(element)));
87
				}
88
			}
89
		};
90
		checkable.addCheckStateListener(listener);
91
	}
92
93
	protected Set getWrappedSet() {
94
		return wrappedSet;
95
	}
96
97
	Set createDiffSet() {
98
		return new HashSet();
99
	}
100
101
	public Object getElementType() {
102
		return elementType;
103
	}
104
105
	public boolean add(Object o) {
106
		getterCalled();
107
		boolean added = wrappedSet.add(o);
108
		if (added) {
109
			checkable.setChecked(o, true);
110
			fireSetChange(Diffs.createSetDiff(Collections.singleton(o),
111
					Collections.EMPTY_SET));
112
		}
113
		return added;
114
	}
115
116
	public boolean remove(Object o) {
117
		getterCalled();
118
		boolean removed = wrappedSet.remove(o);
119
		if (removed) {
120
			checkable.setChecked(o, false);
121
			fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
122
					Collections.singleton(o)));
123
		}
124
		return removed;
125
	}
126
127
	public boolean addAll(Collection c) {
128
		getterCalled();
129
		Set additions = createDiffSet();
130
		for (Iterator iterator = c.iterator(); iterator.hasNext();) {
131
			Object element = iterator.next();
132
			if (wrappedSet.add(element)) {
133
				checkable.setChecked(element, true);
134
				additions.add(element);
135
			}
136
		}
137
		boolean changed = !additions.isEmpty();
138
		if (changed)
139
			fireSetChange(Diffs.createSetDiff(additions, Collections.EMPTY_SET));
140
		return changed;
141
	}
142
143
	public boolean removeAll(Collection c) {
144
		getterCalled();
145
		Set removals = createDiffSet();
146
		for (Iterator iterator = c.iterator(); iterator.hasNext();) {
147
			Object element = iterator.next();
148
			if (wrappedSet.remove(element)) {
149
				checkable.setChecked(element, false);
150
				removals.add(element);
151
			}
152
		}
153
		boolean changed = !removals.isEmpty();
154
		if (changed)
155
			fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
156
		return changed;
157
	}
158
159
	public boolean retainAll(Collection c) {
160
		getterCalled();
161
162
		// To ensure that elements are compared correctly, e.g. ViewerElementSet
163
		Set toRetain = createDiffSet();
164
		toRetain.addAll(c);
165
166
		Set removals = createDiffSet();
167
		for (Iterator iterator = wrappedSet.iterator(); iterator.hasNext();) {
168
			Object element = iterator.next();
169
			if (!toRetain.contains(element)) {
170
				iterator.remove();
171
				checkable.setChecked(element, false);
172
				removals.add(element);
173
			}
174
		}
175
		boolean changed = !removals.isEmpty();
176
		if (changed)
177
			fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
178
		return changed;
179
	}
180
181
	public void clear() {
182
		removeAll(wrappedSet);
183
	}
184
185
	public Iterator iterator() {
186
		getterCalled();
187
		final Iterator wrappedIterator = wrappedSet.iterator();
188
		return new Iterator() {
189
			private Object last = null;
190
191
			public boolean hasNext() {
192
				getterCalled();
193
				return wrappedIterator.hasNext();
194
			}
195
196
			public Object next() {
197
				getterCalled();
198
				return last = wrappedIterator.next();
199
			}
200
201
			public void remove() {
202
				getterCalled();
203
				wrappedIterator.remove();
204
				checkable.setChecked(last, false);
205
				fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
206
						Collections.singleton(last)));
207
			}
208
		};
209
	}
210
211
	public synchronized void dispose() {
212
		if (checkable != null) {
213
			checkable.removeCheckStateListener(listener);
214
			checkable = null;
215
			listener = null;
216
		}
217
		super.dispose();
218
	}
219
}
(-)src/org/eclipse/jface/internal/databinding/provisional/swt/AbstractSWTObservableValue.java (-69 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 The Pampered Chef, Inc. 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
 *     The Pampered Chef, Inc. - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.provisional.swt;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
16
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
17
import org.eclipse.jface.databinding.swt.SWTObservables;
18
import org.eclipse.swt.events.DisposeEvent;
19
import org.eclipse.swt.events.DisposeListener;
20
import org.eclipse.swt.widgets.Widget;
21
22
/**
23
 * NON-API - An abstract superclass for observable values that gurantees that the 
24
 * observable will be disposed when the control to which it is attached is
25
 * disposed.
26
 * 
27
 * @since 1.1
28
 */
29
public abstract class AbstractSWTObservableValue extends AbstractObservableValue implements ISWTObservableValue {
30
31
	private final Widget widget;
32
33
	/**
34
	 * Standard constructor for an SWT ObservableValue.  Makes sure that
35
	 * the observable gets disposed when the SWT widget is disposed.
36
	 * 
37
	 * @param widget
38
	 */
39
	protected AbstractSWTObservableValue(Widget widget) {
40
		this(SWTObservables.getRealm(widget.getDisplay()), widget);
41
	}
42
	
43
	/**
44
	 * Constructor that allows for the setting of the realm. Makes sure that the
45
	 * observable gets disposed when the SWT widget is disposed.
46
	 * 
47
	 * @param realm
48
	 * @param widget
49
	 * @since 1.2
50
	 */
51
	protected AbstractSWTObservableValue(Realm realm, Widget widget) {
52
		super(realm);
53
		this.widget = widget;
54
		widget.addDisposeListener(disposeListener);
55
	}
56
	
57
	private DisposeListener disposeListener = new DisposeListener() {
58
		public void widgetDisposed(DisposeEvent e) {
59
			AbstractSWTObservableValue.this.dispose();
60
		}
61
	};
62
63
	/**
64
	 * @return Returns the widget.
65
	 */
66
	public Widget getWidget() {
67
		return widget;
68
	}
69
}
(-)src/org/eclipse/jface/internal/databinding/provisional/swt/AbstractSWTVetoableValue.java (-71 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 The Pampered Chef, Inc. 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
 *     The Pampered Chef, Inc. - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.provisional.swt;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.value.AbstractVetoableValue;
16
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
17
import org.eclipse.jface.databinding.swt.SWTObservables;
18
import org.eclipse.swt.events.DisposeEvent;
19
import org.eclipse.swt.events.DisposeListener;
20
import org.eclipse.swt.widgets.Widget;
21
22
/**
23
 * NON-API - An abstract superclass for vetoable values that gurantees that the 
24
 * observable will be disposed when the control to which it is attached is
25
 * disposed.
26
 * 
27
 * @since 1.1
28
 */
29
public abstract class AbstractSWTVetoableValue extends AbstractVetoableValue implements ISWTObservableValue {
30
31
	private final Widget widget;
32
33
	/**
34
	 * Standard constructor for an SWT VetoableValue.  Makes sure that
35
	 * the observable gets disposed when the SWT widget is disposed.
36
	 * 
37
	 * @param widget
38
	 */
39
	protected AbstractSWTVetoableValue(Widget widget) {
40
		this(SWTObservables.getRealm(widget.getDisplay()), widget);
41
	}
42
	
43
	/**
44
	 * Constructs a new instance for the provided <code>realm</code> and <code>widget</code>.
45
	 * 
46
	 * @param realm
47
	 * @param widget
48
	 * @since 1.2
49
	 */
50
	protected AbstractSWTVetoableValue(Realm realm, Widget widget) {
51
		super(realm);
52
		this.widget = widget;
53
		if (widget == null) {
54
			throw new IllegalArgumentException("The widget parameter is null."); //$NON-NLS-1$
55
		}
56
		widget.addDisposeListener(disposeListener);
57
	}
58
	
59
	private DisposeListener disposeListener = new DisposeListener() {
60
		public void widgetDisposed(DisposeEvent e) {
61
			AbstractSWTVetoableValue.this.dispose();
62
		}
63
	};
64
65
	/**
66
	 * @return Returns the widget.
67
	 */
68
	public Widget getWidget() {
69
		return widget;
70
	}
71
}
(-)src/org/eclipse/jface/databinding/swt/SWTObservables.java (-182 / +85 lines)
Lines 9-17 Link Here
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matt Carter - bug 170668
10
 *     Matt Carter - bug 170668
11
 *     Brad Reynolds - bug 170848
11
 *     Brad Reynolds - bug 170848
12
 *     Matthew Hall - bugs 180746, 207844, 245647, 248621, 232917
12
 *     Matthew Hall - bugs 180746, 207844, 245647, 248621, 232917, 194734,
13
 *                    195222
13
 *     Michael Krauter - bug 180223
14
 *     Michael Krauter - bug 180223
14
 *     Boris Bokowski - bug 245647
15
 *     Boris Bokowski - bug 245647
16
 *     Tom Schindl - bug 246462
15
 *******************************************************************************/
17
 *******************************************************************************/
16
package org.eclipse.jface.databinding.swt;
18
package org.eclipse.jface.databinding.swt;
17
19
Lines 24-82 Link Here
24
import org.eclipse.core.databinding.observable.value.IObservableValue;
26
import org.eclipse.core.databinding.observable.value.IObservableValue;
25
import org.eclipse.core.databinding.observable.value.IVetoableValue;
27
import org.eclipse.core.databinding.observable.value.IVetoableValue;
26
import org.eclipse.core.databinding.observable.value.ValueChangingEvent;
28
import org.eclipse.core.databinding.observable.value.ValueChangingEvent;
27
import org.eclipse.jface.internal.databinding.internal.swt.LinkObservableValue;
28
import org.eclipse.jface.internal.databinding.swt.ButtonObservableValue;
29
import org.eclipse.jface.internal.databinding.swt.CComboObservableList;
30
import org.eclipse.jface.internal.databinding.swt.CComboObservableValue;
31
import org.eclipse.jface.internal.databinding.swt.CComboSingleSelectionObservableValue;
32
import org.eclipse.jface.internal.databinding.swt.CLabelObservableValue;
33
import org.eclipse.jface.internal.databinding.swt.ComboObservableList;
34
import org.eclipse.jface.internal.databinding.swt.ComboObservableValue;
35
import org.eclipse.jface.internal.databinding.swt.ComboSingleSelectionObservableValue;
36
import org.eclipse.jface.internal.databinding.swt.ControlObservableValue;
37
import org.eclipse.jface.internal.databinding.swt.ItemObservableValue;
38
import org.eclipse.jface.internal.databinding.swt.ItemTooltipObservableValue;
39
import org.eclipse.jface.internal.databinding.swt.LabelObservableValue;
40
import org.eclipse.jface.internal.databinding.swt.ListObservableList;
41
import org.eclipse.jface.internal.databinding.swt.ListObservableValue;
42
import org.eclipse.jface.internal.databinding.swt.ListSingleSelectionObservableValue;
43
import org.eclipse.jface.internal.databinding.swt.SWTDelayedObservableValueDecorator;
29
import org.eclipse.jface.internal.databinding.swt.SWTDelayedObservableValueDecorator;
44
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
45
import org.eclipse.jface.internal.databinding.swt.ScaleObservableValue;
46
import org.eclipse.jface.internal.databinding.swt.ShellObservableValue;
47
import org.eclipse.jface.internal.databinding.swt.SpinnerObservableValue;
48
import org.eclipse.jface.internal.databinding.swt.TableSingleSelectionObservableValue;
49
import org.eclipse.jface.internal.databinding.swt.TextEditableObservableValue;
50
import org.eclipse.jface.internal.databinding.swt.TextObservableValue;
51
import org.eclipse.swt.SWT;
52
import org.eclipse.swt.custom.CCombo;
53
import org.eclipse.swt.custom.CLabel;
54
import org.eclipse.swt.custom.CTabItem;
55
import org.eclipse.swt.widgets.Button;
56
import org.eclipse.swt.widgets.Combo;
57
import org.eclipse.swt.widgets.Control;
30
import org.eclipse.swt.widgets.Control;
58
import org.eclipse.swt.widgets.Display;
31
import org.eclipse.swt.widgets.Display;
59
import org.eclipse.swt.widgets.Item;
60
import org.eclipse.swt.widgets.Label;
61
import org.eclipse.swt.widgets.Link;
62
import org.eclipse.swt.widgets.List;
63
import org.eclipse.swt.widgets.Scale;
64
import org.eclipse.swt.widgets.Shell;
65
import org.eclipse.swt.widgets.Spinner;
66
import org.eclipse.swt.widgets.TabItem;
67
import org.eclipse.swt.widgets.Table;
68
import org.eclipse.swt.widgets.TableColumn;
69
import org.eclipse.swt.widgets.Text;
70
import org.eclipse.swt.widgets.ToolItem;
71
import org.eclipse.swt.widgets.TrayItem;
72
import org.eclipse.swt.widgets.TreeColumn;
73
import org.eclipse.swt.widgets.Widget;
32
import org.eclipse.swt.widgets.Widget;
74
33
75
/**
34
/**
76
 * A factory for creating observables for SWT widgets
35
 * A factory for creating observables for SWT widgets
77
 * 
36
 * 
78
 * @since 1.1
37
 * @since 1.1
79
 * 
80
 */
38
 */
81
public class SWTObservables {
39
public class SWTObservables {
82
40
Lines 140-164 Link Here
140
	}
98
	}
141
99
142
	/**
100
	/**
101
	 * Returns an observable value tracking the enabled state of the given
102
	 * control
103
	 * 
143
	 * @param control
104
	 * @param control
105
	 *            the control to observe
144
	 * @return an observable value tracking the enabled state of the given
106
	 * @return an observable value tracking the enabled state of the given
145
	 *         control
107
	 *         control
146
	 */
108
	 */
147
	public static ISWTObservableValue observeEnabled(Control control) {
109
	public static ISWTObservableValue observeEnabled(Control control) {
148
		return new ControlObservableValue(control, SWTProperties.ENABLED);
110
		return (ISWTObservableValue) WidgetProperties.enabled()
111
				.observe(control);
149
	}
112
	}
150
113
151
	/**
114
	/**
115
	 * Returns an observable value tracking the visible state of the given
116
	 * control
117
	 * 
152
	 * @param control
118
	 * @param control
119
	 *            the control to observe
153
	 * @return an observable value tracking the visible state of the given
120
	 * @return an observable value tracking the visible state of the given
154
	 *         control
121
	 *         control
155
	 */
122
	 */
156
	public static ISWTObservableValue observeVisible(Control control) {
123
	public static ISWTObservableValue observeVisible(Control control) {
157
		return new ControlObservableValue(control, SWTProperties.VISIBLE);
124
		return (ISWTObservableValue) WidgetProperties.visible()
125
				.observe(control);
158
	}
126
	}
159
127
160
	/**
128
	/**
161
	 * Returns an observable tracking the tooltip text of the given item. The supported types are:
129
	 * Returns an observable tracking the tooltip text of the given item. The
130
	 * supported types are:
162
	 * <ul>
131
	 * <ul>
163
	 * <li>org.eclipse.swt.widgets.Control</li>
132
	 * <li>org.eclipse.swt.widgets.Control</li>
164
	 * <li>org.eclipse.swt.custom.CTabItem</li>
133
	 * <li>org.eclipse.swt.custom.CTabItem</li>
Lines 168-197 Link Here
168
	 * <li>org.eclipse.swt.widgets.TrayItem</li>
137
	 * <li>org.eclipse.swt.widgets.TrayItem</li>
169
	 * <li>org.eclipse.swt.widgets.TreeColumn</li>
138
	 * <li>org.eclipse.swt.widgets.TreeColumn</li>
170
	 * </ul>
139
	 * </ul>
140
	 * 
171
	 * @param widget
141
	 * @param widget
172
	 * @return an observable value tracking the tooltip text of the given
142
	 * @return an observable value tracking the tooltip text of the given item
173
	 *         item
174
	 * 
143
	 * 
175
	 * @since 1.3
144
	 * @since 1.3
176
	 */
145
	 */
177
	public static ISWTObservableValue observeTooltipText(Widget widget) {
146
	public static ISWTObservableValue observeTooltipText(Widget widget) {
178
		if (widget instanceof Control) {
147
		return (ISWTObservableValue) WidgetProperties.tooltipText().observe(
179
			return new ControlObservableValue((Control)widget, SWTProperties.TOOLTIP_TEXT);
148
				widget);
180
		} else if (widget instanceof CTabItem
181
				|| widget instanceof TabItem
182
				|| widget instanceof TableColumn
183
				|| widget instanceof ToolItem
184
				|| widget instanceof TrayItem
185
				|| widget instanceof TreeColumn) {
186
			return new ItemTooltipObservableValue((Item) widget);
187
		}
188
		
189
		throw new IllegalArgumentException(
190
				"Item [" + widget.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
191
	}
149
	}
192
150
193
	/**
151
	/**
152
	 * Returns an observable value tracking the tooltip text of the given
153
	 * control
154
	 * 
194
	 * @param control
155
	 * @param control
156
	 *            the control to observe
195
	 * @return an observable value tracking the tooltip text of the given
157
	 * @return an observable value tracking the tooltip text of the given
196
	 *         control
158
	 *         control
197
	 */
159
	 */
Lines 217-242 Link Here
217
	 *             if <code>control</code> type is unsupported
179
	 *             if <code>control</code> type is unsupported
218
	 */
180
	 */
219
	public static ISWTObservableValue observeSelection(Control control) {
181
	public static ISWTObservableValue observeSelection(Control control) {
220
		if (control instanceof Spinner) {
182
		return (ISWTObservableValue) WidgetProperties.selection().observe(
221
			return new SpinnerObservableValue((Spinner) control,
183
				control);
222
					SWTProperties.SELECTION);
223
		} else if (control instanceof Button) {
224
			return new ButtonObservableValue((Button) control);
225
		} else if (control instanceof Combo) {
226
			return new ComboObservableValue((Combo) control,
227
					SWTProperties.SELECTION);
228
		} else if (control instanceof CCombo) {
229
			return new CComboObservableValue((CCombo) control,
230
					SWTProperties.SELECTION);
231
		} else if (control instanceof List) {
232
			return new ListObservableValue((List) control);
233
		} else if (control instanceof Scale) {
234
			return new ScaleObservableValue((Scale) control,
235
					SWTProperties.SELECTION);
236
		}
237
238
		throw new IllegalArgumentException(
239
				"Widget [" + control.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
240
	}
184
	}
241
185
242
	/**
186
	/**
Lines 253-267 Link Here
253
	 *             if <code>control</code> type is unsupported
197
	 *             if <code>control</code> type is unsupported
254
	 */
198
	 */
255
	public static ISWTObservableValue observeMin(Control control) {
199
	public static ISWTObservableValue observeMin(Control control) {
256
		if (control instanceof Spinner) {
200
		return (ISWTObservableValue) WidgetProperties.minimum()
257
			return new SpinnerObservableValue((Spinner) control,
201
				.observe(control);
258
					SWTProperties.MIN);
259
		} else if (control instanceof Scale) {
260
			return new ScaleObservableValue((Scale) control, SWTProperties.MIN);
261
		}
262
263
		throw new IllegalArgumentException(
264
				"Widget [" + control.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
265
	}
202
	}
266
203
267
	/**
204
	/**
Lines 278-292 Link Here
278
	 *             if <code>control</code> type is unsupported
215
	 *             if <code>control</code> type is unsupported
279
	 */
216
	 */
280
	public static ISWTObservableValue observeMax(Control control) {
217
	public static ISWTObservableValue observeMax(Control control) {
281
		if (control instanceof Spinner) {
218
		return (ISWTObservableValue) WidgetProperties.maximum()
282
			return new SpinnerObservableValue((Spinner) control,
219
				.observe(control);
283
					SWTProperties.MAX);
284
		} else if (control instanceof Scale) {
285
			return new ScaleObservableValue((Scale) control, SWTProperties.MAX);
286
		}
287
288
		throw new IllegalArgumentException(
289
				"Widget [" + control.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
290
	}
220
	}
291
221
292
	/**
222
	/**
Lines 294-314 Link Here
294
	 * <code>control</code>. The supported types are:
224
	 * <code>control</code>. The supported types are:
295
	 * <ul>
225
	 * <ul>
296
	 * <li>org.eclipse.swt.widgets.Text</li>
226
	 * <li>org.eclipse.swt.widgets.Text</li>
227
	 * <li>org.eclipse.swt.custom.StyledText (as of 1.3)</li>
297
	 * </ul>
228
	 * </ul>
298
	 * 
229
	 * 
299
	 * @param control
230
	 * @param control
300
	 * @param event event type to register for change events
231
	 * @param event
232
	 *            event type to register for change events
301
	 * @return observable value
233
	 * @return observable value
302
	 * @throws IllegalArgumentException
234
	 * @throws IllegalArgumentException
303
	 *             if <code>control</code> type is unsupported
235
	 *             if <code>control</code> type is unsupported
304
	 */
236
	 */
305
	public static ISWTObservableValue observeText(Control control, int event) {
237
	public static ISWTObservableValue observeText(Control control, int event) {
306
		if (control instanceof Text) {
238
		return (ISWTObservableValue) WidgetProperties.text(event).observe(
307
			return new TextObservableValue((Text) control, event);
239
				control);
308
		}
309
310
		throw new IllegalArgumentException(
311
				"Widget [" + control.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
312
	}
240
	}
313
241
314
	/**
242
	/**
Lines 329-359 Link Here
329
	 * @return observable value
257
	 * @return observable value
330
	 * @throws IllegalArgumentException
258
	 * @throws IllegalArgumentException
331
	 *             if the type of <code>widget</code> is unsupported
259
	 *             if the type of <code>widget</code> is unsupported
332
	 *             
260
	 * 
333
	 * @since 1.3
261
	 * @since 1.3
334
	 */
262
	 */
335
	public static ISWTObservableValue observeText(Widget widget) {
263
	public static ISWTObservableValue observeText(Widget widget) {
336
		if (widget instanceof Label) {
264
		return (ISWTObservableValue) WidgetProperties.text().observe(widget);
337
			return new LabelObservableValue((Label) widget);
338
		} else if (widget instanceof Link) {
339
			return new LinkObservableValue((Link) widget);
340
		} else if (widget instanceof CLabel) {
341
			return new CLabelObservableValue((CLabel) widget);
342
		} else if (widget instanceof Combo) {
343
			return new ComboObservableValue((Combo) widget, SWTProperties.TEXT);
344
		} else if (widget instanceof CCombo) {
345
			return new CComboObservableValue((CCombo) widget,
346
					SWTProperties.TEXT);
347
		} else if (widget instanceof Shell) {
348
			return new ShellObservableValue((Shell) widget);
349
		} else if (widget instanceof Text) {
350
			return new TextObservableValue((Text) widget, SWT.None);
351
		} else if (widget instanceof Item) {
352
			return new ItemObservableValue((Item)widget);
353
		}
354
355
		throw new IllegalArgumentException(
356
				"Widget [" + widget.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
357
	}
265
	}
358
266
359
	/**
267
	/**
Lines 367-372 Link Here
367
	 * <li>org.eclipse.swt.custom.CCombo</li>
275
	 * <li>org.eclipse.swt.custom.CCombo</li>
368
	 * <li>org.eclipse.swt.widgets.Shell</li>
276
	 * <li>org.eclipse.swt.widgets.Shell</li>
369
	 * <li>org.eclipse.swt.widgets.Text (as of 1.3)</li>
277
	 * <li>org.eclipse.swt.widgets.Text (as of 1.3)</li>
278
	 * <li>org.eclipse.swt.custom.StyledText (as of 1.3)</li>
370
	 * </ul>
279
	 * </ul>
371
	 * 
280
	 * 
372
	 * @param control
281
	 * @param control
Lines 393-408 Link Here
393
	 *             if <code>control</code> type is unsupported
302
	 *             if <code>control</code> type is unsupported
394
	 */
303
	 */
395
	public static IObservableList observeItems(Control control) {
304
	public static IObservableList observeItems(Control control) {
396
		if (control instanceof Combo) {
305
		return WidgetProperties.items().observe(control);
397
			return new ComboObservableList((Combo) control);
398
		} else if (control instanceof CCombo) {
399
			return new CComboObservableList((CCombo) control);
400
		} else if (control instanceof List) {
401
			return new ListObservableList((List) control);
402
		}
403
404
		throw new IllegalArgumentException(
405
				"Widget [" + control.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
406
	}
306
	}
407
307
408
	/**
308
	/**
Lines 422-506 Link Here
422
	 */
322
	 */
423
	public static ISWTObservableValue observeSingleSelectionIndex(
323
	public static ISWTObservableValue observeSingleSelectionIndex(
424
			Control control) {
324
			Control control) {
425
		if (control instanceof Table) {
325
		return (ISWTObservableValue) WidgetProperties.singleSelectionIndex()
426
			return new TableSingleSelectionObservableValue((Table) control);
326
				.observe(control);
427
		} else if (control instanceof Combo) {
428
			return new ComboSingleSelectionObservableValue((Combo) control);
429
		} else if (control instanceof CCombo) {
430
			return new CComboSingleSelectionObservableValue((CCombo) control);
431
		} else if (control instanceof List) {
432
			return new ListSingleSelectionObservableValue((List) control);
433
		}
434
435
		throw new IllegalArgumentException(
436
				"Widget [" + control.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
437
	}
327
	}
438
328
439
	/**
329
	/**
330
	 * Returns an observable value tracking the foreground color of the given
331
	 * control
332
	 * 
440
	 * @param control
333
	 * @param control
334
	 *            the control to observe
441
	 * @return an observable value tracking the foreground color of the given
335
	 * @return an observable value tracking the foreground color of the given
442
	 *         control
336
	 *         control
443
	 */
337
	 */
444
	public static ISWTObservableValue observeForeground(Control control) {
338
	public static ISWTObservableValue observeForeground(Control control) {
445
		return new ControlObservableValue(control, SWTProperties.FOREGROUND);
339
		return (ISWTObservableValue) WidgetProperties.foreground().observe(
340
				control);
446
	}
341
	}
447
342
448
	/**
343
	/**
344
	 * Returns an observable value tracking the background color of the given
345
	 * control
346
	 * 
449
	 * @param control
347
	 * @param control
348
	 *            the control to observe
450
	 * @return an observable value tracking the background color of the given
349
	 * @return an observable value tracking the background color of the given
451
	 *         control
350
	 *         control
452
	 */
351
	 */
453
	public static ISWTObservableValue observeBackground(Control control) {
352
	public static ISWTObservableValue observeBackground(Control control) {
454
		return new ControlObservableValue(control, SWTProperties.BACKGROUND);
353
		return (ISWTObservableValue) WidgetProperties.background().observe(
354
				control);
455
	}
355
	}
456
356
457
	/**
357
	/**
358
	 * Returns an observable value tracking the font of the given control.
359
	 * 
458
	 * @param control
360
	 * @param control
361
	 *            the control to observe
459
	 * @return an observable value tracking the font of the given control
362
	 * @return an observable value tracking the font of the given control
460
	 */
363
	 */
461
	public static ISWTObservableValue observeFont(Control control) {
364
	public static ISWTObservableValue observeFont(Control control) {
462
		return new ControlObservableValue(control, SWTProperties.FONT);
365
		return (ISWTObservableValue) WidgetProperties.font().observe(control);
463
	}
366
	}
464
	
367
465
	/**
368
	/**
369
	 * Returns an observable value tracking the size of the given control.
370
	 * 
466
	 * @param control
371
	 * @param control
372
	 *            the control to observe
467
	 * @return an observable value tracking the size of the given control
373
	 * @return an observable value tracking the size of the given control
468
	 * @since 1.3
374
	 * @since 1.3
469
	 */
375
	 */
470
	public static ISWTObservableValue observeSize(Control control) {
376
	public static ISWTObservableValue observeSize(Control control) {
471
		return new ControlObservableValue(control,SWTProperties.SIZE);
377
		return (ISWTObservableValue) WidgetProperties.size().observe(control);
472
	}
378
	}
473
	
379
474
	/**
380
	/**
381
	 * Returns an observable value tracking the location of the given control.
382
	 * 
475
	 * @param control
383
	 * @param control
384
	 *            the control to observe
476
	 * @return an observable value tracking the location of the given control
385
	 * @return an observable value tracking the location of the given control
477
	 * @since 1.3
386
	 * @since 1.3
478
	 */
387
	 */
479
	public static ISWTObservableValue observeLocation(Control control) {
388
	public static ISWTObservableValue observeLocation(Control control) {
480
		return new ControlObservableValue(control,SWTProperties.LOCATION);
389
		return (ISWTObservableValue) WidgetProperties.location().observe(
390
				control);
481
	}
391
	}
482
	
392
483
	/**
393
	/**
394
	 * Returns an observable value tracking the focus of the given control.
395
	 * 
484
	 * @param control
396
	 * @param control
397
	 *            the control to observe
485
	 * @return an observable value tracking the focus of the given control
398
	 * @return an observable value tracking the focus of the given control
486
	 * @since 1.3
399
	 * @since 1.3
487
	 */
400
	 */
488
	public static ISWTObservableValue observeFocus(Control control) {
401
	public static ISWTObservableValue observeFocus(Control control) {
489
		return new ControlObservableValue(control,SWTProperties.FOCUS);
402
		return (ISWTObservableValue) WidgetProperties.focused()
403
				.observe(control);
490
	}
404
	}
491
	
405
492
	/**
406
	/**
407
	 * Returns an observable value tracking the bounds of the given control.
408
	 * 
493
	 * @param control
409
	 * @param control
410
	 *            the control to observe
494
	 * @return an observable value tracking the bounds of the given control
411
	 * @return an observable value tracking the bounds of the given control
495
	 * @since 1.3
412
	 * @since 1.3
496
	 */
413
	 */
497
	public static ISWTObservableValue observeBounds(Control control) {
414
	public static ISWTObservableValue observeBounds(Control control) {
498
		return new ControlObservableValue(control,SWTProperties.BOUNDS);
415
		return (ISWTObservableValue) WidgetProperties.bounds().observe(control);
499
	}
416
	}
500
	
417
501
	/**
418
	/**
502
	 * Returns an observable observing the editable attribute of
419
	 * Returns an observable observing the editable attribute of the provided
503
	 * the provided <code>control</code>. The supported types are:
420
	 * <code>control</code>. The supported types are:
504
	 * <ul>
421
	 * <ul>
505
	 * <li>org.eclipse.swt.widgets.Text</li>
422
	 * <li>org.eclipse.swt.widgets.Text</li>
506
	 * </ul>
423
	 * </ul>
Lines 511-522 Link Here
511
	 *             if <code>control</code> type is unsupported
428
	 *             if <code>control</code> type is unsupported
512
	 */
429
	 */
513
	public static ISWTObservableValue observeEditable(Control control) {
430
	public static ISWTObservableValue observeEditable(Control control) {
514
		if (control instanceof Text) {
431
		return (ISWTObservableValue) WidgetProperties.editable().observe(
515
			return new TextEditableObservableValue((Text) control);
432
				control);
516
		}
517
		
518
		throw new IllegalArgumentException(
519
				"Widget [" + control.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
520
	}
433
	}
521
434
522
	private static class DisplayRealm extends Realm {
435
	private static class DisplayRealm extends Realm {
Lines 555-574 Link Here
555
			}
468
			}
556
		}
469
		}
557
470
558
		/*
559
		 * (non-Javadoc)
560
		 * 
561
		 * @see java.lang.Object#hashCode()
562
		 */
563
		public int hashCode() {
471
		public int hashCode() {
564
			return (display == null) ? 0 : display.hashCode();
472
			return (display == null) ? 0 : display.hashCode();
565
		}
473
		}
566
474
567
		/*
568
		 * (non-Javadoc)
569
		 * 
570
		 * @see java.lang.Object#equals(java.lang.Object)
571
		 */
572
		public boolean equals(Object obj) {
475
		public boolean equals(Object obj) {
573
			if (this == obj)
476
			if (this == obj)
574
				return true;
477
				return true;
(-)src/org/eclipse/jface/internal/databinding/swt/SWTObservableListDecorator.java (+57 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.list.DecoratingObservableList;
15
import org.eclipse.core.databinding.observable.list.IObservableList;
16
import org.eclipse.jface.databinding.swt.ISWTObservable;
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.widgets.Event;
19
import org.eclipse.swt.widgets.Listener;
20
import org.eclipse.swt.widgets.Widget;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class SWTObservableListDecorator extends DecoratingObservableList
27
		implements ISWTObservable {
28
	private Widget widget;
29
30
	/**
31
	 * @param decorated
32
	 * @param widget
33
	 */
34
	public SWTObservableListDecorator(IObservableList decorated, Widget widget) {
35
		super(decorated, true);
36
		this.widget = widget;
37
		widget.addListener(SWT.Dispose, disposeListener);
38
	}
39
40
	private Listener disposeListener = new Listener() {
41
		public void handleEvent(Event event) {
42
			SWTObservableListDecorator.this.dispose();
43
		}
44
	};
45
46
	public void dispose() {
47
		this.widget = null;
48
		super.dispose();
49
	}
50
51
	/**
52
	 * @return Returns the widget.
53
	 */
54
	public Widget getWidget() {
55
		return widget;
56
	}
57
}
(-)src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderMultipleSelectionProperty.java (+86 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.viewers;
14
15
import java.util.Collections;
16
import java.util.List;
17
18
import org.eclipse.core.databinding.observable.list.ListDiff;
19
import org.eclipse.core.databinding.property.INativePropertyListener;
20
import org.eclipse.core.databinding.property.ISimplePropertyListener;
21
import org.eclipse.core.databinding.property.SimplePropertyEvent;
22
import org.eclipse.jface.viewers.ISelection;
23
import org.eclipse.jface.viewers.ISelectionChangedListener;
24
import org.eclipse.jface.viewers.ISelectionProvider;
25
import org.eclipse.jface.viewers.IStructuredSelection;
26
import org.eclipse.jface.viewers.SelectionChangedEvent;
27
import org.eclipse.jface.viewers.StructuredSelection;
28
29
/**
30
 * @since 3.3
31
 * 
32
 */
33
public class SelectionProviderMultipleSelectionProperty extends
34
		ViewerListProperty {
35
	public Object getElementType() {
36
		return Object.class;
37
	}
38
39
	protected List doGetList(Object source) {
40
		ISelection selection = ((ISelectionProvider) source).getSelection();
41
		if (selection instanceof IStructuredSelection) {
42
			return ((IStructuredSelection) selection).toList();
43
		}
44
		return Collections.EMPTY_LIST;
45
	}
46
47
	protected void doSetList(Object source, List list, ListDiff diff) {
48
		((ISelectionProvider) source)
49
				.setSelection(new StructuredSelection(list));
50
	}
51
52
	public INativePropertyListener adaptListener(
53
			ISimplePropertyListener listener) {
54
		return new SelectionChangedListener(listener);
55
	}
56
57
	public void doAddListener(Object source, INativePropertyListener listener) {
58
		((ISelectionProvider) source)
59
				.addSelectionChangedListener((ISelectionChangedListener) listener);
60
	}
61
62
	public void doRemoveListener(Object source, INativePropertyListener listener) {
63
		((ISelectionProvider) source)
64
				.removeSelectionChangedListener((ISelectionChangedListener) listener);
65
66
	}
67
68
	private class SelectionChangedListener implements INativePropertyListener,
69
			ISelectionChangedListener {
70
		private ISimplePropertyListener listener;
71
72
		private SelectionChangedListener(ISimplePropertyListener listener) {
73
			this.listener = listener;
74
		}
75
76
		public void selectionChanged(SelectionChangedEvent event) {
77
			listener.handlePropertyChange(new SimplePropertyEvent(event
78
					.getSource(),
79
					SelectionProviderMultipleSelectionProperty.this, null));
80
		}
81
	}
82
83
	public String toString() {
84
		return "ISelectionProvider.selection[]"; //$NON-NLS-1$
85
	}
86
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerSetProperty.java (+39 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.set.IObservableSet;
16
import org.eclipse.core.databinding.property.set.SimpleSetProperty;
17
import org.eclipse.jface.databinding.swt.SWTObservables;
18
import org.eclipse.jface.viewers.Viewer;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public abstract class ViewerSetProperty extends SimpleSetProperty {
25
	public IObservableSet observe(Object source) {
26
		if (source instanceof Viewer) {
27
			return observe(SWTObservables.getRealm(((Viewer) source)
28
					.getControl().getDisplay()), source);
29
		}
30
		return super.observe(source);
31
	}
32
33
	public IObservableSet observe(Realm realm, Object source) {
34
		IObservableSet observable = super.observe(realm, source);
35
		if (source instanceof Viewer)
36
			return new ViewerObservableSetDecorator(observable, (Viewer) source);
37
		return observable;
38
	}
39
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlEnabledProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Control;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class ControlEnabledProperty extends WidgetBooleanValueProperty {
21
	public boolean doGetBooleanValue(Object source) {
22
		return ((Control) source).getEnabled();
23
	}
24
25
	void doSetBooleanValue(Object source, boolean value) {
26
		((Control) source).setEnabled(value);
27
	}
28
29
	public String toString() {
30
		return "Control.enabled <boolean>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlFocusedProperty.java (+42 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 *     Tom Schindl - initial API and implementation
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.swt.SWT;
16
import org.eclipse.swt.widgets.Control;
17
18
/**
19
 * @since 3.3
20
 * 
21
 */
22
public class ControlFocusedProperty extends WidgetBooleanValueProperty {
23
	/**
24
	 * 
25
	 */
26
	public ControlFocusedProperty() {
27
		super(new int[] { SWT.FocusIn, SWT.FocusOut });
28
	}
29
30
	public boolean doGetBooleanValue(Object source) {
31
		return ((Control) source).isFocusControl();
32
	}
33
34
	public void doSetBooleanValue(Object source, boolean value) {
35
		if (value)
36
			((Control) source).setFocus();
37
	}
38
39
	public String toString() {
40
		return "Control.focus <boolean>"; //$NON-NLS-1$
41
	}
42
}
(-)src/org/eclipse/jface/internal/databinding/swt/CTabItemTooltipTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.custom.CTabItem;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class CTabItemTooltipTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((CTabItem) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((CTabItem) source).setText(value == null ? "" : (String) value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "CTabItem.tooltipText <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlLocationProperty.java (+47 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 *     Tom Schindl - initial API and implementation
11
 *     Matthew Hall - bug 195222
12
 ******************************************************************************/
13
14
package org.eclipse.jface.internal.databinding.swt;
15
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.graphics.Point;
18
import org.eclipse.swt.widgets.Control;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public class ControlLocationProperty extends WidgetValueProperty {
25
	/**
26
	 * 
27
	 */
28
	public ControlLocationProperty() {
29
		super(SWT.Move);
30
	}
31
32
	public Object getValueType() {
33
		return Point.class;
34
	}
35
36
	protected Object doGetValue(Object source) {
37
		return ((Control) source).getLocation();
38
	}
39
40
	protected void doSetValue(Object source, Object value) {
41
		((Control) source).setLocation((Point) value);
42
	}
43
44
	public String toString() {
45
		return "Control.location <Point>"; //$NON-NLS-1$
46
	}
47
}
(-)src/org/eclipse/jface/internal/databinding/swt/TreeItemTooltipTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.TreeItem;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class TreeItemTooltipTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((TreeItem) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((TreeItem) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "TreeItem.tooltipText <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ButtonSelectionProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.Button;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ButtonSelectionProperty extends WidgetBooleanValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public ButtonSelectionProperty() {
26
		super(SWT.Selection);
27
	}
28
29
	boolean doGetBooleanValue(Object source) {
30
		return ((Button) source).getSelection();
31
	}
32
33
	void doSetBooleanValue(Object source, boolean value) {
34
		((Button) source).setSelection(value);
35
	}
36
37
	public String toString() {
38
		return "Button.selection <Boolean>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/TabItemTooltipTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.TabItem;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class TabItemTooltipTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((TabItem) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((TabItem) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "TabItem.tooltipText <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlFontProperty.java (+38 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.swt.graphics.Font;
16
import org.eclipse.swt.widgets.Control;
17
18
/**
19
 * @since 3.3
20
 * 
21
 */
22
public class ControlFontProperty extends WidgetValueProperty {
23
	public Object getValueType() {
24
		return Font.class;
25
	}
26
27
	protected Object doGetValue(Object source) {
28
		return ((Control) source).getFont();
29
	}
30
31
	protected void doSetValue(Object source, Object value) {
32
		((Control) source).setFont((Font) value);
33
	}
34
35
	public String toString() {
36
		return "Control.font <Font>"; //$NON-NLS-1$
37
	}
38
}
(-)src/org/eclipse/jface/internal/databinding/swt/ScaleMaximumProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Scale;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class ScaleMaximumProperty extends WidgetIntValueProperty {
21
	int doGetIntValue(Object source) {
22
		return ((Scale) source).getMaximum();
23
	}
24
25
	void doSetIntValue(Object source, int value) {
26
		((Scale) source).setMaximum(value);
27
	}
28
29
	public String toString() {
30
		return "Scale.maximum <int>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ListSelectionProperty.java (+55 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.List;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ListSelectionProperty extends WidgetStringValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public ListSelectionProperty() {
26
		super(SWT.Selection);
27
	}
28
29
	String doGetStringValue(Object source) {
30
		List list = (List) source;
31
		int index = list.getSelectionIndex();
32
		if (index >= 0)
33
			return list.getItem(index);
34
		return null;
35
	}
36
37
	void doSetStringValue(Object source, String value) {
38
		List list = (List) source;
39
		String items[] = list.getItems();
40
		int index = -1;
41
		if (items != null && value != null) {
42
			for (int i = 0; i < items.length; i++) {
43
				if (value.equals(items[i])) {
44
					index = i;
45
					break;
46
				}
47
			}
48
			list.select(index);
49
		}
50
	}
51
52
	public String toString() {
53
		return "List.selection <String>"; //$NON-NLS-1$
54
	}
55
}
(-)src/org/eclipse/jface/databinding/swt/WidgetProperties.java (+448 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.databinding.swt;
13
14
import org.eclipse.core.databinding.property.list.DelegatingListProperty;
15
import org.eclipse.core.databinding.property.list.IListProperty;
16
import org.eclipse.core.databinding.property.value.DelegatingValueProperty;
17
import org.eclipse.core.databinding.property.value.IValueProperty;
18
import org.eclipse.jface.internal.databinding.swt.ButtonSelectionProperty;
19
import org.eclipse.jface.internal.databinding.swt.CComboItemsProperty;
20
import org.eclipse.jface.internal.databinding.swt.CComboSelectionProperty;
21
import org.eclipse.jface.internal.databinding.swt.CComboSingleSelectionIndexProperty;
22
import org.eclipse.jface.internal.databinding.swt.CComboTextProperty;
23
import org.eclipse.jface.internal.databinding.swt.CLabelTextProperty;
24
import org.eclipse.jface.internal.databinding.swt.CTabItemTooltipTextProperty;
25
import org.eclipse.jface.internal.databinding.swt.ComboItemsProperty;
26
import org.eclipse.jface.internal.databinding.swt.ComboSelectionProperty;
27
import org.eclipse.jface.internal.databinding.swt.ComboSingleSelectionIndexProperty;
28
import org.eclipse.jface.internal.databinding.swt.ComboTextProperty;
29
import org.eclipse.jface.internal.databinding.swt.ControlBackgroundProperty;
30
import org.eclipse.jface.internal.databinding.swt.ControlBoundsProperty;
31
import org.eclipse.jface.internal.databinding.swt.ControlEnabledProperty;
32
import org.eclipse.jface.internal.databinding.swt.ControlFocusedProperty;
33
import org.eclipse.jface.internal.databinding.swt.ControlFontProperty;
34
import org.eclipse.jface.internal.databinding.swt.ControlForegroundProperty;
35
import org.eclipse.jface.internal.databinding.swt.ControlLocationProperty;
36
import org.eclipse.jface.internal.databinding.swt.ControlSizeProperty;
37
import org.eclipse.jface.internal.databinding.swt.ControlTooltipTextProperty;
38
import org.eclipse.jface.internal.databinding.swt.ControlVisibleProperty;
39
import org.eclipse.jface.internal.databinding.swt.ItemTextProperty;
40
import org.eclipse.jface.internal.databinding.swt.LabelTextProperty;
41
import org.eclipse.jface.internal.databinding.swt.LinkTextProperty;
42
import org.eclipse.jface.internal.databinding.swt.ListItemsProperty;
43
import org.eclipse.jface.internal.databinding.swt.ListSelectionProperty;
44
import org.eclipse.jface.internal.databinding.swt.ListSingleSelectionIndexProperty;
45
import org.eclipse.jface.internal.databinding.swt.ScaleMaximumProperty;
46
import org.eclipse.jface.internal.databinding.swt.ScaleMinimumProperty;
47
import org.eclipse.jface.internal.databinding.swt.ScaleSelectionProperty;
48
import org.eclipse.jface.internal.databinding.swt.ShellTextProperty;
49
import org.eclipse.jface.internal.databinding.swt.SpinnerMaximumProperty;
50
import org.eclipse.jface.internal.databinding.swt.SpinnerMinimumProperty;
51
import org.eclipse.jface.internal.databinding.swt.SpinnerSelectionProperty;
52
import org.eclipse.jface.internal.databinding.swt.StyledTextTextProperty;
53
import org.eclipse.jface.internal.databinding.swt.TabItemTooltipTextProperty;
54
import org.eclipse.jface.internal.databinding.swt.TableColumnTooltipTextProperty;
55
import org.eclipse.jface.internal.databinding.swt.TableSingleSelectionIndexProperty;
56
import org.eclipse.jface.internal.databinding.swt.TextEditableProperty;
57
import org.eclipse.jface.internal.databinding.swt.TextTextProperty;
58
import org.eclipse.jface.internal.databinding.swt.ToolItemTooltipTextProperty;
59
import org.eclipse.jface.internal.databinding.swt.TrayItemTooltipTextProperty;
60
import org.eclipse.jface.internal.databinding.swt.TreeItemTooltipTextProperty;
61
import org.eclipse.swt.SWT;
62
import org.eclipse.swt.custom.CCombo;
63
import org.eclipse.swt.custom.CLabel;
64
import org.eclipse.swt.custom.CTabItem;
65
import org.eclipse.swt.custom.StyledText;
66
import org.eclipse.swt.widgets.Button;
67
import org.eclipse.swt.widgets.Combo;
68
import org.eclipse.swt.widgets.Control;
69
import org.eclipse.swt.widgets.Item;
70
import org.eclipse.swt.widgets.Label;
71
import org.eclipse.swt.widgets.Link;
72
import org.eclipse.swt.widgets.List;
73
import org.eclipse.swt.widgets.Scale;
74
import org.eclipse.swt.widgets.Shell;
75
import org.eclipse.swt.widgets.Spinner;
76
import org.eclipse.swt.widgets.TabItem;
77
import org.eclipse.swt.widgets.Table;
78
import org.eclipse.swt.widgets.TableColumn;
79
import org.eclipse.swt.widgets.Text;
80
import org.eclipse.swt.widgets.ToolItem;
81
import org.eclipse.swt.widgets.TrayItem;
82
import org.eclipse.swt.widgets.TreeColumn;
83
import org.eclipse.swt.widgets.TreeItem;
84
import org.eclipse.swt.widgets.Widget;
85
86
/**
87
 * A factory for creating properties of SWT {@link Widget widgets}.
88
 * 
89
 * @since 1.3
90
 */
91
public class WidgetProperties {
92
	private static RuntimeException notSupported(Object source) {
93
		return new IllegalArgumentException(
94
				"Widget [" + source.getClass().getName() + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
95
	}
96
97
	/**
98
	 * Returns a value property for observing the background color of a
99
	 * {@link Control}.
100
	 * 
101
	 * @return a value property for observing the background color of a
102
	 *         {@link Control}.
103
	 */
104
	public static IValueProperty background() {
105
		return new ControlBackgroundProperty();
106
	}
107
108
	/**
109
	 * Returns a value property for observing the bounds of a {@link Control}.
110
	 * 
111
	 * @return a value property for observing the bounds of a {@link Control}.
112
	 */
113
	public static IValueProperty bounds() {
114
		return new ControlBoundsProperty();
115
	}
116
117
	/**
118
	 * Returns a value property for observing the editable state of a
119
	 * {@link Text}.
120
	 * 
121
	 * @return a value property for observing the editable state of a
122
	 *         {@link Text}.
123
	 */
124
	public static IValueProperty editable() {
125
		return new DelegatingValueProperty(Boolean.TYPE) {
126
			IValueProperty text = new TextEditableProperty();
127
128
			protected IValueProperty doGetDelegate(Object source) {
129
				if (source instanceof Text)
130
					return text;
131
				throw notSupported(source);
132
			}
133
		};
134
	}
135
136
	/**
137
	 * Returns a value property for observing the enablement state of a
138
	 * {@link Control}.
139
	 * 
140
	 * @return a value property for observing the enablement state of a
141
	 *         {@link Control}.
142
	 */
143
	public static IValueProperty enabled() {
144
		return new ControlEnabledProperty();
145
	}
146
147
	/**
148
	 * Returns a value property for observing the focus state of a
149
	 * {@link Control}.
150
	 * 
151
	 * @return a value property for observing the focus state of a
152
	 *         {@link Control}.
153
	 */
154
	public static IValueProperty focused() {
155
		return new ControlFocusedProperty();
156
	}
157
158
	/**
159
	 * Returns a value property for observing the font of a {@link Control}.
160
	 * 
161
	 * @return a value property for observing the font of a {@link Control}.
162
	 */
163
	public static IValueProperty font() {
164
		return new ControlFontProperty();
165
	}
166
167
	/**
168
	 * Returns a value property for observing the foreground color of a
169
	 * {@link Control}.
170
	 * 
171
	 * @return a value property for observing the foreground color of a
172
	 *         {@link Control}.
173
	 */
174
	public static IValueProperty foreground() {
175
		return new ControlForegroundProperty();
176
	}
177
178
	/**
179
	 * Returns a list property for observing the items of a {@link CCombo},
180
	 * {@link Combo} or {@link List}.
181
	 * 
182
	 * @return a list property for observing the items of a {@link CCombo},
183
	 *         {@link Combo} or {@link List}.
184
	 */
185
	public static IListProperty items() {
186
		return new DelegatingListProperty(String.class) {
187
			private IListProperty cCombo = new CComboItemsProperty();
188
			private IListProperty combo = new ComboItemsProperty();
189
			private IListProperty list = new ListItemsProperty();
190
191
			protected IListProperty doGetDelegate(Object source) {
192
				if (source instanceof CCombo)
193
					return cCombo;
194
				if (source instanceof Combo)
195
					return combo;
196
				if (source instanceof List)
197
					return list;
198
				throw notSupported(source);
199
			}
200
		};
201
	}
202
203
	/**
204
	 * Returns a value property for observing the location of a {@link Control}.
205
	 * 
206
	 * @return a value property for observing the location of a {@link Control}.
207
	 */
208
	public static IValueProperty location() {
209
		return new ControlLocationProperty();
210
	}
211
212
	/**
213
	 * Returns a value property for observing the maximum value of a
214
	 * {@link Scale} or {@link Spinner}.
215
	 * 
216
	 * @return a value property for observing the maximum value of a
217
	 *         {@link Scale} or {@link Spinner}.
218
	 */
219
	public static IValueProperty maximum() {
220
		return new DelegatingValueProperty(Integer.TYPE) {
221
			private IValueProperty scale = new ScaleMaximumProperty();
222
			private IValueProperty spinner = new SpinnerMaximumProperty();
223
224
			protected IValueProperty doGetDelegate(Object source) {
225
				if (source instanceof Scale)
226
					return scale;
227
				if (source instanceof Spinner)
228
					return spinner;
229
				throw notSupported(source);
230
			}
231
		};
232
	}
233
234
	/**
235
	 * Returns a value property for observing the minimum value of a
236
	 * {@link Scale} or {@link Spinner}.
237
	 * 
238
	 * @return a value property for observing the minimum value of a
239
	 *         {@link Scale} or {@link Spinner}.
240
	 */
241
	public static IValueProperty minimum() {
242
		return new DelegatingValueProperty(Integer.TYPE) {
243
			private IValueProperty scale = new ScaleMinimumProperty();
244
			private IValueProperty spinner = new SpinnerMinimumProperty();
245
246
			protected IValueProperty doGetDelegate(Object source) {
247
				if (source instanceof Scale)
248
					return scale;
249
				if (source instanceof Spinner)
250
					return spinner;
251
				throw notSupported(source);
252
			}
253
		};
254
	}
255
256
	/**
257
	 * Returns a value property for observing the selection state of a
258
	 * {@link Button}, {@link CCombo}, {@link Combo}, {@link List},
259
	 * {@link Scale} or {@link Spinner}.
260
	 * 
261
	 * @return a value property for observing the selection state of a
262
	 *         {@link Button}, {@link CCombo}, {@link Combo}, {@link List},
263
	 *         {@link Scale} or {@link Spinner}.
264
	 */
265
	public static IValueProperty selection() {
266
		return new DelegatingValueProperty() {
267
			private IValueProperty button = new ButtonSelectionProperty();
268
			private IValueProperty cCombo = new CComboSelectionProperty();
269
			private IValueProperty combo = new ComboSelectionProperty();
270
			private IValueProperty list = new ListSelectionProperty();
271
			private IValueProperty scale = new ScaleSelectionProperty();
272
			private IValueProperty spinner = new SpinnerSelectionProperty();
273
274
			protected IValueProperty doGetDelegate(Object source) {
275
				if (source instanceof Button)
276
					return button;
277
				if (source instanceof CCombo)
278
					return cCombo;
279
				if (source instanceof Combo)
280
					return combo;
281
				if (source instanceof List)
282
					return list;
283
				if (source instanceof Scale)
284
					return scale;
285
				if (source instanceof Spinner)
286
					return spinner;
287
				throw notSupported(source);
288
			}
289
		};
290
	}
291
292
	/**
293
	 * Returns a value property for observing the single selection index of a
294
	 * {@link CCombo}, {@link Combo}, {@link List} or {@link Table}.
295
	 * 
296
	 * @return a value property for the single selection index of a SWT Combo.
297
	 */
298
	public static IValueProperty singleSelectionIndex() {
299
		return new DelegatingValueProperty(Integer.TYPE) {
300
			private IValueProperty cCombo = new CComboSingleSelectionIndexProperty();
301
			private IValueProperty combo = new ComboSingleSelectionIndexProperty();
302
			private IValueProperty list = new ListSingleSelectionIndexProperty();
303
			private IValueProperty table = new TableSingleSelectionIndexProperty();
304
305
			protected IValueProperty doGetDelegate(Object source) {
306
				if (source instanceof CCombo)
307
					return cCombo;
308
				if (source instanceof Combo)
309
					return combo;
310
				if (source instanceof List)
311
					return list;
312
				if (source instanceof Table)
313
					return table;
314
				throw notSupported(source);
315
			}
316
		};
317
	}
318
319
	/**
320
	 * Returns a value property for observing the size of a {@link Control}.
321
	 * 
322
	 * @return a value property for observing the size of a {@link Control}.
323
	 */
324
	public static IValueProperty size() {
325
		return new ControlSizeProperty();
326
	}
327
328
	/**
329
	 * Returns a value property for observing the text of a {@link CCombo},
330
	 * {@link CLabel}, {@link Combo}, {@link Label}, {@link Item}, {@link Link},
331
	 * {@link Shell} or {@link Text}.
332
	 * 
333
	 * @return a value property for observing the text of a {@link CCombo},
334
	 *         {@link CLabel}, {@link Combo}, {@link Label}, {@link Item},
335
	 *         {@link Link}, {@link Shell} or {@link Text}.
336
	 */
337
	public static IValueProperty text() {
338
		return new DelegatingValueProperty(String.class) {
339
			private IValueProperty cCombo = new CComboTextProperty();
340
			private IValueProperty cLabel = new CLabelTextProperty();
341
			private IValueProperty combo = new ComboTextProperty();
342
			private IValueProperty item = new ItemTextProperty();
343
			private IValueProperty label = new LabelTextProperty();
344
			private IValueProperty link = new LinkTextProperty();
345
			private IValueProperty shell = new ShellTextProperty();
346
			private IValueProperty text = new TextTextProperty(SWT.None);
347
348
			protected IValueProperty doGetDelegate(Object source) {
349
				if (source instanceof CCombo)
350
					return cCombo;
351
				if (source instanceof CLabel)
352
					return cLabel;
353
				if (source instanceof Combo)
354
					return combo;
355
				if (source instanceof Item)
356
					return item;
357
				if (source instanceof Label)
358
					return label;
359
				if (source instanceof Link)
360
					return link;
361
				if (source instanceof Shell)
362
					return shell;
363
				if (source instanceof Text)
364
					return text;
365
				throw notSupported(source);
366
			}
367
		};
368
	}
369
370
	/**
371
	 * Returns a value property for observing the text of a {@link StyledText}
372
	 * or {@link Text}.
373
	 * 
374
	 * @param event
375
	 *            the SWT event type to register for change events. May be
376
	 *            {@link SWT#None}, {@link SWT#Modify} or {@link SWT#FocusOut}.
377
	 * 
378
	 * @return a value property for observing the text of a {@link StyledText}
379
	 *         or {@link Text}.
380
	 */
381
	public static IValueProperty text(final int event) {
382
		return new DelegatingValueProperty(String.class) {
383
			private IValueProperty styledText = new StyledTextTextProperty(
384
					event);
385
			private IValueProperty text = new TextTextProperty(event);
386
387
			protected IValueProperty doGetDelegate(Object source) {
388
				if (source instanceof StyledText)
389
					return styledText;
390
				if (source instanceof Text)
391
					return text;
392
				throw notSupported(source);
393
			}
394
		};
395
	}
396
397
	/**
398
	 * Returns a value property for observing the tooltip text of a
399
	 * {@link CTabItem}, {@link Control}, {@link TabItem}, {@link TableColumn},
400
	 * {@link ToolItem}, {@link TrayItem}, {@link TreeColumn} or
401
	 * {@link TreeItem}.
402
	 * 
403
	 * @return a value property for observing the tooltip text of a
404
	 *         {@link CTabItem}, {@link Control}, {@link TabItem},
405
	 *         {@link TableColumn}, {@link ToolItem}, {@link TrayItem},
406
	 *         {@link TreeColumn} or {@link TreeItem}.
407
	 */
408
	public static IValueProperty tooltipText() {
409
		return new DelegatingValueProperty(String.class) {
410
			private IValueProperty cTabItem = new CTabItemTooltipTextProperty();
411
			private IValueProperty control = new ControlTooltipTextProperty();
412
			private IValueProperty tabItem = new TabItemTooltipTextProperty();
413
			private IValueProperty tableColumn = new TableColumnTooltipTextProperty();
414
			private IValueProperty toolItem = new ToolItemTooltipTextProperty();
415
			private IValueProperty trayItem = new TrayItemTooltipTextProperty();
416
			private IValueProperty treeItem = new TreeItemTooltipTextProperty();
417
418
			protected IValueProperty doGetDelegate(Object source) {
419
				if (source instanceof CTabItem)
420
					return cTabItem;
421
				if (source instanceof Control)
422
					return control;
423
				if (source instanceof TabItem)
424
					return tabItem;
425
				if (source instanceof TableColumn)
426
					return tableColumn;
427
				if (source instanceof ToolItem)
428
					return toolItem;
429
				if (source instanceof TrayItem)
430
					return trayItem;
431
				if (source instanceof TreeItem)
432
					return treeItem;
433
				throw notSupported(source);
434
			}
435
		};
436
	}
437
438
	/**
439
	 * Returns a value property for observing the visibility state of a
440
	 * {@link Control}.
441
	 * 
442
	 * @return a value property for observing the visibility state of a
443
	 *         {@link Control}.
444
	 */
445
	public static IValueProperty visible() {
446
		return new ControlVisibleProperty();
447
	}
448
}
(-)src/org/eclipse/jface/internal/databinding/swt/ItemTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Item;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class ItemTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((Item) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((Item) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "Item.text <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/LinkTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Link;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class LinkTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((Link) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((Link) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "Link.text <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/TableColumnTooltipTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.TableColumn;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class TableColumnTooltipTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((TableColumn) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((TableColumn) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "TableColumn.tooltipText <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlBackgroundProperty.java (+38 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.swt.graphics.Color;
16
import org.eclipse.swt.widgets.Control;
17
18
/**
19
 * @since 3.3
20
 * 
21
 */
22
public class ControlBackgroundProperty extends WidgetValueProperty {
23
	public Object getValueType() {
24
		return Color.class;
25
	}
26
27
	protected Object doGetValue(Object source) {
28
		return ((Control) source).getBackground();
29
	}
30
31
	protected void doSetValue(Object source, Object value) {
32
		((Control) source).setBackground((Color) value);
33
	}
34
35
	public String toString() {
36
		return "Control.background <Color>"; //$NON-NLS-1$
37
	}
38
}
(-)src/org/eclipse/jface/internal/databinding/swt/ComboSelectionProperty.java (+55 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.Combo;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ComboSelectionProperty extends WidgetStringValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public ComboSelectionProperty() {
26
		super(SWT.Modify);
27
	}
28
29
	String doGetStringValue(Object source) {
30
		return ((Combo) source).getText();
31
	}
32
33
	void doSetStringValue(Object source, String value) {
34
		Combo combo = (Combo) source;
35
		String items[] = combo.getItems();
36
		int index = -1;
37
		if (items != null && value != null) {
38
			for (int i = 0; i < items.length; i++) {
39
				if (value.equals(items[i])) {
40
					index = i;
41
					break;
42
				}
43
			}
44
			if (index == -1) {
45
				combo.setText(value);
46
			} else {
47
				combo.select(index); // -1 will not "unselect"
48
			}
49
		}
50
	}
51
52
	public String toString() {
53
		return "Combo.selection <String>"; //$NON-NLS-1$
54
	}
55
}
(-)src/org/eclipse/jface/internal/databinding/viewers/CheckboxTreeViewerCheckedElementsProperty.java (+57 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import java.util.Arrays;
15
import java.util.Set;
16
17
import org.eclipse.core.databinding.observable.set.SetDiff;
18
import org.eclipse.jface.viewers.CheckboxTreeViewer;
19
import org.eclipse.jface.viewers.ICheckable;
20
21
/**
22
 * @since 3.3
23
 * 
24
 */
25
public class CheckboxTreeViewerCheckedElementsProperty extends
26
		CheckableCheckedElementsProperty {
27
	/**
28
	 * @param elementType
29
	 */
30
	public CheckboxTreeViewerCheckedElementsProperty(Object elementType) {
31
		super(elementType);
32
	}
33
34
	protected Set createElementSet(ICheckable checkable) {
35
		return ViewerElementSet.withComparer(((CheckboxTreeViewer) checkable)
36
				.getComparer());
37
	}
38
39
	protected Set doGetSet(ICheckable checkable) {
40
		CheckboxTreeViewer viewer = (CheckboxTreeViewer) checkable;
41
		Set set = createElementSet(viewer);
42
		set.addAll(Arrays.asList(viewer.getCheckedElements()));
43
		return set;
44
	}
45
46
	protected void doSetSet(Object source, Set set, SetDiff diff) {
47
		CheckboxTreeViewer viewer = (CheckboxTreeViewer) source;
48
		viewer.setCheckedElements(set.toArray());
49
	}
50
51
	public String toString() {
52
		String s = "CheckboxTreeViewer.checkedElements{}"; //$NON-NLS-1$
53
		if (getElementType() != null)
54
			s += " <" + getElementType() + ">"; //$NON-NLS-1$//$NON-NLS-2$
55
		return s;
56
	}
57
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlStringListProperty.java (+56 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import java.util.Arrays;
16
import java.util.List;
17
18
import org.eclipse.core.databinding.observable.list.ListDiff;
19
import org.eclipse.core.databinding.property.INativePropertyListener;
20
import org.eclipse.core.databinding.property.ISimplePropertyListener;
21
import org.eclipse.swt.widgets.Control;
22
23
/**
24
 * @since 3.3
25
 * 
26
 */
27
public abstract class ControlStringListProperty extends WidgetListProperty {
28
	public Object getElementType() {
29
		return String.class;
30
	}
31
32
	protected void doSetList(Object source, List list, ListDiff diff) {
33
		String[] strings = (String[]) list.toArray(new String[list.size()]);
34
		doSetStringList((Control) source, strings);
35
	}
36
37
	abstract void doSetStringList(Control control, String[] list);
38
39
	protected List doGetList(Object source) {
40
		String[] list = doGetStringList((Control) source);
41
		return Arrays.asList(list);
42
	}
43
44
	abstract String[] doGetStringList(Control control);
45
46
	public INativePropertyListener adaptListener(
47
			ISimplePropertyListener listener) {
48
		return null;
49
	}
50
51
	public void doAddListener(Object source, INativePropertyListener listener) {
52
	}
53
54
	public void doRemoveListener(Object source, INativePropertyListener listener) {
55
	}
56
}
(-)src/org/eclipse/jface/internal/databinding/swt/CLabelTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.custom.CLabel;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class CLabelTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((CLabel) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((CLabel) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "CLabel.text <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerObservableSetDecorator.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import org.eclipse.core.databinding.observable.set.DecoratingObservableSet;
15
import org.eclipse.core.databinding.observable.set.IObservableSet;
16
import org.eclipse.jface.databinding.viewers.IViewerObservableSet;
17
import org.eclipse.jface.viewers.Viewer;
18
19
/**
20
 * @since 3.3
21
 * 
22
 */
23
public class ViewerObservableSetDecorator extends DecoratingObservableSet
24
		implements IViewerObservableSet {
25
	private final Viewer viewer;
26
27
	/**
28
	 * @param decorated
29
	 * @param viewer
30
	 */
31
	public ViewerObservableSetDecorator(IObservableSet decorated, Viewer viewer) {
32
		super(decorated, true);
33
		this.viewer = viewer;
34
	}
35
36
	public Viewer getViewer() {
37
		return viewer;
38
	}
39
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/CComboItemsProperty.java (+33 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.custom.CCombo;
15
import org.eclipse.swt.widgets.Control;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class CComboItemsProperty extends ControlStringListProperty {
22
	protected void doSetStringList(Control control, String[] list) {
23
		((CCombo) control).setItems(list);
24
	}
25
26
	public String[] doGetStringList(Control control) {
27
		return ((CCombo) control).getItems();
28
	}
29
30
	public String toString() {
31
		return "CCombo.items[] <String>"; //$NON-NLS-1$
32
	}
33
}
(-)src/org/eclipse/jface/internal/databinding/swt/ComboSingleSelectionIndexProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.Combo;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ComboSingleSelectionIndexProperty extends WidgetIntValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public ComboSingleSelectionIndexProperty() {
26
		super(new int[] { SWT.Selection, SWT.DefaultSelection });
27
	}
28
29
	int doGetIntValue(Object source) {
30
		return ((Combo) source).getSelectionIndex();
31
	}
32
33
	void doSetIntValue(Object source, int value) {
34
		((Combo) source).select(value);
35
	}
36
37
	public String toString() {
38
		return "Combo.selectionIndex <int>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/ToolItemTooltipTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.ToolItem;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class ToolItemTooltipTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((ToolItem) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((ToolItem) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "ToolItem.tooltipText <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/SWTVetoableValueDecorator.java (+148 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.IDecoratingObservable;
16
import org.eclipse.core.databinding.observable.IObservable;
17
import org.eclipse.core.databinding.observable.IStaleListener;
18
import org.eclipse.core.databinding.observable.ObservableTracker;
19
import org.eclipse.core.databinding.observable.StaleEvent;
20
import org.eclipse.core.databinding.observable.value.AbstractVetoableValue;
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
22
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
23
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
24
import org.eclipse.core.runtime.Assert;
25
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.widgets.Event;
28
import org.eclipse.swt.widgets.Listener;
29
import org.eclipse.swt.widgets.Widget;
30
31
/**
32
 * @since 3.3
33
 * 
34
 */
35
public class SWTVetoableValueDecorator extends AbstractVetoableValue implements
36
		ISWTObservableValue, IDecoratingObservable {
37
38
	private IObservableValue decorated;
39
	private Widget widget;
40
	private boolean updating;
41
42
	private IValueChangeListener valueListener = new IValueChangeListener() {
43
		public void handleValueChange(ValueChangeEvent event) {
44
			if (!updating)
45
				fireValueChange(event.diff);
46
		}
47
	};
48
49
	private IStaleListener staleListener = new IStaleListener() {
50
		public void handleStale(StaleEvent staleEvent) {
51
			fireStale();
52
		}
53
	};
54
55
	private Listener verifyListener = new Listener() {
56
		public void handleEvent(Event event) {
57
			String currentText = (String) decorated.getValue();
58
			String newText = currentText.substring(0, event.start) + event.text
59
					+ currentText.substring(event.end);
60
			if (!fireValueChanging(Diffs.createValueDiff(currentText, newText))) {
61
				event.doit = false;
62
			}
63
		}
64
	};
65
66
	private Listener disposeListener = new Listener() {
67
		public void handleEvent(Event event) {
68
			SWTVetoableValueDecorator.this.dispose();
69
		}
70
	};
71
72
	/**
73
	 * @param decorated
74
	 * @param widget
75
	 */
76
	public SWTVetoableValueDecorator(IObservableValue decorated, Widget widget) {
77
		super(decorated.getRealm());
78
		this.decorated = decorated;
79
		this.widget = widget;
80
		Assert
81
				.isTrue(decorated.getValueType().equals(String.class),
82
						"SWTVetoableValueDecorator can only decorate observable values of String type"); //$NON-NLS-1$
83
		widget.addListener(SWT.Dispose, disposeListener);
84
	}
85
86
	private void getterCalled() {
87
		ObservableTracker.getterCalled(this);
88
	}
89
90
	protected void firstListenerAdded() {
91
		decorated.addValueChangeListener(valueListener);
92
		decorated.addStaleListener(staleListener);
93
		widget.addListener(SWT.Verify, verifyListener);
94
	}
95
96
	protected void lastListenerRemoved() {
97
		if (decorated != null) {
98
			decorated.removeValueChangeListener(valueListener);
99
			decorated.removeStaleListener(staleListener);
100
		}
101
		if (widget != null && !widget.isDisposed())
102
			widget.removeListener(SWT.Verify, verifyListener);
103
	}
104
105
	protected void doSetApprovedValue(Object value) {
106
		checkRealm();
107
		updating = true;
108
		try {
109
			decorated.setValue(value);
110
		} finally {
111
			updating = false;
112
		}
113
	}
114
115
	protected Object doGetValue() {
116
		getterCalled();
117
		return decorated.getValue();
118
	}
119
120
	public Object getValueType() {
121
		return decorated.getValueType();
122
	}
123
124
	public boolean isStale() {
125
		getterCalled();
126
		return decorated.isStale();
127
	}
128
129
	public void dispose() {
130
		if (decorated != null) {
131
			decorated.dispose();
132
			decorated = null;
133
		}
134
		if (widget != null && !widget.isDisposed()) {
135
			widget.removeListener(SWT.Verify, verifyListener);
136
		}
137
		this.widget = null;
138
		super.dispose();
139
	}
140
141
	public Widget getWidget() {
142
		return widget;
143
	}
144
145
	public IObservable getDecorated() {
146
		return decorated;
147
	}
148
}
(-)src/org/eclipse/jface/internal/databinding/swt/WidgetBooleanValueProperty.java (+49 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.swt;
14
15
/**
16
 * @since 3.3
17
 * 
18
 */
19
public abstract class WidgetBooleanValueProperty extends WidgetValueProperty {
20
	WidgetBooleanValueProperty() {
21
		super();
22
	}
23
24
	WidgetBooleanValueProperty(int event) {
25
		super(event);
26
	}
27
28
	WidgetBooleanValueProperty(int[] events) {
29
		super(events);
30
	}
31
32
	public Object getValueType() {
33
		return Boolean.TYPE;
34
	}
35
36
	protected Object doGetValue(Object source) {
37
		return doGetBooleanValue(source) ? Boolean.TRUE : Boolean.FALSE;
38
	}
39
40
	protected void doSetValue(Object source, Object value) {
41
		if (value == null)
42
			value = Boolean.FALSE;
43
		doSetBooleanValue(source, ((Boolean) value).booleanValue());
44
	}
45
46
	abstract boolean doGetBooleanValue(Object source);
47
48
	abstract void doSetBooleanValue(Object source, boolean value);
49
}
(-)src/org/eclipse/jface/internal/databinding/viewers/CheckableCheckedElementsProperty.java (+117 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.viewers;
14
15
import java.util.Collections;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.Set;
19
20
import org.eclipse.core.databinding.observable.Diffs;
21
import org.eclipse.core.databinding.observable.set.SetDiff;
22
import org.eclipse.core.databinding.property.INativePropertyListener;
23
import org.eclipse.core.databinding.property.ISimplePropertyListener;
24
import org.eclipse.core.databinding.property.SimplePropertyEvent;
25
import org.eclipse.jface.viewers.CheckStateChangedEvent;
26
import org.eclipse.jface.viewers.ICheckStateListener;
27
import org.eclipse.jface.viewers.ICheckable;
28
29
/**
30
 * @since 3.3
31
 * 
32
 */
33
public class CheckableCheckedElementsProperty extends ViewerSetProperty {
34
	private final Object elementType;
35
36
	/**
37
	 * @param elementType
38
	 */
39
	public CheckableCheckedElementsProperty(Object elementType) {
40
		this.elementType = elementType;
41
	}
42
43
	public Object getElementType() {
44
		return elementType;
45
	}
46
47
	protected Set doGetSet(Object source) {
48
		ICheckable checkable = (ICheckable) source;
49
50
		Set set = doGetSet(checkable);
51
		if (set == null) {
52
			set = createElementSet(checkable);
53
		}
54
55
		return set;
56
	}
57
58
	protected Set doGetSet(ICheckable checkable) {
59
		return null; // overridden by viewer-specific subclasses
60
	}
61
62
	protected Set createElementSet(ICheckable checkable) {
63
		return new HashSet();
64
	}
65
66
	protected void doSetSet(Object source, Set set, SetDiff diff) {
67
		ICheckable checkable = (ICheckable) source;
68
		for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) {
69
			checkable.setChecked(it.next(), true);
70
		}
71
		for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) {
72
			checkable.setChecked(it.next(), false);
73
		}
74
	}
75
76
	public INativePropertyListener adaptListener(
77
			ISimplePropertyListener listener) {
78
		return new CheckStateListener(listener);
79
	}
80
81
	public void doAddListener(Object source, INativePropertyListener listener) {
82
		((ICheckable) source)
83
				.addCheckStateListener((ICheckStateListener) listener);
84
	}
85
86
	public void doRemoveListener(Object source, INativePropertyListener listener) {
87
		((ICheckable) source)
88
				.removeCheckStateListener((ICheckStateListener) listener);
89
	}
90
91
	private class CheckStateListener implements INativePropertyListener,
92
			ICheckStateListener {
93
		private ISimplePropertyListener listener;
94
95
		private CheckStateListener(ISimplePropertyListener listener) {
96
			this.listener = listener;
97
		}
98
99
		public void checkStateChanged(CheckStateChangedEvent event) {
100
			Object element = event.getElement();
101
			boolean checked = event.getChecked();
102
			Set elementSet = Collections.singleton(element);
103
			Set additions = checked ? elementSet : Collections.EMPTY_SET;
104
			Set removals = checked ? Collections.EMPTY_SET : elementSet;
105
			SetDiff diff = Diffs.createSetDiff(additions, removals);
106
			listener.handlePropertyChange(new SimplePropertyEvent(event
107
					.getSource(), CheckableCheckedElementsProperty.this, diff));
108
		}
109
	}
110
111
	public String toString() {
112
		String s = "ICheckable.checkedElements{}"; //$NON-NLS-1$
113
		if (elementType != null)
114
			s += " <" + elementType + ">"; //$NON-NLS-1$//$NON-NLS-2$
115
		return s;
116
	}
117
}
(-)src/org/eclipse/jface/internal/databinding/swt/WidgetIntValueProperty.java (+47 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.swt;
14
15
/**
16
 * @since 3.3
17
 * 
18
 */
19
public abstract class WidgetIntValueProperty extends WidgetValueProperty {
20
	WidgetIntValueProperty() {
21
		super();
22
	}
23
24
	WidgetIntValueProperty(int event) {
25
		super(event);
26
	}
27
28
	WidgetIntValueProperty(int[] events) {
29
		super(events);
30
	}
31
32
	public Object getValueType() {
33
		return Integer.TYPE;
34
	}
35
36
	protected Object doGetValue(Object source) {
37
		return new Integer(doGetIntValue(source));
38
	}
39
40
	protected void doSetValue(Object source, Object value) {
41
		doSetIntValue(source, ((Integer) value).intValue());
42
	}
43
44
	abstract int doGetIntValue(Object source);
45
46
	abstract void doSetIntValue(Object source, int intValue);
47
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlSizeProperty.java (+47 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 *     Tom Schindl - initial API and implementation
11
 *     Matthew Hall - bug 195222
12
 ******************************************************************************/
13
14
package org.eclipse.jface.internal.databinding.swt;
15
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.graphics.Point;
18
import org.eclipse.swt.widgets.Control;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public class ControlSizeProperty extends WidgetValueProperty {
25
	/**
26
	 * 
27
	 */
28
	public ControlSizeProperty() {
29
		super(SWT.Resize);
30
	}
31
32
	public Object getValueType() {
33
		return Point.class;
34
	}
35
36
	protected Object doGetValue(Object source) {
37
		return ((Control) source).getSize();
38
	}
39
40
	protected void doSetValue(Object source, Object value) {
41
		((Control) source).setSize((Point) value);
42
	}
43
44
	public String toString() {
45
		return "Control.size <Point>"; //$NON-NLS-1$
46
	}
47
}
(-)src/org/eclipse/jface/internal/databinding/viewers/CheckboxTableViewerCheckedElementsProperty.java (+57 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import java.util.Arrays;
15
import java.util.Set;
16
17
import org.eclipse.core.databinding.observable.set.SetDiff;
18
import org.eclipse.jface.viewers.CheckboxTableViewer;
19
import org.eclipse.jface.viewers.ICheckable;
20
21
/**
22
 * @since 3.3
23
 * 
24
 */
25
public class CheckboxTableViewerCheckedElementsProperty extends
26
		CheckableCheckedElementsProperty {
27
	/**
28
	 * @param elementType
29
	 */
30
	public CheckboxTableViewerCheckedElementsProperty(Object elementType) {
31
		super(elementType);
32
	}
33
34
	protected Set createElementSet(ICheckable checkable) {
35
		return ViewerElementSet.withComparer(((CheckboxTableViewer) checkable)
36
				.getComparer());
37
	}
38
39
	protected Set doGetSet(ICheckable checkable) {
40
		CheckboxTableViewer viewer = (CheckboxTableViewer) checkable;
41
		Set set = createElementSet(viewer);
42
		set.addAll(Arrays.asList(viewer.getCheckedElements()));
43
		return set;
44
	}
45
46
	protected void doSetSet(Object source, Set set, SetDiff diff) {
47
		CheckboxTableViewer viewer = (CheckboxTableViewer) source;
48
		viewer.setCheckedElements(set.toArray());
49
	}
50
51
	public String toString() {
52
		String s = "CheckboxTableViewer.checkedElements{}"; //$NON-NLS-1$
53
		if (getElementType() != null)
54
			s += " <" + getElementType() + ">"; //$NON-NLS-1$//$NON-NLS-2$
55
		return s;
56
	}
57
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlVisibleProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Control;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class ControlVisibleProperty extends WidgetBooleanValueProperty {
21
	boolean doGetBooleanValue(Object source) {
22
		return ((Control) source).getVisible();
23
	}
24
25
	void doSetBooleanValue(Object source, boolean value) {
26
		((Control) source).setVisible(value);
27
	}
28
29
	public String toString() {
30
		return "Control.visible <boolean>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlTooltipTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Control;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class ControlTooltipTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((Control) source).getToolTipText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((Control) source).setToolTipText(value);
27
	}
28
29
	public String toString() {
30
		return "Control.tooltipText <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/databinding/viewers/ViewerProperties.java (+110 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.databinding.viewers;
13
14
import org.eclipse.core.databinding.property.list.IListProperty;
15
import org.eclipse.core.databinding.property.set.DelegatingSetProperty;
16
import org.eclipse.core.databinding.property.set.ISetProperty;
17
import org.eclipse.core.databinding.property.value.IValueProperty;
18
import org.eclipse.jface.internal.databinding.viewers.CheckableCheckedElementsProperty;
19
import org.eclipse.jface.internal.databinding.viewers.CheckboxTableViewerCheckedElementsProperty;
20
import org.eclipse.jface.internal.databinding.viewers.CheckboxTreeViewerCheckedElementsProperty;
21
import org.eclipse.jface.internal.databinding.viewers.SelectionProviderMultipleSelectionProperty;
22
import org.eclipse.jface.internal.databinding.viewers.SelectionProviderSingleSelectionProperty;
23
import org.eclipse.jface.internal.databinding.viewers.StructuredViewerFiltersProperty;
24
import org.eclipse.jface.internal.databinding.viewers.ViewerInputProperty;
25
import org.eclipse.jface.viewers.CheckboxTableViewer;
26
import org.eclipse.jface.viewers.CheckboxTreeViewer;
27
import org.eclipse.jface.viewers.ICheckable;
28
import org.eclipse.jface.viewers.ISelectionProvider;
29
import org.eclipse.jface.viewers.StructuredViewer;
30
import org.eclipse.jface.viewers.Viewer;
31
32
/**
33
 * A factory for creating properties of JFace {@link Viewer viewers}.
34
 * 
35
 * @since 1.3
36
 */
37
public class ViewerProperties {
38
	/**
39
	 * Returns a set property for observing the checked elements of a
40
	 * {@link CheckboxTableViewer}, {@link CheckboxTreeViewer} or
41
	 * {@link ICheckable}.
42
	 * 
43
	 * @param elementType
44
	 *            the element type of the returned property
45
	 * 
46
	 * @return a set property for observing the checked elements of a
47
	 *         {@link CheckboxTableViewer}, {@link CheckboxTreeViewer} or
48
	 *         {@link ICheckable}.
49
	 */
50
	public static ISetProperty checkedElements(final Object elementType) {
51
		return new DelegatingSetProperty(elementType) {
52
			ISetProperty checkable = new CheckableCheckedElementsProperty(
53
					elementType);
54
			ISetProperty checkboxTableViewer = new CheckboxTableViewerCheckedElementsProperty(
55
					elementType);
56
			ISetProperty checkboxTreeViewer = new CheckboxTreeViewerCheckedElementsProperty(
57
					elementType);
58
59
			protected ISetProperty doGetDelegate(Object source) {
60
				if (source instanceof CheckboxTableViewer)
61
					return checkboxTableViewer;
62
				if (source instanceof CheckboxTreeViewer)
63
					return checkboxTreeViewer;
64
				return checkable;
65
			}
66
		};
67
	}
68
69
	/**
70
	 * Returns a value property for observing the input of a
71
	 * {@link StructuredViewer}.
72
	 * 
73
	 * @return a value property for observing the input of a
74
	 *         {@link StructuredViewer}.
75
	 */
76
	public static ISetProperty filters() {
77
		return new StructuredViewerFiltersProperty();
78
	}
79
80
	/**
81
	 * Returns a value property for observing the input of a {@link Viewer}.
82
	 * 
83
	 * @return a value property for observing the input of a {@link Viewer}.
84
	 */
85
	public static IValueProperty input() {
86
		return new ViewerInputProperty();
87
	}
88
89
	/**
90
	 * Returns a list property for observing the multiple selection of an
91
	 * {@link ISelectionProvider}.
92
	 * 
93
	 * @return a list property for observing the multiple selection of an
94
	 *         {@link ISelectionProvider}.
95
	 */
96
	public static IListProperty multipleSelection() {
97
		return new SelectionProviderMultipleSelectionProperty();
98
	}
99
100
	/**
101
	 * Returns a value property for observing the single selection of a
102
	 * {@link ISelectionProvider}.
103
	 * 
104
	 * @return a value property for observing the single selection of a
105
	 *         {@link ISelectionProvider}.
106
	 */
107
	public static IValueProperty singleSelection() {
108
		return new SelectionProviderSingleSelectionProperty();
109
	}
110
}
(-)src/org/eclipse/jface/internal/databinding/swt/ListSingleSelectionIndexProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.List;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ListSingleSelectionIndexProperty extends WidgetIntValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public ListSingleSelectionIndexProperty() {
26
		super(new int[] { SWT.Selection, SWT.DefaultSelection });
27
	}
28
29
	int doGetIntValue(Object source) {
30
		return ((List) source).getSelectionIndex();
31
	}
32
33
	void doSetIntValue(Object source, int value) {
34
		((List) source).setSelection(value);
35
	}
36
37
	public String toString() {
38
		return "List.selectionIndex <int>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/CComboSelectionProperty.java (+57 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.custom.CCombo;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class CComboSelectionProperty extends WidgetStringValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public CComboSelectionProperty() {
26
		super(SWT.Modify);
27
	}
28
29
	String doGetStringValue(Object source) {
30
		return ((CCombo) source).getText();
31
	}
32
33
	void doSetStringValue(Object source, String value) {
34
		CCombo ccombo = (CCombo) source;
35
		String items[] = ccombo.getItems();
36
		int index = -1;
37
		if (value == null) {
38
			ccombo.select(-1);
39
		} else if (items != null) {
40
			for (int i = 0; i < items.length; i++) {
41
				if (value.equals(items[i])) {
42
					index = i;
43
					break;
44
				}
45
			}
46
			if (index == -1) {
47
				ccombo.setText(value);
48
			} else {
49
				ccombo.select(index); // -1 will not "unselect"
50
			}
51
		}
52
	}
53
54
	public String toString() {
55
		return "CCombo.selection <String>"; //$NON-NLS-1$
56
	}
57
}
(-)src/org/eclipse/jface/internal/databinding/swt/SpinnerSelectionProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.Spinner;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class SpinnerSelectionProperty extends WidgetIntValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public SpinnerSelectionProperty() {
26
		super(SWT.Modify);
27
	}
28
29
	int doGetIntValue(Object source) {
30
		return ((Spinner) source).getSelection();
31
	}
32
33
	void doSetIntValue(Object source, int value) {
34
		((Spinner) source).setSelection(value);
35
	}
36
37
	public String toString() {
38
		return "Spinner.selection <int>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlBoundsProperty.java (+47 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 *     Tom Schindl - initial API and implementation
11
 *     Matthew Hall - bug 195222
12
 ******************************************************************************/
13
14
package org.eclipse.jface.internal.databinding.swt;
15
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.graphics.Rectangle;
18
import org.eclipse.swt.widgets.Control;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public class ControlBoundsProperty extends WidgetValueProperty {
25
	/**
26
	 * 
27
	 */
28
	public ControlBoundsProperty() {
29
		super(new int[] { SWT.Resize, SWT.Move });
30
	}
31
32
	public Object getValueType() {
33
		return Rectangle.class;
34
	}
35
36
	protected Object doGetValue(Object source) {
37
		return ((Control) source).getBounds();
38
	}
39
40
	protected void doSetValue(Object source, Object value) {
41
		((Control) source).setBounds((Rectangle) value);
42
	}
43
44
	public String toString() {
45
		return "Control.bounds <Rectangle>"; //$NON-NLS-1$
46
	}
47
}
(-)src/org/eclipse/jface/internal/databinding/swt/ComboTextProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.Combo;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ComboTextProperty extends WidgetStringValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public ComboTextProperty() {
26
		super(SWT.Modify);
27
	}
28
29
	String doGetStringValue(Object source) {
30
		return ((Combo) source).getText();
31
	}
32
33
	void doSetStringValue(Object source, String value) {
34
		((Combo) source).setText(value != null ? value : ""); //$NON-NLS-1$
35
	}
36
37
	public String toString() {
38
		return "Combo.text <String>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/StyledTextTextProperty.java (+60 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.value.IObservableValue;
15
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.custom.StyledText;
18
import org.eclipse.swt.widgets.Widget;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public class StyledTextTextProperty extends WidgetStringValueProperty {
25
	/**
26
	 * @param event
27
	 */
28
	public StyledTextTextProperty(int event) {
29
		super(checkEvent(event));
30
	}
31
32
	private static int checkEvent(int event) {
33
		switch (event) {
34
		case SWT.None:
35
		case SWT.Modify:
36
		case SWT.FocusOut:
37
			return event;
38
		default:
39
			throw new IllegalArgumentException("UpdateEventType [" //$NON-NLS-1$
40
					+ event + "] is not supported."); //$NON-NLS-1$
41
		}
42
	}
43
44
	String doGetStringValue(Object source) {
45
		return ((StyledText) source).getText();
46
	}
47
48
	void doSetStringValue(Object source, String value) {
49
		((StyledText) source).setText(value == null ? "" : value); //$NON-NLS-1$
50
	}
51
52
	public String toString() {
53
		return "StyledText.text <String>"; //$NON-NLS-1$
54
	}
55
56
	protected ISWTObservableValue wrapObservable(IObservableValue observable,
57
			Widget widget) {
58
		return new SWTVetoableValueDecorator(observable, widget);
59
	}
60
}
(-)src/org/eclipse/jface/internal/databinding/swt/LabelTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Label;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class LabelTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((Label) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((Label) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "Label.text <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/TextTextProperty.java (+60 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.value.IObservableValue;
15
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.widgets.Text;
18
import org.eclipse.swt.widgets.Widget;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public class TextTextProperty extends WidgetStringValueProperty {
25
	/**
26
	 * @param event
27
	 */
28
	public TextTextProperty(int event) {
29
		super(checkEvent(event));
30
	}
31
32
	private static int checkEvent(int event) {
33
		switch (event) {
34
		case SWT.None:
35
		case SWT.Modify:
36
		case SWT.FocusOut:
37
			return event;
38
		default:
39
			throw new IllegalArgumentException("UpdateEventType [" //$NON-NLS-1$
40
					+ event + "] is not supported."); //$NON-NLS-1$
41
		}
42
	}
43
44
	String doGetStringValue(Object source) {
45
		return ((Text) source).getText();
46
	}
47
48
	void doSetStringValue(Object source, String value) {
49
		((Text) source).setText(value == null ? "" : value); //$NON-NLS-1$
50
	}
51
52
	public String toString() {
53
		return "Text.text <String>"; //$NON-NLS-1$
54
	}
55
56
	protected ISWTObservableValue wrapObservable(IObservableValue observable,
57
			Widget widget) {
58
		return new SWTVetoableValueDecorator(observable, widget);
59
	}
60
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerValueProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.value.IObservableValue;
16
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
17
import org.eclipse.jface.databinding.swt.SWTObservables;
18
import org.eclipse.jface.viewers.Viewer;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public abstract class ViewerValueProperty extends SimpleValueProperty {
25
	public IObservableValue observe(Object source) {
26
		if (source instanceof Viewer) {
27
			return observe(SWTObservables.getRealm(((Viewer) source)
28
					.getControl().getDisplay()), source);
29
		}
30
		return super.observe(source);
31
	}
32
33
	public IObservableValue observe(Realm realm, Object source) {
34
		IObservableValue observable = super.observe(realm, source);
35
		if (source instanceof Viewer)
36
			observable = new ViewerObservableValueDecorator(observable,
37
					(Viewer) source);
38
		return observable;
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/SpinnerMaximumProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Spinner;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class SpinnerMaximumProperty extends WidgetIntValueProperty {
21
	int doGetIntValue(Object source) {
22
		return ((Spinner) source).getMaximum();
23
	}
24
25
	void doSetIntValue(Object source, int value) {
26
		((Spinner) source).setMaximum(value);
27
	}
28
29
	public String toString() {
30
		return "Spinner.maximum <int>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/WidgetListProperty.java (+36 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.list.IObservableList;
16
import org.eclipse.core.databinding.property.list.SimpleListProperty;
17
import org.eclipse.jface.databinding.swt.SWTObservables;
18
import org.eclipse.swt.widgets.Widget;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public abstract class WidgetListProperty extends SimpleListProperty {
25
	public IObservableList observe(Object source) {
26
		if (source instanceof Widget) {
27
			return observe(SWTObservables.getRealm(((Widget) source)
28
					.getDisplay()), source);
29
		}
30
		return super.observe(source);
31
	}
32
33
	public IObservableList observe(Realm realm, Object source) {
34
		return new SWTObservableListDecorator(super.observe(realm, source), (Widget) source);
35
	}
36
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerListProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.list.IObservableList;
16
import org.eclipse.core.databinding.property.list.SimpleListProperty;
17
import org.eclipse.jface.databinding.swt.SWTObservables;
18
import org.eclipse.jface.viewers.Viewer;
19
20
/**
21
 * @since 3.3
22
 * 
23
 */
24
public abstract class ViewerListProperty extends SimpleListProperty {
25
	public IObservableList observe(Object source) {
26
		if (source instanceof Viewer) {
27
			return observe(SWTObservables.getRealm(((Viewer) source)
28
					.getControl().getDisplay()), source);
29
		}
30
		return super.observe(source);
31
	}
32
33
	public IObservableList observe(Realm realm, Object source) {
34
		IObservableList observable = super.observe(realm, source);
35
		if (source instanceof Viewer)
36
			observable = new ViewerObservableListDecorator(observable,
37
					(Viewer) source);
38
		return observable;
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerObservableListDecorator.java (+41 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.viewers;
13
14
import org.eclipse.core.databinding.observable.list.DecoratingObservableList;
15
import org.eclipse.core.databinding.observable.list.IObservableList;
16
import org.eclipse.jface.databinding.viewers.IViewerObservableList;
17
import org.eclipse.jface.viewers.Viewer;
18
19
/**
20
 * @since 3.3
21
 * 
22
 */
23
public class ViewerObservableListDecorator extends DecoratingObservableList
24
		implements IViewerObservableList {
25
	private final Viewer viewer;
26
27
	/**
28
	 * @param decorated
29
	 * @param viewer
30
	 */
31
	public ViewerObservableListDecorator(IObservableList decorated,
32
			Viewer viewer) {
33
		super(decorated, true);
34
		this.viewer = viewer;
35
	}
36
37
	public Viewer getViewer() {
38
		return viewer;
39
	}
40
41
}
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerInputProperty.java (+51 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.viewers;
14
15
import org.eclipse.core.databinding.property.INativePropertyListener;
16
import org.eclipse.core.databinding.property.ISimplePropertyListener;
17
import org.eclipse.jface.viewers.Viewer;
18
19
/**
20
 * @since 3.3
21
 * 
22
 */
23
public class ViewerInputProperty extends ViewerValueProperty {
24
	public Object getValueType() {
25
		return null;
26
	}
27
28
	protected Object doGetValue(Object source) {
29
		return ((Viewer) source).getInput();
30
	}
31
32
	protected void doSetValue(Object source, Object value) {
33
		((Viewer) source).setInput(value);
34
	}
35
36
	public INativePropertyListener adaptListener(
37
			ISimplePropertyListener listener) {
38
		return null;
39
	}
40
41
	protected void doAddListener(Object source, INativePropertyListener listener) {
42
	}
43
44
	protected void doRemoveListener(Object source,
45
			INativePropertyListener listener) {
46
	}
47
48
	public String toString() {
49
		return "Viewer.input"; //$NON-NLS-1$
50
	}
51
}
(-)src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderSingleSelectionProperty.java (+84 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.viewers;
14
15
import org.eclipse.core.databinding.property.INativePropertyListener;
16
import org.eclipse.core.databinding.property.ISimplePropertyListener;
17
import org.eclipse.core.databinding.property.SimplePropertyEvent;
18
import org.eclipse.jface.viewers.ISelection;
19
import org.eclipse.jface.viewers.ISelectionChangedListener;
20
import org.eclipse.jface.viewers.ISelectionProvider;
21
import org.eclipse.jface.viewers.IStructuredSelection;
22
import org.eclipse.jface.viewers.SelectionChangedEvent;
23
import org.eclipse.jface.viewers.StructuredSelection;
24
25
/**
26
 * @since 3.3
27
 * 
28
 */
29
public class SelectionProviderSingleSelectionProperty extends
30
		ViewerValueProperty {
31
	public Object getValueType() {
32
		return null;
33
	}
34
35
	protected Object doGetValue(Object source) {
36
		ISelection selection = ((ISelectionProvider) source).getSelection();
37
		if (selection instanceof IStructuredSelection) {
38
			return ((IStructuredSelection) selection).getFirstElement();
39
		}
40
		return null;
41
	}
42
43
	protected void doSetValue(Object source, Object value) {
44
		((ISelectionProvider) source)
45
				.setSelection(value == null ? StructuredSelection.EMPTY
46
						: new StructuredSelection(value));
47
	}
48
49
	public INativePropertyListener adaptListener(
50
			ISimplePropertyListener listener) {
51
		return new SelectionChangedListener(listener);
52
	}
53
54
	protected void doAddListener(Object source, INativePropertyListener listener) {
55
		((ISelectionProvider) source)
56
				.addSelectionChangedListener((ISelectionChangedListener) listener);
57
	}
58
59
	protected void doRemoveListener(Object source,
60
			INativePropertyListener listener) {
61
		((ISelectionProvider) source)
62
				.removeSelectionChangedListener((ISelectionChangedListener) listener);
63
64
	}
65
66
	private class SelectionChangedListener implements INativePropertyListener,
67
			ISelectionChangedListener {
68
		private ISimplePropertyListener listener;
69
70
		private SelectionChangedListener(ISimplePropertyListener listener) {
71
			this.listener = listener;
72
		}
73
74
		public void selectionChanged(SelectionChangedEvent event) {
75
			listener.handlePropertyChange(new SimplePropertyEvent(event
76
					.getSource(),
77
					SelectionProviderSingleSelectionProperty.this, null));
78
		}
79
	}
80
81
	public String toString() {
82
		return "ISelectionProvider.selection"; //$NON-NLS-1$
83
	}
84
}
(-)src/org/eclipse/jface/internal/databinding/swt/ComboItemsProperty.java (+33 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Combo;
15
import org.eclipse.swt.widgets.Control;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ComboItemsProperty extends ControlStringListProperty {
22
	protected void doSetStringList(Control control, String[] list) {
23
		((Combo) control).setItems(list);
24
	}
25
26
	public String[] doGetStringList(Control control) {
27
		return ((Combo) control).getItems();
28
	}
29
30
	public String toString() {
31
		return "Combo.items[] <String>"; //$NON-NLS-1$
32
	}
33
}
(-)src/org/eclipse/jface/internal/databinding/viewers/StructuredViewerFiltersProperty.java (+64 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.viewers;
14
15
import java.util.Arrays;
16
import java.util.HashSet;
17
import java.util.Set;
18
19
import org.eclipse.core.databinding.observable.set.SetDiff;
20
import org.eclipse.core.databinding.property.INativePropertyListener;
21
import org.eclipse.core.databinding.property.ISimplePropertyListener;
22
import org.eclipse.jface.viewers.StructuredViewer;
23
import org.eclipse.jface.viewers.ViewerFilter;
24
25
/**
26
 * @since 3.3
27
 * 
28
 */
29
public class StructuredViewerFiltersProperty extends ViewerSetProperty {
30
	public Object getElementType() {
31
		return ViewerFilter.class;
32
	}
33
34
	protected Set doGetSet(Object source) {
35
		return new HashSet(Arrays.asList(((StructuredViewer) source)
36
				.getFilters()));
37
	}
38
39
	public void doSetSet(Object source, Set set, SetDiff diff) {
40
		StructuredViewer viewer = (StructuredViewer) source;
41
		viewer.getControl().setRedraw(false);
42
		try {
43
			viewer.setFilters((ViewerFilter[]) set.toArray(new ViewerFilter[set
44
					.size()]));
45
		} finally {
46
			viewer.getControl().setRedraw(true);
47
		}
48
	}
49
50
	public INativePropertyListener adaptListener(
51
			ISimplePropertyListener listener) {
52
		return null;
53
	}
54
55
	public void doAddListener(Object source, INativePropertyListener listener) {
56
	}
57
58
	public void doRemoveListener(Object source, INativePropertyListener listener) {
59
	}
60
61
	public String toString() {
62
		return "StructuredViewer.filters{} <ViewerFilter>"; //$NON-NLS-1$
63
	}
64
}
(-)src/org/eclipse/jface/internal/databinding/swt/ListItemsProperty.java (+33 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Control;
15
import org.eclipse.swt.widgets.List;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ListItemsProperty extends ControlStringListProperty {
22
	protected void doSetStringList(Control control, String[] list) {
23
		((List) control).setItems(list);
24
	}
25
26
	public String[] doGetStringList(Control control) {
27
		return ((List) control).getItems();
28
	}
29
30
	public String toString() {
31
		return "List.items[] <String>"; //$NON-NLS-1$
32
	}
33
}
(-)src/org/eclipse/jface/internal/databinding/swt/CComboSingleSelectionIndexProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.custom.CCombo;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class CComboSingleSelectionIndexProperty extends WidgetIntValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public CComboSingleSelectionIndexProperty() {
26
		super(new int[] { SWT.Selection, SWT.DefaultSelection });
27
	}
28
29
	int doGetIntValue(Object source) {
30
		return ((CCombo) source).getSelectionIndex();
31
	}
32
33
	void doSetIntValue(Object source, int value) {
34
		((CCombo) source).select(value);
35
	}
36
37
	public String toString() {
38
		return "CCombo.selectionIndex <int>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/ControlForegroundProperty.java (+38 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.swt;
14
15
import org.eclipse.swt.graphics.Color;
16
import org.eclipse.swt.widgets.Control;
17
18
/**
19
 * @since 3.3
20
 * 
21
 */
22
public class ControlForegroundProperty extends WidgetValueProperty {
23
	public Object getValueType() {
24
		return Color.class;
25
	}
26
27
	protected Object doGetValue(Object source) {
28
		return ((Control) source).getForeground();
29
	}
30
31
	protected void doSetValue(Object source, Object value) {
32
		((Control) source).setForeground((Color) value);
33
	}
34
35
	public String toString() {
36
		return "Control.foreground <Color>"; //$NON-NLS-1$
37
	}
38
}
(-)src/org/eclipse/jface/internal/databinding/swt/ScaleMinimumProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Scale;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class ScaleMinimumProperty extends WidgetIntValueProperty {
21
	int doGetIntValue(Object source) {
22
		return ((Scale) source).getMinimum();
23
	}
24
25
	void doSetIntValue(Object source, int value) {
26
		((Scale) source).setMinimum(value);
27
	}
28
29
	public String toString() {
30
		return "Scale.minimum <int>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/WidgetStringValueProperty.java (+43 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.internal.databinding.swt;
14
15
/**
16
 * @since 3.3
17
 * 
18
 */
19
public abstract class WidgetStringValueProperty extends WidgetValueProperty {
20
	WidgetStringValueProperty() {
21
		super();
22
	}
23
24
	WidgetStringValueProperty(int event) {
25
		super(event);
26
	}
27
28
	public Object getValueType() {
29
		return String.class;
30
	}
31
32
	protected Object doGetValue(Object source) {
33
		return doGetStringValue(source);
34
	}
35
36
	protected void doSetValue(Object source, Object value) {
37
		doSetStringValue(source, (String) value);
38
	}
39
40
	abstract String doGetStringValue(Object source);
41
42
	abstract void doSetStringValue(Object source, String value);
43
}
(-)src/org/eclipse/jface/internal/databinding/swt/SpinnerMinimumProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Spinner;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class SpinnerMinimumProperty extends WidgetIntValueProperty {
21
	int doGetIntValue(Object source) {
22
		return ((Spinner) source).getMinimum();
23
	}
24
25
	void doSetIntValue(Object source, int value) {
26
		((Spinner) source).setMinimum(value);
27
	}
28
29
	public String toString() {
30
		return "Spinner.minimum <int>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ScaleSelectionProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.Scale;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class ScaleSelectionProperty extends WidgetIntValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public ScaleSelectionProperty() {
26
		super(SWT.Selection);
27
	}
28
29
	int doGetIntValue(Object source) {
30
		return ((Scale) source).getSelection();
31
	}
32
33
	void doSetIntValue(Object source, int value) {
34
		((Scale) source).setSelection(value);
35
	}
36
37
	public String toString() {
38
		return "Scale.selection <int>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/WidgetValueProperty.java (+101 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.value.IObservableValue;
16
import org.eclipse.core.databinding.property.INativePropertyListener;
17
import org.eclipse.core.databinding.property.ISimplePropertyListener;
18
import org.eclipse.core.databinding.property.SimplePropertyEvent;
19
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
20
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
21
import org.eclipse.jface.databinding.swt.SWTObservables;
22
import org.eclipse.swt.SWT;
23
import org.eclipse.swt.widgets.Event;
24
import org.eclipse.swt.widgets.Listener;
25
import org.eclipse.swt.widgets.Widget;
26
27
abstract class WidgetValueProperty extends SimpleValueProperty {
28
	private int[] events;
29
30
	WidgetValueProperty() {
31
		this(null);
32
	}
33
34
	WidgetValueProperty(int event) {
35
		this(new int[] { event });
36
	}
37
38
	WidgetValueProperty(int[] events) {
39
		this.events = events;
40
	}
41
42
	public INativePropertyListener adaptListener(
43
			ISimplePropertyListener listener) {
44
		return new WidgetListener(listener);
45
	}
46
47
	protected void doAddListener(Object source, INativePropertyListener listener) {
48
		if (events != null) {
49
			for (int i = 0; i < events.length; i++) {
50
				int event = events[i];
51
				if (event != SWT.None) {
52
					((Widget) source).addListener(event, (Listener) listener);
53
				}
54
			}
55
		}
56
	}
57
58
	protected void doRemoveListener(Object source,
59
			INativePropertyListener listener) {
60
		if (events != null) {
61
			Widget widget = (Widget) source;
62
			if (!widget.isDisposed()) {
63
				for (int i = 0; i < events.length; i++) {
64
					int event = events[i];
65
					if (event != SWT.None)
66
						widget.removeListener(event, (Listener) listener);
67
				}
68
			}
69
		}
70
	}
71
72
	private class WidgetListener implements INativePropertyListener, Listener {
73
		private final ISimplePropertyListener listener;
74
75
		protected WidgetListener(ISimplePropertyListener listener) {
76
			this.listener = listener;
77
		}
78
79
		public void handleEvent(Event event) {
80
			listener.handlePropertyChange(new SimplePropertyEvent(event.widget,
81
					WidgetValueProperty.this, null));
82
		}
83
	}
84
85
	public IObservableValue observe(Object source) {
86
		if (source instanceof Widget) {
87
			return observe(SWTObservables.getRealm(((Widget) source)
88
					.getDisplay()), source);
89
		}
90
		return super.observe(source);
91
	}
92
93
	public IObservableValue observe(Realm realm, Object source) {
94
		return wrapObservable(super.observe(realm, source), (Widget) source);
95
	}
96
97
	protected ISWTObservableValue wrapObservable(IObservableValue observable,
98
			Widget widget) {
99
		return new SWTObservableValueDecorator(observable, widget);
100
	}
101
}
(-)src/org/eclipse/jface/internal/databinding/swt/TextEditableProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Text;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class TextEditableProperty extends WidgetBooleanValueProperty {
21
	boolean doGetBooleanValue(Object source) {
22
		return ((Text) source).getEditable();
23
	}
24
25
	void doSetBooleanValue(Object source, boolean value) {
26
		((Text) source).setEditable(value);
27
	}
28
29
	public String toString() {
30
		return "Text.editable <boolean>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/TrayItemTooltipTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.TrayItem;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class TrayItemTooltipTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((TrayItem) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((TrayItem) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "TrayItem.tooltipText <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/ShellTextProperty.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.widgets.Shell;
15
16
/**
17
 * @since 3.3
18
 * 
19
 */
20
public class ShellTextProperty extends WidgetStringValueProperty {
21
	String doGetStringValue(Object source) {
22
		return ((Shell) source).getText();
23
	}
24
25
	void doSetStringValue(Object source, String value) {
26
		((Shell) source).setText(value == null ? "" : value); //$NON-NLS-1$
27
	}
28
29
	public String toString() {
30
		return "Shell.text <String>"; //$NON-NLS-1$
31
	}
32
}
(-)src/org/eclipse/jface/internal/databinding/swt/TableSingleSelectionIndexProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.widgets.Table;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class TableSingleSelectionIndexProperty extends WidgetIntValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public TableSingleSelectionIndexProperty() {
26
		super(new int[] { SWT.Selection, SWT.DefaultSelection });
27
	}
28
29
	int doGetIntValue(Object source) {
30
		return ((Table) source).getSelectionIndex();
31
	}
32
33
	void doSetIntValue(Object source, int value) {
34
		((Table) source).setSelection(value);
35
	}
36
37
	public String toString() {
38
		return "Table.selectionIndex <int>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/internal/databinding/swt/CComboTextProperty.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.swt;
13
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.custom.CCombo;
16
17
/**
18
 * @since 3.3
19
 * 
20
 */
21
public class CComboTextProperty extends WidgetStringValueProperty {
22
	/**
23
	 * 
24
	 */
25
	public CComboTextProperty() {
26
		super(SWT.Modify);
27
	}
28
29
	String doGetStringValue(Object source) {
30
		return ((CCombo) source).getText();
31
	}
32
33
	void doSetStringValue(Object source, String value) {
34
		((CCombo) source).setText(value != null ? value : ""); //$NON-NLS-1$
35
	}
36
37
	public String toString() {
38
		return "CCombo.text <String>"; //$NON-NLS-1$
39
	}
40
}
(-)src/org/eclipse/jface/tests/databinding/swt/SWTObservablesTest.java (-62 / +124 lines)
Lines 7-45 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Chris Aniszczyk <zx@code9.com> - bug 131435
10
 *     Matthew Hall - bug 248621
11
 *     Matthew Hall - bug 248621
11
 ******************************************************************************/
12
 ******************************************************************************/
12
13
13
package org.eclipse.jface.tests.databinding.swt;
14
package org.eclipse.jface.tests.databinding.swt;
14
15
16
import org.eclipse.core.databinding.observable.IDecoratingObservable;
15
import org.eclipse.core.databinding.observable.list.IObservableList;
17
import org.eclipse.core.databinding.observable.list.IObservableList;
18
import org.eclipse.core.databinding.property.IPropertyObservable;
19
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
16
import org.eclipse.jface.databinding.conformance.util.RealmTester;
20
import org.eclipse.jface.databinding.conformance.util.RealmTester;
21
import org.eclipse.jface.databinding.swt.ISWTObservable;
17
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
22
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
18
import org.eclipse.jface.databinding.swt.SWTObservables;
23
import org.eclipse.jface.databinding.swt.SWTObservables;
19
import org.eclipse.jface.internal.databinding.swt.ButtonObservableValue;
24
import org.eclipse.jface.internal.databinding.swt.CComboSelectionProperty;
20
import org.eclipse.jface.internal.databinding.swt.CComboObservableList;
25
import org.eclipse.jface.internal.databinding.swt.CComboTextProperty;
21
import org.eclipse.jface.internal.databinding.swt.CComboObservableValue;
26
import org.eclipse.jface.internal.databinding.swt.CLabelTextProperty;
22
import org.eclipse.jface.internal.databinding.swt.CLabelObservableValue;
27
import org.eclipse.jface.internal.databinding.swt.CTabItemTooltipTextProperty;
23
import org.eclipse.jface.internal.databinding.swt.ComboObservableList;
28
import org.eclipse.jface.internal.databinding.swt.ComboSelectionProperty;
24
import org.eclipse.jface.internal.databinding.swt.ComboObservableValue;
29
import org.eclipse.jface.internal.databinding.swt.ComboTextProperty;
25
import org.eclipse.jface.internal.databinding.swt.ControlObservableValue;
30
import org.eclipse.jface.internal.databinding.swt.ControlTooltipTextProperty;
26
import org.eclipse.jface.internal.databinding.swt.ItemObservableValue;
31
import org.eclipse.jface.internal.databinding.swt.ItemTextProperty;
27
import org.eclipse.jface.internal.databinding.swt.ItemTooltipObservableValue;
32
import org.eclipse.jface.internal.databinding.swt.LabelTextProperty;
28
import org.eclipse.jface.internal.databinding.swt.LabelObservableValue;
33
import org.eclipse.jface.internal.databinding.swt.ScaleMaximumProperty;
29
import org.eclipse.jface.internal.databinding.swt.ListObservableList;
34
import org.eclipse.jface.internal.databinding.swt.ScaleMinimumProperty;
30
import org.eclipse.jface.internal.databinding.swt.ListObservableValue;
35
import org.eclipse.jface.internal.databinding.swt.ScaleSelectionProperty;
31
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
36
import org.eclipse.jface.internal.databinding.swt.SpinnerMaximumProperty;
32
import org.eclipse.jface.internal.databinding.swt.ScaleObservableValue;
37
import org.eclipse.jface.internal.databinding.swt.SpinnerMinimumProperty;
33
import org.eclipse.jface.internal.databinding.swt.SpinnerObservableValue;
38
import org.eclipse.jface.internal.databinding.swt.SpinnerSelectionProperty;
34
import org.eclipse.jface.internal.databinding.swt.TableSingleSelectionObservableValue;
39
import org.eclipse.jface.internal.databinding.swt.StyledTextTextProperty;
35
import org.eclipse.jface.internal.databinding.swt.TextEditableObservableValue;
40
import org.eclipse.jface.internal.databinding.swt.TableSingleSelectionIndexProperty;
36
import org.eclipse.jface.internal.databinding.swt.TextObservableValue;
41
import org.eclipse.jface.internal.databinding.swt.TextEditableProperty;
42
import org.eclipse.jface.internal.databinding.swt.TextTextProperty;
37
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
43
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
38
import org.eclipse.swt.SWT;
44
import org.eclipse.swt.SWT;
39
import org.eclipse.swt.custom.CCombo;
45
import org.eclipse.swt.custom.CCombo;
40
import org.eclipse.swt.custom.CLabel;
46
import org.eclipse.swt.custom.CLabel;
41
import org.eclipse.swt.custom.CTabFolder;
47
import org.eclipse.swt.custom.CTabFolder;
42
import org.eclipse.swt.custom.CTabItem;
48
import org.eclipse.swt.custom.CTabItem;
49
import org.eclipse.swt.custom.StyledText;
43
import org.eclipse.swt.graphics.Color;
50
import org.eclipse.swt.graphics.Color;
44
import org.eclipse.swt.graphics.Font;
51
import org.eclipse.swt.graphics.Font;
45
import org.eclipse.swt.widgets.Button;
52
import org.eclipse.swt.widgets.Button;
Lines 96-149 Link Here
96
		Spinner spinner = new Spinner(shell, SWT.NONE);
103
		Spinner spinner = new Spinner(shell, SWT.NONE);
97
		ISWTObservableValue value = SWTObservables.observeSelection(spinner);
104
		ISWTObservableValue value = SWTObservables.observeSelection(spinner);
98
		assertNotNull(value);
105
		assertNotNull(value);
99
		assertTrue(value instanceof SpinnerObservableValue);
106
		assertTrue(value.getWidget() == spinner);
100
107
101
		SpinnerObservableValue spinnerObservable = (SpinnerObservableValue) value;
108
		IPropertyObservable propertyObservable = getPropertyObservable(value);
102
		assertEquals(SWTProperties.SELECTION, spinnerObservable.getAttribute());
109
		assertTrue(propertyObservable.getProperty() instanceof SpinnerSelectionProperty);
103
	}
110
	}
104
111
105
	public void testObserveSelectionOfButton() throws Exception {
112
	public void testObserveSelectionOfButton() throws Exception {
106
		Button button = new Button(shell, SWT.PUSH);
113
		Button button = new Button(shell, SWT.PUSH);
107
		ISWTObservableValue value = SWTObservables.observeSelection(button);
114
		ISWTObservableValue value = SWTObservables.observeSelection(button);
108
		assertNotNull(value);
115
		assertNotNull(value);
109
		assertTrue(value instanceof ButtonObservableValue);
116
		assertTrue(value.getWidget() == button);
110
	}
117
	}
111
118
112
	public void testObserveSelectionOfCombo() throws Exception {
119
	public void testObserveSelectionOfCombo() throws Exception {
113
		Combo combo = new Combo(shell, SWT.NONE);
120
		Combo combo = new Combo(shell, SWT.NONE);
114
		ISWTObservableValue value = SWTObservables.observeSelection(combo);
121
		ISWTObservableValue value = SWTObservables.observeSelection(combo);
115
		assertNotNull(value);
122
		assertNotNull(value);
116
		assertTrue(value instanceof ComboObservableValue);
123
		assertTrue(value.getWidget() == combo);
117
124
118
		ComboObservableValue comboObservable = (ComboObservableValue) value;
125
		IPropertyObservable propertyObservable = getPropertyObservable(value);
119
		assertEquals(SWTProperties.SELECTION, comboObservable.getAttribute());
126
		assertTrue(propertyObservable.getProperty() instanceof ComboSelectionProperty);
120
	}
127
	}
121
128
122
	public void testObserveSelectionOfCCombo() throws Exception {
129
	public void testObserveSelectionOfCCombo() throws Exception {
123
		CCombo combo = new CCombo(shell, SWT.NONE);
130
		CCombo combo = new CCombo(shell, SWT.NONE);
124
		ISWTObservableValue value = SWTObservables.observeSelection(combo);
131
		ISWTObservableValue value = SWTObservables.observeSelection(combo);
125
		assertNotNull(value);
132
		assertNotNull(value);
126
		assertTrue(value instanceof CComboObservableValue);
133
		assertTrue(value.getWidget() == combo);
127
134
128
		CComboObservableValue ccomboObservable = (CComboObservableValue) value;
135
		IPropertyObservable property = getPropertyObservable(value);
129
		assertEquals(SWTProperties.SELECTION, ccomboObservable.getAttribute());
136
		assertTrue(property.getProperty() instanceof CComboSelectionProperty);
130
	}
137
	}
131
138
132
	public void testObserveSelectionOfList() throws Exception {
139
	public void testObserveSelectionOfList() throws Exception {
133
		List list = new List(shell, SWT.NONE);
140
		List list = new List(shell, SWT.NONE);
134
		ISWTObservableValue value = SWTObservables.observeSelection(list);
141
		ISWTObservableValue value = SWTObservables.observeSelection(list);
135
		assertNotNull(value);
142
		assertNotNull(value);
136
		assertTrue(value instanceof ListObservableValue);
143
		assertTrue(value.getWidget() == list);
137
	}
144
	}
138
	
145
	
139
	public void testObserveSelectionOfScale() throws Exception {
146
	public void testObserveSelectionOfScale() throws Exception {
140
		Scale scale = new Scale(shell, SWT.NONE);
147
		Scale scale = new Scale(shell, SWT.NONE);
141
		ISWTObservableValue value = SWTObservables.observeSelection(scale);
148
		ISWTObservableValue value = SWTObservables.observeSelection(scale);
142
		assertNotNull(value);
149
		assertNotNull(value);
143
		assertTrue(value instanceof ScaleObservableValue);
150
		assertTrue(value.getWidget() == scale);
144
		
151
		
145
		ScaleObservableValue scaleObservable = (ScaleObservableValue) value;
152
		IPropertyObservable property = getPropertyObservable(value);
146
		assertEquals(SWTProperties.SELECTION, scaleObservable.getAttribute());
153
		assertTrue(property.getProperty() instanceof ScaleSelectionProperty);
147
	}
154
	}
148
155
149
	public void testObserveSelectionOfUnsupportedControl() throws Exception {
156
	public void testObserveSelectionOfUnsupportedControl() throws Exception {
Lines 162-168 Link Here
162
		ISWTObservableValue value = SWTObservables.observeText(text,
169
		ISWTObservableValue value = SWTObservables.observeText(text,
163
				SWT.FocusOut);
170
				SWT.FocusOut);
164
		assertNotNull(value);
171
		assertNotNull(value);
165
		assertTrue(value instanceof TextObservableValue);
172
		assertTrue(value.getWidget() == text);
173
		IPropertyObservable propertyObservable = getPropertyObservable(value);
174
		assertTrue(propertyObservable.getProperty() instanceof TextTextProperty);
175
176
		assertFalse(text.isListening(SWT.FocusOut));
177
		ChangeEventTracker.observe(value);
178
		assertTrue(text.isListening(SWT.FocusOut));
179
	}
180
181
	public void testObserveTextOfStyledText() throws Exception {
182
		StyledText text = new StyledText(shell, SWT.NONE);
183
		assertFalse(text.isListening(SWT.FocusOut));
184
185
		ISWTObservableValue value = SWTObservables.observeText(text,
186
				SWT.FocusOut);
187
		assertNotNull(value);
188
		assertTrue(value.getWidget() == text);
189
		IPropertyObservable propertyObservable = getPropertyObservable(value);
190
		assertTrue(propertyObservable.getProperty() instanceof StyledTextTextProperty);
191
192
		assertFalse(text.isListening(SWT.FocusOut));
193
		ChangeEventTracker.observe(value);
166
		assertTrue(text.isListening(SWT.FocusOut));
194
		assertTrue(text.isListening(SWT.FocusOut));
167
	}
195
	}
168
196
Lines 179-219 Link Here
179
		Label label = new Label(shell, SWT.NONE);
207
		Label label = new Label(shell, SWT.NONE);
180
		ISWTObservableValue value = SWTObservables.observeText(label);
208
		ISWTObservableValue value = SWTObservables.observeText(label);
181
		assertNotNull(label);
209
		assertNotNull(label);
182
		assertTrue(value instanceof LabelObservableValue);
210
		assertTrue(value.getWidget() == label);
211
		IPropertyObservable propertyObservable = getPropertyObservable(value);
212
		assertTrue(propertyObservable.getProperty() instanceof LabelTextProperty);
183
	}
213
	}
184
214
185
	public void testObserveTextOfCLabel() throws Exception {
215
	public void testObserveTextOfCLabel() throws Exception {
186
		CLabel label = new CLabel(shell, SWT.NONE);
216
		CLabel label = new CLabel(shell, SWT.NONE);
187
		ISWTObservableValue value = SWTObservables.observeText(label);
217
		ISWTObservableValue value = SWTObservables.observeText(label);
188
		assertNotNull(label);
218
		assertNotNull(label);
189
		assertTrue(value instanceof CLabelObservableValue);
219
		assertTrue(value.getWidget() == label);
220
		IPropertyObservable propertyObservable = getPropertyObservable(value);
221
		assertTrue(propertyObservable.getProperty() instanceof CLabelTextProperty);
190
	}
222
	}
191
223
192
	public void testObserveTextOfCombo() throws Exception {
224
	public void testObserveTextOfCombo() throws Exception {
193
		Combo combo = new Combo(shell, SWT.NONE);
225
		Combo combo = new Combo(shell, SWT.NONE);
194
		ISWTObservableValue value = SWTObservables.observeText(combo);
226
		ISWTObservableValue value = SWTObservables.observeText(combo);
195
		assertNotNull(value);
227
		assertNotNull(value);
196
		assertTrue(value instanceof ComboObservableValue);
228
		assertTrue(value.getWidget() == combo);
197
229
198
		ComboObservableValue comboObservable = (ComboObservableValue) value;
230
		assertTrue(getPropertyObservable(value).getProperty() instanceof ComboTextProperty);
199
		assertEquals(SWTProperties.TEXT, comboObservable.getAttribute());
231
	}
232
233
	/**
234
	 * @param observable
235
	 * @return
236
	 */
237
	private IPropertyObservable getPropertyObservable(
238
			ISWTObservableValue observable) {
239
		IDecoratingObservable decoratingObservable = (IDecoratingObservable) observable;
240
		IPropertyObservable propertyObservable = (IPropertyObservable) decoratingObservable
241
				.getDecorated();
242
		return propertyObservable;
200
	}
243
	}
201
244
202
	public void testObserveTextOfCCombo() throws Exception {
245
	public void testObserveTextOfCCombo() throws Exception {
203
		CCombo combo = new CCombo(shell, SWT.NONE);
246
		CCombo combo = new CCombo(shell, SWT.NONE);
204
		ISWTObservableValue value = SWTObservables.observeText(combo);
247
		ISWTObservableValue value = SWTObservables.observeText(combo);
205
		assertNotNull(value);
248
		assertNotNull(value);
206
		assertTrue(value instanceof CComboObservableValue);
249
		assertTrue(value.getWidget() == combo);
207
250
208
		CComboObservableValue ccomboObservable = (CComboObservableValue) value;
251
		IDecoratingObservable decorating = (IDecoratingObservable) value;
209
		assertEquals(SWTProperties.TEXT, ccomboObservable.getAttribute());
252
		IPropertyObservable property = (IPropertyObservable) decorating
253
				.getDecorated();
254
		assertTrue(property.getProperty() instanceof CComboTextProperty);
210
	}
255
	}
211
256
212
	public void testObserveTextOfText() throws Exception {
257
	public void testObserveTextOfText() throws Exception {
213
		Text text = new Text(shell, SWT.NONE);
258
		Text text = new Text(shell, SWT.NONE);
214
		ISWTObservableValue value = SWTObservables.observeText(text);
259
		ISWTObservableValue value = SWTObservables.observeText(text);
215
		assertNotNull(value);
260
		assertNotNull(value);
216
		assertTrue(value instanceof TextObservableValue);
261
262
		assertTrue(value.getWidget() == text);
263
		IPropertyObservable propertyObservable = getPropertyObservable(value);
264
		assertTrue(propertyObservable.getProperty() instanceof TextTextProperty);
265
		
217
		assertFalse(text.isListening(SWT.Modify));
266
		assertFalse(text.isListening(SWT.Modify));
218
		assertFalse(text.isListening(SWT.FocusOut));
267
		assertFalse(text.isListening(SWT.FocusOut));
219
	}
268
	}
Lines 223-229 Link Here
223
		Item item = new CTabItem(ctf, SWT.NONE);
272
		Item item = new CTabItem(ctf, SWT.NONE);
224
		ISWTObservableValue value = SWTObservables.observeText(item);
273
		ISWTObservableValue value = SWTObservables.observeText(item);
225
		assertNotNull(value);
274
		assertNotNull(value);
226
		assertTrue(value instanceof ItemObservableValue);
275
		assertTrue(value.getWidget() == item);
276
		IPropertyObservable propertyObservable = getPropertyObservable(value);
277
		assertTrue(propertyObservable.getProperty() instanceof ItemTextProperty);
227
	}
278
	}
228
279
229
	public void testObserveTextOfUnsupportedControl() throws Exception {
280
	public void testObserveTextOfUnsupportedControl() throws Exception {
Lines 240-246 Link Here
240
		Item item = new CTabItem(ctf, SWT.NONE);
291
		Item item = new CTabItem(ctf, SWT.NONE);
241
		ISWTObservableValue value = SWTObservables.observeTooltipText(item);
292
		ISWTObservableValue value = SWTObservables.observeTooltipText(item);
242
		assertNotNull(value);
293
		assertNotNull(value);
243
		assertTrue(value instanceof ItemTooltipObservableValue);
294
		assertTrue(value.getWidget() == item);
295
		IPropertyObservable propertyObservable = getPropertyObservable(value);
296
		assertTrue(propertyObservable.getProperty() instanceof CTabItemTooltipTextProperty);
244
	}
297
	}
245
298
246
	public void testObserveTooltipOfUnsupportedControl() throws Exception {
299
	public void testObserveTooltipOfUnsupportedControl() throws Exception {
Lines 256-283 Link Here
256
		Label label = new Label(shell, SWT.NONE);
309
		Label label = new Label(shell, SWT.NONE);
257
		ISWTObservableValue value = SWTObservables.observeTooltipText(label);
310
		ISWTObservableValue value = SWTObservables.observeTooltipText(label);
258
		assertNotNull(value);
311
		assertNotNull(value);
259
		assertTrue(value instanceof ControlObservableValue);
312
		assertTrue(value.getWidget() == label);
313
		IPropertyObservable propertyObservable = getPropertyObservable(value);
314
		assertTrue(propertyObservable.getProperty() instanceof ControlTooltipTextProperty);
260
	}
315
	}
261
316
262
	public void testObserveItemsOfCombo() throws Exception {
317
	public void testObserveItemsOfCombo() throws Exception {
263
		Combo combo = new Combo(shell, SWT.NONE);
318
		Combo combo = new Combo(shell, SWT.NONE);
264
		IObservableList list = SWTObservables.observeItems(combo);
319
		IObservableList list = SWTObservables.observeItems(combo);
265
		assertNotNull(list);
320
		assertNotNull(list);
266
		assertTrue(list instanceof ComboObservableList);
321
		assertTrue(list instanceof ISWTObservable);
322
		assertTrue(((ISWTObservable) list).getWidget() == combo);
267
	}
323
	}
268
324
269
	public void testObserveItemsOfCCombo() throws Exception {
325
	public void testObserveItemsOfCCombo() throws Exception {
270
		CCombo ccombo = new CCombo(shell, SWT.NONE);
326
		CCombo ccombo = new CCombo(shell, SWT.NONE);
271
		IObservableList list = SWTObservables.observeItems(ccombo);
327
		IObservableList list = SWTObservables.observeItems(ccombo);
272
		assertNotNull(list);
328
		assertNotNull(list);
273
		assertTrue(list instanceof CComboObservableList);
329
		ISWTObservable swtObservable = (ISWTObservable) list;
330
		assertTrue(swtObservable.getWidget() == ccombo);
274
	}
331
	}
275
332
276
	public void testObserveItemsOfList() throws Exception {
333
	public void testObserveItemsOfList() throws Exception {
277
		List list = new List(shell, SWT.NONE);
334
		List list = new List(shell, SWT.NONE);
278
		IObservableList observableList = SWTObservables.observeItems(list);
335
		IObservableList observableList = SWTObservables.observeItems(list);
279
		assertNotNull(observableList);
336
		assertNotNull(observableList);
280
		assertTrue(observableList instanceof ListObservableList);
337
		ISWTObservable swtObservable = (ISWTObservable) observableList;
338
		assertTrue(swtObservable.getWidget() == list);
281
	}
339
	}
282
340
283
	public void testObserveItemsOfUnsupportedControl() throws Exception {
341
	public void testObserveItemsOfUnsupportedControl() throws Exception {
Lines 294-300 Link Here
294
		ISWTObservableValue value = SWTObservables
352
		ISWTObservableValue value = SWTObservables
295
				.observeSingleSelectionIndex(table);
353
				.observeSingleSelectionIndex(table);
296
		assertNotNull(value);
354
		assertNotNull(value);
297
		assertTrue(value instanceof TableSingleSelectionObservableValue);
355
		assertTrue(value.getWidget() == table);
356
		IPropertyObservable propertyObservable = getPropertyObservable(value);
357
		assertTrue(propertyObservable.getProperty() instanceof TableSingleSelectionIndexProperty);
298
	}
358
	}
299
359
300
	public void testObserveSingleSelectionIndexOfUnsupportedControl()
360
	public void testObserveSingleSelectionIndexOfUnsupportedControl()
Lines 312-331 Link Here
312
		Spinner spinner = new Spinner(shell, SWT.NONE);
372
		Spinner spinner = new Spinner(shell, SWT.NONE);
313
		ISWTObservableValue value = SWTObservables.observeMin(spinner);
373
		ISWTObservableValue value = SWTObservables.observeMin(spinner);
314
		assertNotNull(value);
374
		assertNotNull(value);
315
		assertTrue(value instanceof SpinnerObservableValue);
375
		assertTrue(value.getWidget() == spinner);
316
		
376
		
317
		SpinnerObservableValue spinnerObservable = (SpinnerObservableValue) value;
377
		IPropertyObservable propertyObservable = getPropertyObservable(value);
318
		assertEquals(SWTProperties.MIN, spinnerObservable.getAttribute());
378
		assertTrue(propertyObservable.getProperty() instanceof SpinnerMinimumProperty);
319
	}
379
	}
320
	
380
	
321
	public void testObserveMinOfScale() throws Exception {
381
	public void testObserveMinOfScale() throws Exception {
322
		Scale scale = new Scale(shell, SWT.NONE);
382
		Scale scale = new Scale(shell, SWT.NONE);
323
		ISWTObservableValue value = SWTObservables.observeMin(scale);
383
		ISWTObservableValue value = SWTObservables.observeMin(scale);
324
		assertNotNull(value);
384
		assertNotNull(value);
325
		assertTrue(value instanceof ScaleObservableValue);
385
		assertTrue(value.getWidget() == scale);
326
		
386
		
327
		ScaleObservableValue scaleObservable = (ScaleObservableValue) value;
387
		IPropertyObservable propertyObservable = getPropertyObservable(value);
328
		assertEquals(SWTProperties.MIN, scaleObservable.getAttribute());
388
		assertTrue(propertyObservable.getProperty() instanceof ScaleMinimumProperty);
329
	}
389
	}
330
390
331
	public void testObserveMinOfUnsupportedControl() throws Exception {
391
	public void testObserveMinOfUnsupportedControl() throws Exception {
Lines 341-360 Link Here
341
		Spinner spinner = new Spinner(shell, SWT.NONE);
401
		Spinner spinner = new Spinner(shell, SWT.NONE);
342
		ISWTObservableValue value = SWTObservables.observeMax(spinner);
402
		ISWTObservableValue value = SWTObservables.observeMax(spinner);
343
		assertNotNull(value);
403
		assertNotNull(value);
344
		assertTrue(value instanceof SpinnerObservableValue);
404
		assertTrue(value.getWidget() == spinner);
345
		
405
		
346
		SpinnerObservableValue spinnerObservable = (SpinnerObservableValue) value;
406
		IPropertyObservable propertyObservable = getPropertyObservable(value);
347
		assertEquals(SWTProperties.MAX, spinnerObservable.getAttribute());
407
		assertTrue(propertyObservable.getProperty() instanceof SpinnerMaximumProperty);
348
	}
408
	}
349
	
409
	
350
	public void testObserveMaxOfScale() throws Exception {
410
	public void testObserveMaxOfScale() throws Exception {
351
		Scale scale = new Scale(shell, SWT.NONE);
411
		Scale scale = new Scale(shell, SWT.NONE);
352
		ISWTObservableValue value = SWTObservables.observeMax(scale);
412
		ISWTObservableValue value = SWTObservables.observeMax(scale);
353
		assertNotNull(value);
413
		assertNotNull(value);
354
		assertTrue(value instanceof ScaleObservableValue);
414
		assertTrue(value.getWidget() == scale);
355
		
415
		
356
		ScaleObservableValue scaleObservable = (ScaleObservableValue) value;
416
		IPropertyObservable propertyObservable = getPropertyObservable(value);
357
		assertEquals(SWTProperties.MAX, scaleObservable.getAttribute());
417
		assertTrue(propertyObservable.getProperty() instanceof ScaleMaximumProperty);
358
	}
418
	}
359
	
419
	
360
	public void testObserveMaxOfUnsupportedControl() throws Exception {
420
	public void testObserveMaxOfUnsupportedControl() throws Exception {
Lines 370-376 Link Here
370
		Text text = new Text(shell, SWT.NONE);
430
		Text text = new Text(shell, SWT.NONE);
371
		ISWTObservableValue value = SWTObservables.observeEditable(text);
431
		ISWTObservableValue value = SWTObservables.observeEditable(text);
372
		assertNotNull(value);
432
		assertNotNull(value);
373
		assertTrue(value instanceof TextEditableObservableValue);
433
		assertTrue(value.getWidget() == text);
434
		IPropertyObservable propertyObservable = getPropertyObservable(value);
435
		assertTrue(propertyObservable.getProperty() instanceof TextEditableProperty);
374
	}
436
	}
375
	
437
	
376
	public void testObserveEditableOfUnsupportedControl() throws Exception {
438
	public void testObserveEditableOfUnsupportedControl() throws Exception {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ScaleObservableValueMaxTest.java (-6 / +7 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-29 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.jface.internal.databinding.swt.ScaleObservableValue;
27
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Scale;
28
import org.eclipse.swt.widgets.Scale;
Lines 73-81 Link Here
73
	}
72
	}
74
73
75
	public static Test suite() {
74
	public static Test suite() {
76
		TestSuite suite = new TestSuite(ScaleObservableValueMaxTest.class.toString());
75
		TestSuite suite = new TestSuite(ScaleObservableValueMaxTest.class
76
				.toString());
77
		suite.addTestSuite(ScaleObservableValueMaxTest.class);
77
		suite.addTestSuite(ScaleObservableValueMaxTest.class);
78
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
78
		suite.addTest(SWTMutableObservableValueContractTest
79
				.suite(new Delegate()));
79
		return suite;
80
		return suite;
80
	}
81
	}
81
82
Lines 96-102 Link Here
96
		}
97
		}
97
98
98
		public IObservableValue createObservableValue(Realm realm) {
99
		public IObservableValue createObservableValue(Realm realm) {
99
			return new ScaleObservableValue(realm, scale, SWTProperties.MAX);
100
			return WidgetProperties.maximum().observe(realm, scale);
100
		}
101
		}
101
102
102
		public void change(IObservable observable) {
103
		public void change(IObservable observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/TableSingleSelectionObservableValueTest.java (-17 / +23 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bugs 118516, 213145
10
 *     Matthew Hall - bugs 118516, 213145, 194734, 195222
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 23-29 Link Here
23
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
24
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
25
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.databinding.swt.SWTObservables;
26
import org.eclipse.jface.internal.databinding.swt.TableSingleSelectionObservableValue;
26
import org.eclipse.jface.databinding.swt.WidgetProperties;
27
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.widgets.Display;
28
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Shell;
29
import org.eclipse.swt.widgets.Shell;
Lines 33-66 Link Here
33
/**
33
/**
34
 * @since 3.2
34
 * @since 3.2
35
 */
35
 */
36
public class TableSingleSelectionObservableValueTest extends ObservableDelegateTest {
36
public class TableSingleSelectionObservableValueTest extends
37
		ObservableDelegateTest {
37
	private Delegate delegate;
38
	private Delegate delegate;
38
	private IObservableValue observable;
39
	private IObservableValue observable;
39
	private Table table;
40
	private Table table;
40
	
41
41
	public TableSingleSelectionObservableValueTest() {
42
	public TableSingleSelectionObservableValueTest() {
42
		this(null);
43
		this(null);
43
	}
44
	}
44
	
45
45
	public TableSingleSelectionObservableValueTest(String testName) {
46
	public TableSingleSelectionObservableValueTest(String testName) {
46
		super(testName, new Delegate());
47
		super(testName, new Delegate());
47
	}
48
	}
48
	
49
49
	protected void setUp() throws Exception {
50
	protected void setUp() throws Exception {
50
		super.setUp();
51
		super.setUp();
51
		
52
52
		observable = (IObservableValue) getObservable();
53
		observable = (IObservableValue) getObservable();
53
		delegate = (Delegate) getObservableContractDelegate();
54
		delegate = (Delegate) getObservableContractDelegate();
54
		table = delegate.table;
55
		table = delegate.table;
55
	}
56
	}
56
	
57
57
	protected IObservable doCreateObservable() {
58
	protected IObservable doCreateObservable() {
58
		Delegate delegate = (Delegate) getObservableContractDelegate();
59
		Delegate delegate = (Delegate) getObservableContractDelegate();
59
		return delegate.createObservableValue(SWTObservables.getRealm(Display.getDefault()));
60
		return delegate.createObservableValue(SWTObservables.getRealm(Display
61
				.getDefault()));
60
	}
62
	}
61
	
63
62
	public void testSetValue() throws Exception {
64
	public void testSetValue() throws Exception {
63
		//preconditions
65
		// preconditions
64
		assertEquals(-1, table.getSelectionIndex());
66
		assertEquals(-1, table.getSelectionIndex());
65
		assertEquals(-1, ((Integer) observable.getValue()).intValue());
67
		assertEquals(-1, ((Integer) observable.getValue()).intValue());
66
68
Lines 70-88 Link Here
70
				.getSelectionIndex());
72
				.getSelectionIndex());
71
		assertEquals("observable value", value, observable.getValue());
73
		assertEquals("observable value", value, observable.getValue());
72
	}
74
	}
73
	
75
74
	public void testGetValue() throws Exception {
76
	public void testGetValue() throws Exception {
75
		int value = 1;
77
		int value = 1;
76
		table.setSelection(value);
78
		table.setSelection(value);
77
		
79
78
		assertEquals("table selection index", value, table.getSelectionIndex());
80
		assertEquals("table selection index", value, table.getSelectionIndex());
79
		assertEquals("observable value", new Integer(value), observable.getValue());
81
		assertEquals("observable value", new Integer(value), observable
82
				.getValue());
80
	}
83
	}
81
84
82
	public static Test suite() {
85
	public static Test suite() {
83
		TestSuite suite = new TestSuite(TableSingleSelectionObservableValueTest.class.toString());
86
		TestSuite suite = new TestSuite(
87
				TableSingleSelectionObservableValueTest.class.toString());
84
		suite.addTestSuite(TableSingleSelectionObservableValueTest.class);
88
		suite.addTestSuite(TableSingleSelectionObservableValueTest.class);
85
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
89
		suite.addTest(SWTMutableObservableValueContractTest
90
				.suite(new Delegate()));
86
		return suite;
91
		return suite;
87
	}
92
	}
88
93
Lines 104-110 Link Here
104
		}
109
		}
105
110
106
		public IObservableValue createObservableValue(Realm realm) {
111
		public IObservableValue createObservableValue(Realm realm) {
107
			return new TableSingleSelectionObservableValue(realm, table);
112
			return WidgetProperties.singleSelectionIndex()
113
					.observe(realm, table);
108
		}
114
		}
109
115
110
		public Object getValueType(IObservableValue observable) {
116
		public Object getValueType(IObservableValue observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/CLabelObservableValueTest.java (-24 / +27 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-28 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.CLabelObservableValue;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.custom.CLabel;
27
import org.eclipse.swt.custom.CLabel;
28
import org.eclipse.swt.widgets.Display;
28
import org.eclipse.swt.widgets.Display;
Lines 36-73 Link Here
36
	private Delegate delegate;
36
	private Delegate delegate;
37
	private IObservableValue observable;
37
	private IObservableValue observable;
38
	private CLabel label;
38
	private CLabel label;
39
	
39
40
	protected void setUp() throws Exception {
40
	protected void setUp() throws Exception {
41
		super.setUp();
41
		super.setUp();
42
		
42
43
		delegate = new Delegate();
43
		delegate = new Delegate();
44
		delegate.setUp();
44
		delegate.setUp();
45
		label = delegate.label;
45
		label = delegate.label;
46
		observable = delegate.createObservableValue(SWTObservables.getRealm(Display.getDefault()));
46
		observable = delegate.createObservableValue(SWTObservables
47
				.getRealm(Display.getDefault()));
47
	}
48
	}
48
	
49
49
	protected void tearDown() throws Exception {
50
	protected void tearDown() throws Exception {
50
		super.tearDown();
51
		super.tearDown();
51
		
52
52
		delegate.tearDown();
53
		delegate.tearDown();
53
		observable.dispose();
54
		observable.dispose();
54
	}
55
	}
55
	
56
56
    public void testSetValue() throws Exception {
57
	public void testSetValue() throws Exception {
57
    	//preconditions
58
		// preconditions
58
        assertEquals(null, label.getText());
59
		assertEquals(null, label.getText());
59
        assertEquals(null, observable.getValue());
60
		assertEquals(null, observable.getValue());
60
        
61
61
        String value = "value";
62
		String value = "value";
62
        observable.setValue(value);
63
		observable.setValue(value);
63
        assertEquals("label text", value, label.getText());
64
		assertEquals("label text", value, label.getText());
64
        assertEquals("observable value", value, observable.getValue());
65
		assertEquals("observable value", value, observable.getValue());
65
    }
66
	}
66
	
67
67
	public static Test suite() {
68
	public static Test suite() {
68
		TestSuite suite = new TestSuite(CLabelObservableValueTest.class.getName());
69
		TestSuite suite = new TestSuite(CLabelObservableValueTest.class
70
				.getName());
69
		suite.addTestSuite(CLabelObservableValueTest.class);
71
		suite.addTestSuite(CLabelObservableValueTest.class);
70
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
72
		suite.addTest(SWTMutableObservableValueContractTest
73
				.suite(new Delegate()));
71
		return suite;
74
		return suite;
72
	}
75
	}
73
76
Lines 87-104 Link Here
87
		}
90
		}
88
91
89
		public IObservableValue createObservableValue(Realm realm) {
92
		public IObservableValue createObservableValue(Realm realm) {
90
			return new CLabelObservableValue(realm, label);
93
			return WidgetProperties.text().observe(realm, label);
91
		}
94
		}
92
95
93
		public void change(IObservable observable) {
96
		public void change(IObservable observable) {
94
			IObservableValue value = (IObservableValue) observable;
97
			IObservableValue value = (IObservableValue) observable;
95
			value.setValue(value.getValue() + "a");
98
			value.setValue(value.getValue() + "a");
96
		}
99
		}
97
		
100
98
		public Object getValueType(IObservableValue observable) {
101
		public Object getValueType(IObservableValue observable) {
99
			return String.class;
102
			return String.class;
100
		}
103
		}
101
		
104
102
		public Object createValue(IObservableValue observable) {
105
		public Object createValue(IObservableValue observable) {
103
			return observable.getValue() + "a";
106
			return observable.getValue() + "a";
104
		}
107
		}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/SpinnerObservableValueTest.java (-4 / +4 lines)
Lines 8-20 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Ashley Cambrell - bug 198904
10
 *     Ashley Cambrell - bug 198904
11
 *     Matthew Hall - bug 194734
11
 ******************************************************************************/
12
 ******************************************************************************/
12
13
13
package org.eclipse.jface.tests.internal.databinding.swt;
14
package org.eclipse.jface.tests.internal.databinding.swt;
14
15
15
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
16
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
16
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
17
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
17
import org.eclipse.jface.internal.databinding.swt.SpinnerObservableValue;
18
import org.eclipse.jface.databinding.swt.SWTObservables;
18
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
19
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
19
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.widgets.Spinner;
21
import org.eclipse.swt.widgets.Spinner;
Lines 26-33 Link Here
26
public class SpinnerObservableValueTest extends AbstractSWTTestCase {
27
public class SpinnerObservableValueTest extends AbstractSWTTestCase {
27
	public void testDispose() throws Exception {
28
	public void testDispose() throws Exception {
28
		Spinner spinner = new Spinner(getShell(), SWT.NONE);
29
		Spinner spinner = new Spinner(getShell(), SWT.NONE);
29
		SpinnerObservableValue observableValue = new SpinnerObservableValue(
30
		ISWTObservableValue observableValue = SWTObservables.observeSelection(spinner);
30
				spinner, SWTProperties.SELECTION);
31
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
31
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
32
		observableValue.addValueChangeListener(testCounterValueChangeListener);
32
		observableValue.addValueChangeListener(testCounterValueChangeListener);
33
33
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ScaleObservableValueSelectionTest.java (-7 / +7 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-29 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.jface.internal.databinding.swt.ScaleObservableValue;
27
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Scale;
28
import org.eclipse.swt.widgets.Scale;
Lines 42-52 Link Here
42
	public ScaleObservableValueSelectionTest() {
41
	public ScaleObservableValueSelectionTest() {
43
		this(null);
42
		this(null);
44
	}
43
	}
45
	
44
46
	public ScaleObservableValueSelectionTest(String testName) {
45
	public ScaleObservableValueSelectionTest(String testName) {
47
		super(testName, new Delegate());
46
		super(testName, new Delegate());
48
	}
47
	}
49
	
48
50
	protected void setUp() throws Exception {
49
	protected void setUp() throws Exception {
51
		super.setUp();
50
		super.setUp();
52
51
Lines 56-62 Link Here
56
	}
55
	}
57
56
58
	protected IObservable doCreateObservable() {
57
	protected IObservable doCreateObservable() {
59
		return getObservableContractDelegate().createObservable(SWTObservables.getRealm(Display.getDefault()));
58
		return getObservableContractDelegate().createObservable(
59
				SWTObservables.getRealm(Display.getDefault()));
60
	}
60
	}
61
61
62
	public void testGetValue() throws Exception {
62
	public void testGetValue() throws Exception {
Lines 97-103 Link Here
97
		}
97
		}
98
98
99
		public IObservableValue createObservableValue(Realm realm) {
99
		public IObservableValue createObservableValue(Realm realm) {
100
			return new ScaleObservableValue(realm, scale, SWTProperties.SELECTION);
100
			return WidgetProperties.selection().observe(realm, scale);
101
		}
101
		}
102
102
103
		public void change(IObservable observable) {
103
		public void change(IObservable observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/SWTObservableListTest.java (-115 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 208858)
10
 *     Matthew Hall - bug 213145
11
 ******************************************************************************/
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
14
15
import junit.framework.Test;
16
import junit.framework.TestSuite;
17
18
import org.eclipse.core.databinding.observable.IObservable;
19
import org.eclipse.core.databinding.observable.IObservableCollection;
20
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
23
import org.eclipse.jface.internal.databinding.swt.SWTObservableList;
24
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
25
26
/**
27
 * @since 3.3
28
 */
29
public class SWTObservableListTest extends AbstractDefaultRealmTestCase {
30
	SWTObservableListStub list;
31
32
	protected void setUp() throws Exception {
33
		super.setUp();
34
		list = new SWTObservableListStub(Realm.getDefault(), 0);
35
	}
36
37
	public void testMove_ForwardAndBackward() {
38
		String element0 = "element0";
39
		String element1 = "element1";
40
41
		list.add(element0);
42
		list.add(element1);
43
44
		// move forward
45
		assertEquals(element0, list.move(0, 1));
46
		assertEquals(element1, list.move(0, 1));
47
48
		// move backward
49
		assertEquals(element1, list.move(1, 0));
50
		assertEquals(element0, list.move(1, 0));
51
	}
52
53
	public static Test suite() {
54
		TestSuite suite = new TestSuite(SWTObservableListTest.class.toString());
55
		suite.addTestSuite(SWTObservableListTest.class);
56
		suite.addTest(MutableObservableListContractTest.suite(new Delegate()));
57
		return suite;
58
	}
59
60
	static class Delegate extends AbstractObservableCollectionContractDelegate {
61
		public IObservableCollection createObservableCollection(Realm realm,
62
				int elementCount) {
63
			return new SWTObservableListStub(realm, elementCount);
64
		}
65
66
		private int counter;
67
68
		public Object createElement(IObservableCollection collection) {
69
			return "Item" + counter++;
70
		}
71
72
		public Object getElementType(IObservableCollection collection) {
73
			return String.class;
74
		}
75
76
		public void change(IObservable observable) {
77
			((SWTObservableListStub) observable).fireChange();
78
		}
79
	}
80
81
	static class SWTObservableListStub extends SWTObservableList {
82
		String[] items;
83
84
		public SWTObservableListStub(Realm realm, int elementCount) {
85
			super(realm);
86
			items = new String[elementCount];
87
			for (int i = 0; i < items.length; i++)
88
				items[i] = Integer.toString(i);
89
		}
90
91
		protected String getItem(int index) {
92
			return items[index];
93
		}
94
95
		protected int getItemCount() {
96
			return items.length;
97
		}
98
99
		protected String[] getItems() {
100
			return items;
101
		}
102
103
		protected void setItem(int index, String string) {
104
			items[index] = string;
105
		}
106
107
		protected void setItems(String[] newItems) {
108
			items = newItems;
109
		}
110
111
		protected void fireChange() {
112
			super.fireChange();
113
		}
114
	}
115
}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/TableObservableValueTest.java (-3 / +5 lines)
Lines 8-18 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Ashley Cambrell - bug 198904
10
 *     Ashley Cambrell - bug 198904
11
 *     Matthew Hall - bug 194734
11
 ******************************************************************************/
12
 ******************************************************************************/
12
13
13
package org.eclipse.jface.tests.internal.databinding.swt;
14
package org.eclipse.jface.tests.internal.databinding.swt;
14
15
15
import org.eclipse.jface.internal.databinding.swt.TableSingleSelectionObservableValue;
16
import org.eclipse.core.databinding.observable.value.IObservableValue;
17
import org.eclipse.jface.databinding.swt.SWTObservables;
16
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
18
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
17
import org.eclipse.swt.SWT;
19
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.widgets.Table;
20
import org.eclipse.swt.widgets.Table;
Lines 24-31 Link Here
24
public class TableObservableValueTest extends AbstractSWTTestCase {
26
public class TableObservableValueTest extends AbstractSWTTestCase {
25
	public void testDispose() throws Exception {
27
	public void testDispose() throws Exception {
26
		Table table = new Table(getShell(), SWT.NONE);
28
		Table table = new Table(getShell(), SWT.NONE);
27
		TableSingleSelectionObservableValue observableValue = new TableSingleSelectionObservableValue(
29
		IObservableValue observableValue = SWTObservables
28
				table);
30
				.observeSingleSelectionIndex(table);
29
31
30
		TableItem item1 = new TableItem(table, SWT.NONE);
32
		TableItem item1 = new TableItem(table, SWT.NONE);
31
		item1.setText("Item1");
33
		item1.setText("Item1");
(-)src/org/eclipse/jface/tests/internal/databinding/swt/TextObservableValueFocusOutTest.java (-8 / +10 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 21-27 Link Here
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.internal.databinding.swt.TextObservableValue;
24
import org.eclipse.jface.databinding.swt.WidgetProperties;
25
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.widgets.Shell;
26
import org.eclipse.swt.widgets.Shell;
27
import org.eclipse.swt.widgets.Text;
27
import org.eclipse.swt.widgets.Text;
Lines 31-38 Link Here
31
 */
31
 */
32
public class TextObservableValueFocusOutTest extends TestCase {
32
public class TextObservableValueFocusOutTest extends TestCase {
33
	public static Test suite() {
33
	public static Test suite() {
34
		TestSuite suite = new TestSuite(TextObservableValueFocusOutTest.class.toString());
34
		TestSuite suite = new TestSuite(TextObservableValueFocusOutTest.class
35
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
35
				.toString());
36
		suite.addTest(SWTMutableObservableValueContractTest
37
				.suite(new Delegate()));
36
		return suite;
38
		return suite;
37
	}
39
	}
38
40
Lines 41-47 Link Here
41
		private Shell shell;
43
		private Shell shell;
42
44
43
		private Text text;
45
		private Text text;
44
		
46
45
		public void setUp() {
47
		public void setUp() {
46
			shell = new Shell();
48
			shell = new Shell();
47
			text = new Text(shell, SWT.NONE);
49
			text = new Text(shell, SWT.NONE);
Lines 52-58 Link Here
52
		}
54
		}
53
55
54
		public IObservableValue createObservableValue(Realm realm) {
56
		public IObservableValue createObservableValue(Realm realm) {
55
			return new TextObservableValue(realm, text, SWT.FocusOut);
57
			return WidgetProperties.text(SWT.FocusOut).observe(realm, text);
56
		}
58
		}
57
59
58
		public Object getValueType(IObservableValue observable) {
60
		public Object getValueType(IObservableValue observable) {
Lines 61-70 Link Here
61
63
62
		public void change(IObservable observable) {
64
		public void change(IObservable observable) {
63
			text.setFocus();
65
			text.setFocus();
64
			
66
65
			IObservableValue observableValue = (IObservableValue) observable;
67
			IObservableValue observableValue = (IObservableValue) observable;
66
			text.setText((String) createValue(observableValue));
68
			text.setText((String) createValue(observableValue));
67
			
69
68
			text.notifyListeners(SWT.FocusOut, null);
70
			text.notifyListeners(SWT.FocusOut, null);
69
		}
71
		}
70
72
(-)src/org/eclipse/jface/tests/internal/databinding/swt/TextEditableObservableValueTest.java (-28 / +34 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 21-27 Link Here
21
import org.eclipse.jface.databinding.conformance.ObservableDelegateTest;
21
import org.eclipse.jface.databinding.conformance.ObservableDelegateTest;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.internal.databinding.swt.TextEditableObservableValue;
24
import org.eclipse.jface.databinding.swt.WidgetProperties;
25
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.widgets.Shell;
26
import org.eclipse.swt.widgets.Shell;
27
import org.eclipse.swt.widgets.Text;
27
import org.eclipse.swt.widgets.Text;
Lines 29-37 Link Here
29
/**
29
/**
30
 * @since 1.1
30
 * @since 1.1
31
 */
31
 */
32
public class TextEditableObservableValueTest extends
32
public class TextEditableObservableValueTest extends ObservableDelegateTest {
33
		ObservableDelegateTest {
33
34
	
35
	private Delegate delegate;
34
	private Delegate delegate;
36
	private Text text;
35
	private Text text;
37
	private IObservableValue observable;
36
	private IObservableValue observable;
Lines 39-116 Link Here
39
	public TextEditableObservableValueTest() {
38
	public TextEditableObservableValueTest() {
40
		this(null);
39
		this(null);
41
	}
40
	}
42
	
41
43
	public TextEditableObservableValueTest(String testName) {
42
	public TextEditableObservableValueTest(String testName) {
44
		super(testName, new Delegate());
43
		super(testName, new Delegate());
45
	}
44
	}
46
45
47
	/* (non-Javadoc)
46
	/*
48
	 * @see org.eclipse.jface.conformance.databinding.ObservableDelegateTest#setUp()
47
	 * (non-Javadoc)
48
	 * 
49
	 * @see
50
	 * org.eclipse.jface.conformance.databinding.ObservableDelegateTest#setUp()
49
	 */
51
	 */
50
	protected void setUp() throws Exception {
52
	protected void setUp() throws Exception {
51
		super.setUp();
53
		super.setUp();
52
		
54
53
		delegate = (Delegate) getObservableContractDelegate();
55
		delegate = (Delegate) getObservableContractDelegate();
54
		observable = (IObservableValue) getObservable();
56
		observable = (IObservableValue) getObservable();
55
		text = delegate.text;
57
		text = delegate.text;
56
	}
58
	}
57
	
59
58
	protected IObservable doCreateObservable() {
60
	protected IObservable doCreateObservable() {
59
		return super.doCreateObservable();
61
		return super.doCreateObservable();
60
	}
62
	}
61
	
63
62
	public void testGetValue() throws Exception {
64
	public void testGetValue() throws Exception {
63
		text.setEditable(false);
65
		text.setEditable(false);
64
		assertEquals(Boolean.valueOf(text.getEditable()), observable.getValue());
66
		assertEquals(Boolean.valueOf(text.getEditable()), observable.getValue());
65
		
67
66
		text.setEditable(true);
68
		text.setEditable(true);
67
		assertEquals(Boolean.valueOf(text.getEditable()), observable.getValue());
69
		assertEquals(Boolean.valueOf(text.getEditable()), observable.getValue());
68
	}
70
	}
69
	
71
70
	public void testSetValue() throws Exception {
72
	public void testSetValue() throws Exception {
71
		text.setEditable(false);
73
		text.setEditable(false);
72
		observable.setValue(Boolean.TRUE);
74
		observable.setValue(Boolean.TRUE);
73
		assertEquals(Boolean.TRUE, Boolean.valueOf(text.getEditable()));
75
		assertEquals(Boolean.TRUE, Boolean.valueOf(text.getEditable()));
74
		
76
75
		observable.setValue(Boolean.FALSE);
77
		observable.setValue(Boolean.FALSE);
76
		assertEquals(Boolean.FALSE, Boolean.valueOf(text.getEditable()));
78
		assertEquals(Boolean.FALSE, Boolean.valueOf(text.getEditable()));
77
	}
79
	}
78
	
80
79
	public static Test suite() {
81
	public static Test suite() {
80
		TestSuite suite = new TestSuite(TextEditableObservableValueTest.class.toString());
82
		TestSuite suite = new TestSuite(TextEditableObservableValueTest.class
83
				.toString());
81
		suite.addTestSuite(TextEditableObservableValueTest.class);
84
		suite.addTestSuite(TextEditableObservableValueTest.class);
82
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
85
		suite.addTest(SWTMutableObservableValueContractTest
86
				.suite(new Delegate()));
83
		return suite;
87
		return suite;
84
	}
88
	}
85
	
89
86
	/*package*/ static class Delegate extends AbstractObservableValueContractDelegate {
90
	/* package */static class Delegate extends
91
			AbstractObservableValueContractDelegate {
87
		private Shell shell;
92
		private Shell shell;
88
		Text text;
93
		Text text;
89
		
94
90
		public void setUp() {			
95
		public void setUp() {
91
			shell = new Shell();
96
			shell = new Shell();
92
			text = new Text(shell, SWT.NONE);
97
			text = new Text(shell, SWT.NONE);
93
		}
98
		}
94
99
95
		public void tearDown() {			
100
		public void tearDown() {
96
			shell.dispose();
101
			shell.dispose();
97
		}
102
		}
98
		
103
99
		public IObservableValue createObservableValue(Realm realm) {
104
		public IObservableValue createObservableValue(Realm realm) {
100
			return new TextEditableObservableValue(realm, text);
105
			return WidgetProperties.editable().observe(realm, text);
101
		}
106
		}
102
		
107
103
		public Object getValueType(IObservableValue observable) {
108
		public Object getValueType(IObservableValue observable) {
104
			return Boolean.TYPE;
109
			return Boolean.TYPE;
105
		}
110
		}
106
		
111
107
		public void change(IObservable observable) {
112
		public void change(IObservable observable) {
108
			IObservableValue observableValue = (IObservableValue) observable;
113
			IObservableValue observableValue = (IObservableValue) observable;
109
			observableValue.setValue(createValue(observableValue));
114
			observableValue.setValue(createValue(observableValue));
110
		}
115
		}
111
		
116
112
		public Object createValue(IObservableValue observable) {
117
		public Object createValue(IObservableValue observable) {
113
			return (Boolean.TRUE.equals(observable.getValue()) ? Boolean.FALSE: Boolean.TRUE);
118
			return (Boolean.TRUE.equals(observable.getValue()) ? Boolean.FALSE
119
					: Boolean.TRUE);
114
		}
120
		}
115
	}
121
	}
116
}
122
}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ControlObservableValueTest.java (-40 / +23 lines)
Lines 8-19 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Brad Reynolds - bug 170848
10
 *     Brad Reynolds - bug 170848
11
 *     Matthew Hall - bug 194734
11
 ******************************************************************************/
12
 ******************************************************************************/
12
13
13
package org.eclipse.jface.tests.internal.databinding.swt;
14
package org.eclipse.jface.tests.internal.databinding.swt;
14
15
15
import org.eclipse.jface.internal.databinding.swt.ControlObservableValue;
16
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
16
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
17
import org.eclipse.jface.databinding.swt.SWTObservables;
17
import org.eclipse.jface.resource.JFaceResources;
18
import org.eclipse.jface.resource.JFaceResources;
18
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
19
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
19
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.SWT;
Lines 47-95 Link Here
47
	}
48
	}
48
49
49
	public void testSetValueEnabled() throws Exception {
50
	public void testSetValueEnabled() throws Exception {
50
		ControlObservableValue observableValue = new ControlObservableValue(
51
		ISWTObservableValue observableValue = SWTObservables
51
				shell, SWTProperties.ENABLED);
52
				.observeEnabled(shell);
52
		Boolean value = Boolean.FALSE;
53
		Boolean value = Boolean.FALSE;
53
		observableValue.setValue(value);
54
		observableValue.setValue(value);
54
		assertFalse(shell.isEnabled());
55
		assertFalse(shell.isEnabled());
55
	}
56
	}
56
57
57
	public void testGetValueEnabled() throws Exception {
58
	public void testGetValueEnabled() throws Exception {
58
		ControlObservableValue value = new ControlObservableValue(shell,
59
		ISWTObservableValue value = SWTObservables.observeEnabled(shell);
59
				SWTProperties.ENABLED);
60
		shell.setEnabled(false);
60
		shell.setEnabled(false);
61
		assertEquals(Boolean.FALSE, value.getValue());
61
		assertEquals(Boolean.FALSE, value.getValue());
62
	}
62
	}
63
63
64
	public void testGetValueTypeEnabled() throws Exception {
64
	public void testGetValueTypeEnabled() throws Exception {
65
		ControlObservableValue value = new ControlObservableValue(shell,
65
		ISWTObservableValue value = SWTObservables.observeEnabled(shell);
66
				SWTProperties.ENABLED);
67
		assertEquals(boolean.class, value.getValueType());
66
		assertEquals(boolean.class, value.getValueType());
68
	}
67
	}
69
68
70
	public void testSetValueVisible() throws Exception {
69
	public void testSetValueVisible() throws Exception {
71
		ControlObservableValue value = new ControlObservableValue(shell,
70
		ISWTObservableValue value = SWTObservables.observeVisible(shell);
72
				SWTProperties.VISIBLE);
73
		value.setValue(Boolean.FALSE);
71
		value.setValue(Boolean.FALSE);
74
		assertFalse(shell.isVisible());
72
		assertFalse(shell.isVisible());
75
	}
73
	}
76
74
77
	public void testGetValueVisible() throws Exception {
75
	public void testGetValueVisible() throws Exception {
78
		ControlObservableValue value = new ControlObservableValue(shell,
76
		ISWTObservableValue value = SWTObservables.observeVisible(shell);
79
				SWTProperties.VISIBLE);
80
		shell.setVisible(false);
77
		shell.setVisible(false);
81
		assertEquals(Boolean.FALSE, value.getValue());
78
		assertEquals(Boolean.FALSE, value.getValue());
82
	}
79
	}
83
80
84
	public void testGetValueTypeVisible() throws Exception {
81
	public void testGetValueTypeVisible() throws Exception {
85
		ControlObservableValue value = new ControlObservableValue(shell,
82
		ISWTObservableValue value = SWTObservables.observeVisible(shell);
86
				SWTProperties.VISIBLE);
87
		assertEquals(Boolean.TYPE, value.getValueType());
83
		assertEquals(Boolean.TYPE, value.getValueType());
88
	}
84
	}
89
85
90
	public void testSetValueForeground() throws Exception {
86
	public void testSetValueForeground() throws Exception {
91
		ControlObservableValue value = new ControlObservableValue(shell,
87
		ISWTObservableValue value = SWTObservables.observeForeground(shell);
92
				SWTProperties.FOREGROUND);
93
88
94
		Color color = shell.getDisplay().getSystemColor(SWT.COLOR_BLACK);
89
		Color color = shell.getDisplay().getSystemColor(SWT.COLOR_BLACK);
95
90
Lines 98-105 Link Here
98
	}
93
	}
99
94
100
	public void testGetValueForeground() throws Exception {
95
	public void testGetValueForeground() throws Exception {
101
		ControlObservableValue value = new ControlObservableValue(shell,
96
		ISWTObservableValue value = SWTObservables.observeForeground(shell);
102
				SWTProperties.FOREGROUND);
103
97
104
		Color color = shell.getDisplay().getSystemColor(SWT.COLOR_BLACK);
98
		Color color = shell.getDisplay().getSystemColor(SWT.COLOR_BLACK);
105
		shell.setForeground(color);
99
		shell.setForeground(color);
Lines 107-120 Link Here
107
	}
101
	}
108
102
109
	public void testGetValueTypeForgroundColor() throws Exception {
103
	public void testGetValueTypeForgroundColor() throws Exception {
110
		ControlObservableValue value = new ControlObservableValue(shell,
104
		ISWTObservableValue value = SWTObservables.observeForeground(shell);
111
				SWTProperties.FOREGROUND);
112
		assertEquals(Color.class, value.getValueType());
105
		assertEquals(Color.class, value.getValueType());
113
	}
106
	}
114
107
115
	public void testGetValueBackground() throws Exception {
108
	public void testGetValueBackground() throws Exception {
116
		ControlObservableValue value = new ControlObservableValue(shell,
109
		ISWTObservableValue value = SWTObservables.observeBackground(shell);
117
				SWTProperties.BACKGROUND);
118
110
119
		Color color = shell.getDisplay().getSystemColor(SWT.COLOR_BLACK);
111
		Color color = shell.getDisplay().getSystemColor(SWT.COLOR_BLACK);
120
		shell.setBackground(color);
112
		shell.setBackground(color);
Lines 122-129 Link Here
122
	}
114
	}
123
115
124
	public void testSetValueBackground() throws Exception {
116
	public void testSetValueBackground() throws Exception {
125
		ControlObservableValue value = new ControlObservableValue(shell,
117
		ISWTObservableValue value = SWTObservables.observeBackground(shell);
126
				SWTProperties.BACKGROUND);
127
118
128
		Color color = shell.getDisplay().getSystemColor(SWT.COLOR_BLACK);
119
		Color color = shell.getDisplay().getSystemColor(SWT.COLOR_BLACK);
129
120
Lines 132-151 Link Here
132
	}
123
	}
133
124
134
	public void testGetValueTypeBackgroundColor() throws Exception {
125
	public void testGetValueTypeBackgroundColor() throws Exception {
135
		ControlObservableValue value = new ControlObservableValue(shell,
126
		ISWTObservableValue value = SWTObservables.observeBackground(shell);
136
				SWTProperties.BACKGROUND);
137
		assertEquals(Color.class, value.getValueType());
127
		assertEquals(Color.class, value.getValueType());
138
	}
128
	}
139
129
140
	public void testGetValueTypeTooltip() throws Exception {
130
	public void testGetValueTypeTooltip() throws Exception {
141
		ControlObservableValue value = new ControlObservableValue(shell,
131
		ISWTObservableValue value = SWTObservables.observeTooltipText(shell);
142
				SWTProperties.TOOLTIP_TEXT);
143
		assertEquals(String.class, value.getValueType());
132
		assertEquals(String.class, value.getValueType());
144
	}
133
	}
145
134
146
	public void testSetValueFont() throws Exception {
135
	public void testSetValueFont() throws Exception {
147
		ControlObservableValue value = new ControlObservableValue(shell,
136
		ISWTObservableValue value = SWTObservables.observeFont(shell);
148
				SWTProperties.FONT);
149
137
150
		Font font = JFaceResources.getDialogFont();
138
		Font font = JFaceResources.getDialogFont();
151
139
Lines 154-161 Link Here
154
	}
142
	}
155
143
156
	public void testGetValueFont() throws Exception {
144
	public void testGetValueFont() throws Exception {
157
		ControlObservableValue value = new ControlObservableValue(shell,
145
		ISWTObservableValue value = SWTObservables.observeFont(shell);
158
				SWTProperties.FONT);
159
146
160
		Font font = JFaceResources.getDialogFont();
147
		Font font = JFaceResources.getDialogFont();
161
		shell.setFont(font);
148
		shell.setFont(font);
Lines 163-192 Link Here
163
	}
150
	}
164
151
165
	public void testGetValueTypeFont() throws Exception {
152
	public void testGetValueTypeFont() throws Exception {
166
		ControlObservableValue value = new ControlObservableValue(shell,
153
		ISWTObservableValue value = SWTObservables.observeFont(shell);
167
				SWTProperties.FONT);
168
		assertEquals(Font.class, value.getValueType());
154
		assertEquals(Font.class, value.getValueType());
169
	}
155
	}
170
156
171
	public void testSetValueTooltipText() throws Exception {
157
	public void testSetValueTooltipText() throws Exception {
172
		ControlObservableValue value = new ControlObservableValue(shell,
158
		ISWTObservableValue value = SWTObservables.observeTooltipText(shell);
173
				SWTProperties.TOOLTIP_TEXT);
174
		String text = "text";
159
		String text = "text";
175
		value.setValue(text);
160
		value.setValue(text);
176
		assertEquals(text, shell.getToolTipText());
161
		assertEquals(text, shell.getToolTipText());
177
	}
162
	}
178
163
179
	public void testGetValueTooltipText() throws Exception {
164
	public void testGetValueTooltipText() throws Exception {
180
		ControlObservableValue value = new ControlObservableValue(shell,
165
		ISWTObservableValue value = SWTObservables.observeTooltipText(shell);
181
				SWTProperties.TOOLTIP_TEXT);
182
		String text = "text";
166
		String text = "text";
183
		shell.setToolTipText(text);
167
		shell.setToolTipText(text);
184
		assertEquals(text, value.getValue());
168
		assertEquals(text, value.getValue());
185
	}
169
	}
186
170
187
	public void testGetValueTypeTooltipText() throws Exception {
171
	public void testGetValueTypeTooltipText() throws Exception {
188
		ControlObservableValue value = new ControlObservableValue(shell,
172
		ISWTObservableValue value = SWTObservables.observeTooltipText(shell);
189
				SWTProperties.TOOLTIP_TEXT);
190
		assertEquals(String.class, value.getValueType());
173
		assertEquals(String.class, value.getValueType());
191
	}
174
	}
192
}
175
}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/LabelObservableValueTest.java (-28 / +31 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-28 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.LabelObservableValue;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Display;
28
import org.eclipse.swt.widgets.Label;
28
import org.eclipse.swt.widgets.Label;
Lines 35-77 Link Here
35
	private Delegate delegate;
35
	private Delegate delegate;
36
	private IObservableValue observable;
36
	private IObservableValue observable;
37
	private Label label;
37
	private Label label;
38
	
38
39
	public LabelObservableValueTest() {
39
	public LabelObservableValueTest() {
40
		this(null);
40
		this(null);
41
	}
41
	}
42
	
42
43
	public LabelObservableValueTest(String testName) {
43
	public LabelObservableValueTest(String testName) {
44
		super(testName, new Delegate());
44
		super(testName, new Delegate());
45
	}
45
	}
46
	
46
47
	protected void setUp() throws Exception {
47
	protected void setUp() throws Exception {
48
		super.setUp();
48
		super.setUp();
49
		
49
50
		delegate = (Delegate) getObservableContractDelegate();
50
		delegate = (Delegate) getObservableContractDelegate();
51
		observable = (IObservableValue) getObservable();
51
		observable = (IObservableValue) getObservable();
52
		label = delegate.label;
52
		label = delegate.label;
53
	}
53
	}
54
	
54
55
	protected IObservable doCreateObservable() {
55
	protected IObservable doCreateObservable() {
56
		return getObservableContractDelegate().createObservable(SWTObservables.getRealm(Display.getDefault()));
56
		return getObservableContractDelegate().createObservable(
57
				SWTObservables.getRealm(Display.getDefault()));
57
	}
58
	}
58
	
59
59
    public void testSetValue() throws Exception {
60
	public void testSetValue() throws Exception {
60
    	//preconditions
61
		// preconditions
61
        assertEquals("", label.getText());
62
		assertEquals("", label.getText());
62
        assertEquals("", observable.getValue());
63
		assertEquals("", observable.getValue());
63
        
64
64
        String value = "value";
65
		String value = "value";
65
        observable.setValue(value);
66
		observable.setValue(value);
66
        assertEquals("label text", value, label.getText());
67
		assertEquals("label text", value, label.getText());
67
        assertEquals("observable value", value, observable.getValue());
68
		assertEquals("observable value", value, observable.getValue());
68
    }
69
	}
69
    
70
70
    public static Test suite() {
71
	public static Test suite() {
71
    	TestSuite suite = new TestSuite(LabelObservableValueTest.class.toString());
72
		TestSuite suite = new TestSuite(LabelObservableValueTest.class
72
    	suite.addTestSuite(LabelObservableValueTest.class);
73
				.toString());
73
    	suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
74
		suite.addTestSuite(LabelObservableValueTest.class);
74
    	return suite;
75
		suite.addTest(SWTMutableObservableValueContractTest
76
				.suite(new Delegate()));
77
		return suite;
75
	}
78
	}
76
79
77
	/* package */static class Delegate extends
80
	/* package */static class Delegate extends
Lines 90-107 Link Here
90
		}
93
		}
91
94
92
		public IObservableValue createObservableValue(Realm realm) {
95
		public IObservableValue createObservableValue(Realm realm) {
93
			return new LabelObservableValue(realm, label);
96
			return WidgetProperties.text().observe(realm, label);
94
		}
97
		}
95
98
96
		public void change(IObservable observable) {
99
		public void change(IObservable observable) {
97
			IObservableValue value = (IObservableValue) observable;
100
			IObservableValue value = (IObservableValue) observable;
98
			value.setValue(value.getValue() + "a");
101
			value.setValue(value.getValue() + "a");
99
		}
102
		}
100
		
103
101
		public Object getValueType(IObservableValue observable) {
104
		public Object getValueType(IObservableValue observable) {
102
			return String.class;
105
			return String.class;
103
		}
106
		}
104
		
107
105
		public Object createValue(IObservableValue observable) {
108
		public Object createValue(IObservableValue observable) {
106
			return observable.getValue() + "a";
109
			return observable.getValue() + "a";
107
		}
110
		}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/TextObservableValueTest.java (-18 / +29 lines)
Lines 7-21 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 116920
10
 *     Brad Reynolds - bug 116920, 164653
11
 *     Brad Reynolds - bug 164653
12
 *     Ashley Cambrell - bug 198904
11
 *     Ashley Cambrell - bug 198904
12
 *     Matthew Hall - bug 194734, 195222
13
 *******************************************************************************/
13
 *******************************************************************************/
14
14
15
package org.eclipse.jface.tests.internal.databinding.swt;
15
package org.eclipse.jface.tests.internal.databinding.swt;
16
16
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
17
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
19
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
18
import org.eclipse.jface.internal.databinding.swt.TextObservableValue;
20
import org.eclipse.jface.databinding.swt.WidgetProperties;
19
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
21
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
20
import org.eclipse.swt.SWT;
22
import org.eclipse.swt.SWT;
21
import org.eclipse.swt.widgets.Shell;
23
import org.eclipse.swt.widgets.Shell;
Lines 35-41 Link Here
35
37
36
		Shell shell = new Shell();
38
		Shell shell = new Shell();
37
		text = new Text(shell, SWT.NONE);
39
		text = new Text(shell, SWT.NONE);
38
		
40
39
		listener = new ValueChangeEventTracker();
41
		listener = new ValueChangeEventTracker();
40
	}
42
	}
41
43
Lines 45-92 Link Here
45
	 */
47
	 */
46
	public void testConstructorUpdateEventTypes() {
48
	public void testConstructorUpdateEventTypes() {
47
		try {
49
		try {
48
			new TextObservableValue(text, SWT.NONE);
50
			WidgetProperties.text(SWT.None);
49
			new TextObservableValue(text, SWT.FocusOut);
51
			WidgetProperties.text(SWT.FocusOut);
50
			new TextObservableValue(text, SWT.Modify);
52
			WidgetProperties.text(SWT.Modify);
51
			assertTrue(true);
53
			assertTrue(true);
52
		} catch (IllegalArgumentException e) {
54
		} catch (IllegalArgumentException e) {
53
			fail();
55
			fail();
54
		}
56
		}
55
57
56
		try {
58
		try {
57
			new TextObservableValue(text, SWT.Verify);
59
			WidgetProperties.text(SWT.Verify);
58
			fail();
60
			fail();
59
		} catch (IllegalArgumentException e) {
61
		} catch (IllegalArgumentException e) {
60
			assertTrue(true);
62
			assertTrue(true);
61
		}
63
		}
62
	}
64
	}
63
	
65
64
	/**
66
	/**
65
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=171132
67
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=171132
66
	 * 
68
	 * 
67
	 * @throws Exception
69
	 * @throws Exception
68
	 */
70
	 */
69
	public void testGetValueBeforeFocusOutChangeEventsFire() throws Exception {
71
	public void testGetValueBeforeFocusOutChangeEventsFire() throws Exception {
70
		TextObservableValue observableValue = new TextObservableValue(text, SWT.FocusOut);
72
		IObservableValue observableValue = WidgetProperties.text(SWT.FocusOut)
73
				.observe(Realm.getDefault(), text);
71
		observableValue.addValueChangeListener(listener);
74
		observableValue.addValueChangeListener(listener);
72
		
75
73
		String a = "a";
76
		String a = "a";
74
		String b = "b";
77
		String b = "b";
75
		
78
76
		text.setText(a);
79
		text.setText(a);
77
		assertEquals(a, observableValue.getValue()); //fetch the value updating the buffered value
80
78
		
81
		assertEquals(0, listener.count);
82
83
		// fetching the value updates the buffered value
84
		assertEquals(a, observableValue.getValue());
85
		assertEquals(1, listener.count);
86
79
		text.setText(b);
87
		text.setText(b);
80
		text.notifyListeners(SWT.FocusOut, null);
88
81
		
82
		assertEquals(1, listener.count);
89
		assertEquals(1, listener.count);
90
91
		text.notifyListeners(SWT.FocusOut, null);
92
93
		assertEquals(2, listener.count);
83
		assertEquals(a, listener.event.diff.getOldValue());
94
		assertEquals(a, listener.event.diff.getOldValue());
84
		assertEquals(b, listener.event.diff.getNewValue());
95
		assertEquals(b, listener.event.diff.getNewValue());
85
	}
96
	}
86
97
87
	public void testDispose() throws Exception {
98
	public void testDispose() throws Exception {
88
		TextObservableValue observableValue = new TextObservableValue(text,
99
		IObservableValue observableValue = WidgetProperties.text(SWT.Modify)
89
				SWT.Modify);
100
				.observe(Realm.getDefault(), text);
90
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
101
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
91
		observableValue.addValueChangeListener(testCounterValueChangeListener);
102
		observableValue.addValueChangeListener(testCounterValueChangeListener);
92
103
(-)src/org/eclipse/jface/tests/internal/databinding/swt/CComboSingleSelectionObservableValueTest.java (-16 / +18 lines)
Lines 8-14 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Ashley Cambrell - bug 198903
10
 *     Ashley Cambrell - bug 198903
11
 *     Matthew Hall - bug 213145
11
 *     Matthew Hall - bug 213145, 194734, 195222
12
 ******************************************************************************/
12
 ******************************************************************************/
13
13
14
package org.eclipse.jface.tests.internal.databinding.swt;
14
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 21-28 Link Here
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.ISWTObservable;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.CComboSingleSelectionObservableValue;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
26
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
27
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.custom.CCombo;
28
import org.eclipse.swt.custom.CCombo;
Lines 31-41 Link Here
31
/**
31
/**
32
 * @since 3.2
32
 * @since 3.2
33
 */
33
 */
34
public class CComboSingleSelectionObservableValueTest extends AbstractSWTTestCase {
34
public class CComboSingleSelectionObservableValueTest extends
35
		AbstractSWTTestCase {
35
	public void testSetValue() throws Exception {
36
	public void testSetValue() throws Exception {
36
		CCombo combo = new CCombo(getShell(), SWT.NONE);
37
		CCombo combo = new CCombo(getShell(), SWT.NONE);
37
		CComboSingleSelectionObservableValue observableValue = new CComboSingleSelectionObservableValue(
38
		IObservableValue observableValue = SWTObservables
38
				combo);
39
				.observeSingleSelectionIndex(combo);
39
		combo.add("Item1");
40
		combo.add("Item1");
40
		combo.add("Item2");
41
		combo.add("Item2");
41
42
Lines 52-60 Link Here
52
	}
53
	}
53
54
54
	public static Test suite() {
55
	public static Test suite() {
55
		TestSuite suite = new TestSuite(CComboSingleSelectionObservableValueTest.class.getName());
56
		TestSuite suite = new TestSuite(
57
				CComboSingleSelectionObservableValueTest.class.getName());
56
		suite.addTestSuite(CComboSingleSelectionObservableValueTest.class);
58
		suite.addTestSuite(CComboSingleSelectionObservableValueTest.class);
57
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
59
		suite.addTest(SWTMutableObservableValueContractTest
60
				.suite(new Delegate()));
58
		return suite;
61
		return suite;
59
	}
62
	}
60
63
Lines 75-87 Link Here
75
		}
78
		}
76
79
77
		public IObservableValue createObservableValue(Realm realm) {
80
		public IObservableValue createObservableValue(Realm realm) {
78
			return new CComboSingleSelectionObservableValue(realm, combo);
81
			return WidgetProperties.singleSelectionIndex()
82
					.observe(realm, combo);
79
		}
83
		}
80
84
81
		public void change(IObservable observable) {
85
		public void change(IObservable observable) {
82
			int index = _createValue((IObservableValue) observable);
86
			IObservableValue value = (IObservableValue) observable;
83
			combo.select(index);
87
			value.setValue(createValue(value));
84
			combo.notifyListeners(SWT.Selection, null);
85
		}
88
		}
86
89
87
		public Object getValueType(IObservableValue observable) {
90
		public Object getValueType(IObservableValue observable) {
Lines 91-102 Link Here
91
		public Object createValue(IObservableValue observable) {
94
		public Object createValue(IObservableValue observable) {
92
			return new Integer(_createValue(observable));
95
			return new Integer(_createValue(observable));
93
		}
96
		}
94
		
97
95
		private int _createValue(IObservableValue observable) {
98
		private int _createValue(IObservableValue observable) {
96
			CCombo combo = ((CCombo) ((ISWTObservable) observable).getWidget());
97
			int value = Math.max(0, combo.getSelectionIndex());
99
			int value = Math.max(0, combo.getSelectionIndex());
98
			
100
99
			//returns either 0 or 1 depending upon current value
101
			// returns either 0 or 1 depending upon current value
100
			return Math.abs(value - 1);
102
			return Math.abs(value - 1);
101
		}
103
		}
102
	}
104
	}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/SWTDelayedObservableValueDecoratorTest.java (-45 / +8 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Matthew Hall - initial API and implementation (bug 212223)
9
 *     Matthew Hall - initial API and implementation (bug 212223)
10
 *     Matthew Hall - bug 213145, 245647
10
 *     Matthew Hall - bug 213145, 245647, 194734
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 15-36 Link Here
15
import junit.framework.Test;
15
import junit.framework.Test;
16
import junit.framework.TestSuite;
16
import junit.framework.TestSuite;
17
17
18
import org.eclipse.core.databinding.observable.Diffs;
19
import org.eclipse.core.databinding.observable.IObservable;
18
import org.eclipse.core.databinding.observable.IObservable;
20
import org.eclipse.core.databinding.observable.Realm;
19
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
20
import org.eclipse.core.databinding.observable.value.IObservableValue;
21
import org.eclipse.core.databinding.observable.value.WritableValue;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
25
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
25
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
27
import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTObservableValue;
27
import org.eclipse.jface.internal.databinding.swt.SWTObservableValueDecorator;
28
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
28
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
29
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.SWT;
30
import org.eclipse.swt.widgets.Display;
30
import org.eclipse.swt.widgets.Display;
31
import org.eclipse.swt.widgets.Event;
31
import org.eclipse.swt.widgets.Event;
32
import org.eclipse.swt.widgets.Shell;
32
import org.eclipse.swt.widgets.Shell;
33
import org.eclipse.swt.widgets.Widget;
34
33
35
/**
34
/**
36
 * Tests for DelayedObservableValue
35
 * Tests for DelayedObservableValue
Lines 43-57 Link Here
43
	private Shell shell;
42
	private Shell shell;
44
	private Object oldValue;
43
	private Object oldValue;
45
	private Object newValue;
44
	private Object newValue;
46
	private SWTObservableValueStub target;
45
	private ISWTObservableValue target;
47
	private ISWTObservableValue delayed;
46
	private ISWTObservableValue delayed;
48
47
49
	protected void setUp() throws Exception {
48
	protected void setUp() throws Exception {
50
		super.setUp();
49
		super.setUp();
51
		display = Display.getCurrent();
50
		display = Display.getCurrent();
52
		shell = new Shell(display);
51
		shell = new Shell(display);
53
		target = new SWTObservableValueStub(SWTObservables.getRealm(display),
52
		target = new SWTObservableValueDecorator(new WritableValue(
54
				shell);
53
				SWTObservables.getRealm(display)), shell);
55
		oldValue = new Object();
54
		oldValue = new Object();
56
		newValue = new Object();
55
		newValue = new Object();
57
		target.setValue(oldValue);
56
		target.setValue(oldValue);
Lines 93-135 Link Here
93
		assertEquals(newValue, tracker.event.diff.getNewValue());
92
		assertEquals(newValue, tracker.event.diff.getNewValue());
94
	}
93
	}
95
94
96
	static class SWTObservableValueStub extends AbstractSWTObservableValue {
97
		private Object value;
98
		private boolean stale;
99
100
		Object overrideValue;
101
102
		public SWTObservableValueStub(Realm realm, Widget widget) {
103
			super(realm, widget);
104
		}
105
106
		protected Object doGetValue() {
107
			return value;
108
		}
109
110
		protected void doSetValue(Object value) {
111
			Object oldValue = this.value;
112
			if (overrideValue != null)
113
				value = overrideValue;
114
			this.value = value;
115
			stale = false;
116
			fireValueChange(Diffs.createValueDiff(oldValue, value));
117
		}
118
119
		public Object getValueType() {
120
			return Object.class;
121
		}
122
123
		protected void fireStale() {
124
			stale = true;
125
			super.fireStale();
126
		}
127
128
		public boolean isStale() {
129
			return stale;
130
		}
131
	}
132
133
	public static Test suite() {
95
	public static Test suite() {
134
		TestSuite suite = new TestSuite(
96
		TestSuite suite = new TestSuite(
135
				SWTDelayedObservableValueDecoratorTest.class.getName());
97
				SWTDelayedObservableValueDecoratorTest.class.getName());
Lines 155-161 Link Here
155
117
156
		public IObservableValue createObservableValue(Realm realm) {
118
		public IObservableValue createObservableValue(Realm realm) {
157
			return SWTObservables.observeDelayedValue(0,
119
			return SWTObservables.observeDelayedValue(0,
158
					new SWTObservableValueStub(realm, shell));
120
					new SWTObservableValueDecorator(new WritableValue(realm,
121
							null, Object.class), shell));
159
		}
122
		}
160
123
161
		public Object getValueType(IObservableValue observable) {
124
		public Object getValueType(IObservableValue observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/SpinnerObservableValueMinTest.java (-10 / +12 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-29 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.jface.internal.databinding.swt.SpinnerObservableValue;
27
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Shell;
28
import org.eclipse.swt.widgets.Shell;
Lines 46-62 Link Here
46
	public SpinnerObservableValueMinTest(String testName) {
45
	public SpinnerObservableValueMinTest(String testName) {
47
		super(testName, new Delegate());
46
		super(testName, new Delegate());
48
	}
47
	}
49
	
48
50
	protected void setUp() throws Exception {
49
	protected void setUp() throws Exception {
51
		super.setUp();
50
		super.setUp();
52
		
51
53
		delegate = (Delegate) getObservableContractDelegate();
52
		delegate = (Delegate) getObservableContractDelegate();
54
		observable = (IObservableValue) getObservable();
53
		observable = (IObservableValue) getObservable();
55
		spinner = delegate.spinner;
54
		spinner = delegate.spinner;
56
	}
55
	}
57
	
56
58
	protected IObservable doCreateObservable() {
57
	protected IObservable doCreateObservable() {
59
		return getObservableContractDelegate().createObservable(SWTObservables.getRealm(Display.getDefault()));
58
		return getObservableContractDelegate().createObservable(
59
				SWTObservables.getRealm(Display.getDefault()));
60
	}
60
	}
61
61
62
	public void testGetValue() throws Exception {
62
	public void testGetValue() throws Exception {
Lines 72-80 Link Here
72
	}
72
	}
73
73
74
	public static Test suite() {
74
	public static Test suite() {
75
		TestSuite suite = new TestSuite(SpinnerObservableValueMinTest.class.toString());
75
		TestSuite suite = new TestSuite(SpinnerObservableValueMinTest.class
76
				.toString());
76
		suite.addTestSuite(SpinnerObservableValueMinTest.class);
77
		suite.addTestSuite(SpinnerObservableValueMinTest.class);
77
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
78
		suite.addTest(SWTMutableObservableValueContractTest
79
				.suite(new Delegate()));
78
		return suite;
80
		return suite;
79
	}
81
	}
80
82
Lines 95-101 Link Here
95
		}
97
		}
96
98
97
		public IObservableValue createObservableValue(Realm realm) {
99
		public IObservableValue createObservableValue(Realm realm) {
98
			return new SpinnerObservableValue(realm, spinner, SWTProperties.MIN);
100
			return WidgetProperties.minimum().observe(realm, spinner);
99
		}
101
		}
100
102
101
		public void change(IObservable observable) {
103
		public void change(IObservable observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/SpinnerObservableValueMaxTest.java (-10 / +12 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-29 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.jface.internal.databinding.swt.SpinnerObservableValue;
27
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Shell;
28
import org.eclipse.swt.widgets.Shell;
Lines 46-52 Link Here
46
	public SpinnerObservableValueMaxTest(String testName) {
45
	public SpinnerObservableValueMaxTest(String testName) {
47
		super(testName, new Delegate());
46
		super(testName, new Delegate());
48
	}
47
	}
49
	
48
50
	protected void setUp() throws Exception {
49
	protected void setUp() throws Exception {
51
		super.setUp();
50
		super.setUp();
52
51
Lines 54-62 Link Here
54
		observable = (IObservableValue) getObservable();
53
		observable = (IObservableValue) getObservable();
55
		spinner = delegate.spinner;
54
		spinner = delegate.spinner;
56
	}
55
	}
57
	
56
58
	protected IObservable doCreateObservable() {
57
	protected IObservable doCreateObservable() {
59
		return getObservableContractDelegate().createObservable(SWTObservables.getRealm(Display.getDefault()));
58
		return getObservableContractDelegate().createObservable(
59
				SWTObservables.getRealm(Display.getDefault()));
60
	}
60
	}
61
61
62
	public void testGetValue() throws Exception {
62
	public void testGetValue() throws Exception {
Lines 70-80 Link Here
70
		observable.setValue(new Integer(max));
70
		observable.setValue(new Integer(max));
71
		assertEquals(max, spinner.getMaximum());
71
		assertEquals(max, spinner.getMaximum());
72
	}
72
	}
73
	
73
74
	public static Test suite() {
74
	public static Test suite() {
75
		TestSuite suite = new TestSuite(SpinnerObservableValueMaxTest.class.toString());
75
		TestSuite suite = new TestSuite(SpinnerObservableValueMaxTest.class
76
				.toString());
76
		suite.addTestSuite(SpinnerObservableValueMaxTest.class);
77
		suite.addTestSuite(SpinnerObservableValueMaxTest.class);
77
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
78
		suite.addTest(SWTMutableObservableValueContractTest
79
				.suite(new Delegate()));
78
		return suite;
80
		return suite;
79
	}
81
	}
80
82
Lines 95-101 Link Here
95
		}
97
		}
96
98
97
		public IObservableValue createObservableValue(Realm realm) {
99
		public IObservableValue createObservableValue(Realm realm) {
98
			return new SpinnerObservableValue(realm, spinner, SWTProperties.MAX);
100
			return WidgetProperties.maximum().observe(realm, spinner);
99
		}
101
		}
100
102
101
		public void change(IObservable observable) {
103
		public void change(IObservable observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ButtonObservableValueTest.java (-24 / +26 lines)
Lines 8-14 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Ashley Cambrell - bug 198904
10
 *     Ashley Cambrell - bug 198904
11
 *     Matthew Hall - bug 213145
11
 *     Matthew Hall - bug 213145, 194734, 195222
12
 ******************************************************************************/
12
 ******************************************************************************/
13
13
14
package org.eclipse.jface.tests.internal.databinding.swt;
14
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-28 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
25
import org.eclipse.jface.internal.databinding.swt.ButtonObservableValue;
25
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
27
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
28
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
27
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.widgets.Button;
30
import org.eclipse.swt.widgets.Button;
Lines 33-54 Link Here
33
 */
35
 */
34
public class ButtonObservableValueTest extends AbstractSWTTestCase {
36
public class ButtonObservableValueTest extends AbstractSWTTestCase {
35
	private Button button;
37
	private Button button;
36
	private ButtonObservableValue observableValue;
38
	private ISWTObservableValue observableValue;
37
	private ValueChangeEventTracker listener;
39
	private ValueChangeEventTracker listener;
38
	
40
39
	/* (non-Javadoc)
40
	 * @see junit.framework.TestCase#setUp()
41
	 */
42
	protected void setUp() throws Exception {
41
	protected void setUp() throws Exception {
43
		super.setUp();
42
		super.setUp();
44
		
43
45
		Shell shell = getShell();
44
		Shell shell = getShell();
46
		button = new Button(shell, SWT.CHECK);
45
		button = new Button(shell, SWT.CHECK);
47
		observableValue = new ButtonObservableValue(
46
		observableValue = SWTObservables.observeSelection(button);
48
				button);
49
		listener = new ValueChangeEventTracker();
47
		listener = new ValueChangeEventTracker();
50
	}
48
	}
51
	
49
52
	public void testSelection_ChangeNotifiesObservable() throws Exception {
50
	public void testSelection_ChangeNotifiesObservable() throws Exception {
53
		observableValue.addValueChangeListener(listener);
51
		observableValue.addValueChangeListener(listener);
54
		button.setSelection(true);
52
		button.setSelection(true);
Lines 60-78 Link Here
60
		assertEquals("Selection event should notify observable.", 1,
58
		assertEquals("Selection event should notify observable.", 1,
61
				listener.count);
59
				listener.count);
62
	}
60
	}
63
	
61
64
	public void testSelection_NoChange() throws Exception {
62
	public void testSelection_NoChange() throws Exception {
65
		button.setSelection(true);
63
		button.setSelection(true);
66
		button.notifyListeners(SWT.Selection, null);
64
		button.notifyListeners(SWT.Selection, null);
67
		observableValue.addValueChangeListener(listener);
65
		observableValue.addValueChangeListener(listener);
68
		
66
69
		//precondition
67
		// precondition
70
		assertEquals(0, listener.count);
68
		assertEquals(0, listener.count);
71
		
69
72
		button.notifyListeners(SWT.Selection, null);
70
		button.notifyListeners(SWT.Selection, null);
73
		assertEquals("Value did not change.  Listeners should not have been notified.", 0, listener.count);
71
		assertEquals(
72
				"Value did not change.  Listeners should not have been notified.",
73
				0, listener.count);
74
	}
74
	}
75
	
75
76
	public void testSetValue_NullConvertedToFalse() {
76
	public void testSetValue_NullConvertedToFalse() {
77
		button.setSelection(true);
77
		button.setSelection(true);
78
		assertEquals(Boolean.TRUE, observableValue.getValue());
78
		assertEquals(Boolean.TRUE, observableValue.getValue());
Lines 104-112 Link Here
104
	}
104
	}
105
105
106
	public static Test suite() {
106
	public static Test suite() {
107
		TestSuite suite = new TestSuite(ButtonObservableValueTest.class.getName());
107
		TestSuite suite = new TestSuite(ButtonObservableValueTest.class
108
				.getName());
108
		suite.addTestSuite(ButtonObservableValueTest.class);
109
		suite.addTestSuite(ButtonObservableValueTest.class);
109
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
110
		suite.addTest(SWTMutableObservableValueContractTest
111
				.suite(new Delegate()));
110
		return suite;
112
		return suite;
111
	}
113
	}
112
114
Lines 130-136 Link Here
130
		}
132
		}
131
133
132
		public IObservableValue createObservableValue(Realm realm) {
134
		public IObservableValue createObservableValue(Realm realm) {
133
			return new ButtonObservableValue(realm, button);
135
			return WidgetProperties.selection().observe(realm, button);
134
		}
136
		}
135
137
136
		public Object getValueType(IObservableValue observable) {
138
		public Object getValueType(IObservableValue observable) {
Lines 138-151 Link Here
138
		}
140
		}
139
141
140
		public void change(IObservable observable) {
142
		public void change(IObservable observable) {
141
			button.setSelection(changeValue(button));
143
			((IObservableValue) observable).setValue(Boolean
142
			button.notifyListeners(SWT.Selection, null);
144
					.valueOf(changeValue(button)));
143
		}
145
		}
144
		
146
145
		public Object createValue(IObservableValue observable) {
147
		public Object createValue(IObservableValue observable) {
146
			return Boolean.valueOf(changeValue(button));
148
			return Boolean.valueOf(changeValue(button));
147
		}
149
		}
148
		
150
149
		private boolean changeValue(Button button) {
151
		private boolean changeValue(Button button) {
150
			return !button.getSelection();
152
			return !button.getSelection();
151
		}
153
		}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ScaleObservableValueMinTest.java (-10 / +12 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-29 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.jface.internal.databinding.swt.ScaleObservableValue;
27
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Scale;
28
import org.eclipse.swt.widgets.Scale;
Lines 42-52 Link Here
42
	public ScaleObservableValueMinTest() {
41
	public ScaleObservableValueMinTest() {
43
		this(null);
42
		this(null);
44
	}
43
	}
45
	
44
46
	public ScaleObservableValueMinTest(String testName) {
45
	public ScaleObservableValueMinTest(String testName) {
47
		super(testName, new Delegate());
46
		super(testName, new Delegate());
48
	}
47
	}
49
	
48
50
	protected void setUp() throws Exception {
49
	protected void setUp() throws Exception {
51
		super.setUp();
50
		super.setUp();
52
51
Lines 56-64 Link Here
56
	}
55
	}
57
56
58
	protected IObservable doCreateObservable() {
57
	protected IObservable doCreateObservable() {
59
		return getObservableContractDelegate().createObservable(SWTObservables.getRealm(Display.getDefault()));
58
		return getObservableContractDelegate().createObservable(
59
				SWTObservables.getRealm(Display.getDefault()));
60
	}
60
	}
61
	
61
62
	public void testGetValue() throws Exception {
62
	public void testGetValue() throws Exception {
63
		int min = 100;
63
		int min = 100;
64
		scale.setMinimum(min);
64
		scale.setMinimum(min);
Lines 72-80 Link Here
72
	}
72
	}
73
73
74
	public static Test suite() {
74
	public static Test suite() {
75
		TestSuite suite = new TestSuite(ScaleObservableValueMinTest.class.toString());
75
		TestSuite suite = new TestSuite(ScaleObservableValueMinTest.class
76
				.toString());
76
		suite.addTestSuite(ScaleObservableValueMinTest.class);
77
		suite.addTestSuite(ScaleObservableValueMinTest.class);
77
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
78
		suite.addTest(SWTMutableObservableValueContractTest
79
				.suite(new Delegate()));
78
		return suite;
80
		return suite;
79
	}
81
	}
80
82
Lines 95-101 Link Here
95
		}
97
		}
96
98
97
		public IObservableValue createObservableValue(Realm realm) {
99
		public IObservableValue createObservableValue(Realm realm) {
98
			return new ScaleObservableValue(realm, scale, SWTProperties.MIN);
100
			return WidgetProperties.minimum().observe(realm, scale);
99
		}
101
		}
100
102
101
		public void change(IObservable observable) {
103
		public void change(IObservable observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ListSingleSelectionObservableValueTest.java (-5 / +7 lines)
Lines 7-17 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Ashley Cambrell - initial API and implementation
9
 *     Ashley Cambrell - initial API and implementation
10
 *     Matthew Hall - bug 194734
10
 ******************************************************************************/
11
 ******************************************************************************/
11
12
12
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
14
14
import org.eclipse.jface.internal.databinding.swt.ListSingleSelectionObservableValue;
15
import org.eclipse.core.databinding.observable.value.IObservableValue;
16
import org.eclipse.jface.databinding.swt.SWTObservables;
15
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
17
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
16
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.widgets.List;
19
import org.eclipse.swt.widgets.List;
Lines 23-30 Link Here
23
public class ListSingleSelectionObservableValueTest extends AbstractSWTTestCase {
25
public class ListSingleSelectionObservableValueTest extends AbstractSWTTestCase {
24
	public void testSetValue() throws Exception {
26
	public void testSetValue() throws Exception {
25
		List list = new List(getShell(), SWT.NONE);
27
		List list = new List(getShell(), SWT.NONE);
26
		ListSingleSelectionObservableValue observableValue = new ListSingleSelectionObservableValue(
28
		IObservableValue observableValue = SWTObservables
27
				list);
29
				.observeSingleSelectionIndex(list);
28
		list.add("Item1");
30
		list.add("Item1");
29
31
30
		assertEquals(-1, list.getSelectionIndex());
32
		assertEquals(-1, list.getSelectionIndex());
Lines 39-46 Link Here
39
41
40
	public void testDispose() throws Exception {
42
	public void testDispose() throws Exception {
41
		List list = new List(getShell(), SWT.NONE);
43
		List list = new List(getShell(), SWT.NONE);
42
		ListSingleSelectionObservableValue observableValue = new ListSingleSelectionObservableValue(
44
		IObservableValue observableValue = SWTObservables
43
				list);
45
				.observeSingleSelectionIndex(list);
44
		list.add("Item1");
46
		list.add("Item1");
45
		list.add("Item2");
47
		list.add("Item2");
46
48
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ShellObservableValueTest.java (-7 / +10 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Matthew Hall - initial API and implementation (bug 212235)
9
 *     Matthew Hall - initial API and implementation (bug 212235)
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 21-27 Link Here
21
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
21
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
22
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
23
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
24
import org.eclipse.jface.internal.databinding.swt.ShellObservableValue;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
25
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
26
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
26
import org.eclipse.swt.widgets.Shell;
27
import org.eclipse.swt.widgets.Shell;
27
28
Lines 34-46 Link Here
34
	String oldValue;
35
	String oldValue;
35
	String newValue;
36
	String newValue;
36
	Shell shell;
37
	Shell shell;
37
	ShellObservableValue observable;
38
	IObservableValue observable;
38
	ValueChangeEventTracker tracker;
39
	ValueChangeEventTracker tracker;
39
40
40
	protected void setUp() throws Exception {
41
	protected void setUp() throws Exception {
41
		super.setUp();
42
		super.setUp();
42
		shell = new Shell();
43
		shell = new Shell();
43
		observable = new ShellObservableValue(shell);
44
		observable = SWTObservables.observeText(shell);
44
		oldValue = "old";
45
		oldValue = "old";
45
		newValue = "new";
46
		newValue = "new";
46
		shell.setText(oldValue);
47
		shell.setText(oldValue);
Lines 88-96 Link Here
88
	}
89
	}
89
90
90
	public static Test suite() {
91
	public static Test suite() {
91
		TestSuite suite = new TestSuite(ShellObservableValueTest.class.toString());
92
		TestSuite suite = new TestSuite(ShellObservableValueTest.class
93
				.toString());
92
		suite.addTestSuite(ShellObservableValueTest.class);
94
		suite.addTestSuite(ShellObservableValueTest.class);
93
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
95
		suite.addTest(SWTMutableObservableValueContractTest
96
				.suite(new Delegate()));
94
		return suite;
97
		return suite;
95
	}
98
	}
96
99
Lines 109-115 Link Here
109
		}
112
		}
110
113
111
		public IObservableValue createObservableValue(Realm realm) {
114
		public IObservableValue createObservableValue(Realm realm) {
112
			return new ShellObservableValue(realm, shell);
115
			return WidgetProperties.text().observe(realm, shell);
113
		}
116
		}
114
117
115
		public Object getValueType(IObservableValue observable) {
118
		public Object getValueType(IObservableValue observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ComboSingleSelectionObservableValueTest.java (-3 / +5 lines)
Lines 7-16 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Ashley Cambrell - initial API and implementation (bug 198903)
9
 *     Ashley Cambrell - initial API and implementation (bug 198903)
10
 *     Matthew Hall - bug 194734
10
 ******************************************************************************/
11
 ******************************************************************************/
11
package org.eclipse.jface.tests.internal.databinding.swt;
12
package org.eclipse.jface.tests.internal.databinding.swt;
12
13
13
import org.eclipse.jface.internal.databinding.swt.ComboSingleSelectionObservableValue;
14
import org.eclipse.core.databinding.observable.value.IObservableValue;
15
import org.eclipse.jface.databinding.swt.SWTObservables;
14
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
16
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
15
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.SWT;
16
import org.eclipse.swt.widgets.Combo;
18
import org.eclipse.swt.widgets.Combo;
Lines 23-30 Link Here
23
		AbstractSWTTestCase {
25
		AbstractSWTTestCase {
24
	public void testSetValue() throws Exception {
26
	public void testSetValue() throws Exception {
25
		Combo combo = new Combo(getShell(), SWT.NONE);
27
		Combo combo = new Combo(getShell(), SWT.NONE);
26
		ComboSingleSelectionObservableValue observableValue = new ComboSingleSelectionObservableValue(
28
		IObservableValue observableValue = SWTObservables
27
				combo);
29
				.observeSingleSelectionIndex(combo);
28
		combo.add("Item1");
30
		combo.add("Item1");
29
		combo.add("Item2");
31
		combo.add("Item2");
30
32
(-)src/org/eclipse/jface/tests/internal/databinding/swt/CComboObservableValueTextTest.java (-9 / +9 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-31 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
25
import org.eclipse.jface.databinding.swt.ISWTObservable;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.databinding.swt.SWTObservables;
27
import org.eclipse.jface.internal.databinding.swt.CComboObservableValue;
26
import org.eclipse.jface.databinding.swt.WidgetProperties;
28
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
29
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.SWT;
30
import org.eclipse.swt.custom.CCombo;
28
import org.eclipse.swt.custom.CCombo;
31
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Display;
Lines 66-74 Link Here
66
	}
64
	}
67
65
68
	public static Test suite() {
66
	public static Test suite() {
69
		TestSuite suite = new TestSuite(CComboObservableValueTextTest.class.getName());
67
		TestSuite suite = new TestSuite(CComboObservableValueTextTest.class
68
				.getName());
70
		suite.addTestSuite(CComboObservableValueTextTest.class);
69
		suite.addTestSuite(CComboObservableValueTextTest.class);
71
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
70
		suite.addTest(SWTMutableObservableValueContractTest
71
				.suite(new Delegate()));
72
		return suite;
72
		return suite;
73
	}
73
	}
74
74
Lines 88-99 Link Here
88
		}
88
		}
89
89
90
		public IObservableValue createObservableValue(Realm realm) {
90
		public IObservableValue createObservableValue(Realm realm) {
91
			return new CComboObservableValue(realm, combo, SWTProperties.TEXT);
91
			return WidgetProperties.text().observe(realm, combo);
92
		}
92
		}
93
93
94
		public void change(IObservable observable) {
94
		public void change(IObservable observable) {
95
			CCombo combo = (CCombo) ((ISWTObservable) observable).getWidget();
95
			IObservableValue ov = (IObservableValue) observable;
96
			combo.setText(combo.getText() + "a");
96
			ov.setValue(createValue(ov));
97
		}
97
		}
98
98
99
		public Object getValueType(IObservableValue observable) {
99
		public Object getValueType(IObservableValue observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ComboObservableValueTextTest.java (-9 / +9 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-31 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
25
import org.eclipse.jface.databinding.swt.ISWTObservable;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.databinding.swt.SWTObservables;
27
import org.eclipse.jface.internal.databinding.swt.ComboObservableValue;
26
import org.eclipse.jface.databinding.swt.WidgetProperties;
28
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
29
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.SWT;
30
import org.eclipse.swt.widgets.Combo;
28
import org.eclipse.swt.widgets.Combo;
31
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Display;
Lines 67-75 Link Here
67
	}
65
	}
68
66
69
	public static Test suite() {
67
	public static Test suite() {
70
		TestSuite suite = new TestSuite(ComboObservableValueTextTest.class.toString());
68
		TestSuite suite = new TestSuite(ComboObservableValueTextTest.class
69
				.toString());
71
		suite.addTestSuite(ComboObservableValueTextTest.class);
70
		suite.addTestSuite(ComboObservableValueTextTest.class);
72
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
71
		suite.addTest(SWTMutableObservableValueContractTest
72
				.suite(new Delegate()));
73
		return suite;
73
		return suite;
74
	}
74
	}
75
75
Lines 89-100 Link Here
89
		}
89
		}
90
90
91
		public IObservableValue createObservableValue(Realm realm) {
91
		public IObservableValue createObservableValue(Realm realm) {
92
			return new ComboObservableValue(realm, combo, SWTProperties.TEXT);
92
			return WidgetProperties.text().observe(realm, combo);
93
		}
93
		}
94
94
95
		public void change(IObservable observable) {
95
		public void change(IObservable observable) {
96
			Combo combo = (Combo) ((ISWTObservable) observable).getWidget();
96
			((IObservableValue) observable)
97
			combo.setText(combo.getText() + "a");
97
					.setValue(createValue((IObservableValue) observable));
98
		}
98
		}
99
99
100
		public Object getValueType(IObservableValue observable) {
100
		public Object getValueType(IObservableValue observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/SpinnerObservableValueSelectionTest.java (-11 / +12 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 22-29 Link Here
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
24
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.jface.internal.databinding.swt.SpinnerObservableValue;
27
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Shell;
28
import org.eclipse.swt.widgets.Shell;
Lines 38-44 Link Here
38
	private Spinner spinner;
37
	private Spinner spinner;
39
38
40
	private IObservableValue observable;
39
	private IObservableValue observable;
41
	
40
42
	public SpinnerObservableValueSelectionTest() {
41
	public SpinnerObservableValueSelectionTest() {
43
		this(null);
42
		this(null);
44
	}
43
	}
Lines 56-62 Link Here
56
	}
55
	}
57
56
58
	protected IObservable doCreateObservable() {
57
	protected IObservable doCreateObservable() {
59
		return getObservableContractDelegate().createObservable(SWTObservables.getRealm(Display.getDefault()));
58
		return getObservableContractDelegate().createObservable(
59
				SWTObservables.getRealm(Display.getDefault()));
60
	}
60
	}
61
61
62
	public void testGetValue() throws Exception {
62
	public void testGetValue() throws Exception {
Lines 72-80 Link Here
72
	}
72
	}
73
73
74
	public static Test suite() {
74
	public static Test suite() {
75
		TestSuite suite = new TestSuite(SpinnerObservableValueSelectionTest.class.toString());
75
		TestSuite suite = new TestSuite(
76
				SpinnerObservableValueSelectionTest.class.toString());
76
		suite.addTestSuite(SpinnerObservableValueSelectionTest.class);
77
		suite.addTestSuite(SpinnerObservableValueSelectionTest.class);
77
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
78
		suite.addTest(SWTMutableObservableValueContractTest
79
				.suite(new Delegate()));
78
		return suite;
80
		return suite;
79
	}
81
	}
80
82
Lines 95-107 Link Here
95
		}
97
		}
96
98
97
		public IObservableValue createObservableValue(Realm realm) {
99
		public IObservableValue createObservableValue(Realm realm) {
98
			return new SpinnerObservableValue(realm, spinner, SWTProperties.SELECTION);
100
			return WidgetProperties.selection().observe(realm, spinner);
99
		}
101
		}
100
102
101
		public void change(IObservable observable) {
103
		public void change(IObservable observable) {
102
			spinner
104
			spinner.setSelection(createIntegerValue(
103
					.setSelection(createIntegerValue(
105
					(IObservableValue) observable).intValue());
104
							(IObservableValue) observable).intValue());
105
			spinner.notifyListeners(SWT.Selection, null);
106
			spinner.notifyListeners(SWT.Selection, null);
106
		}
107
		}
107
108
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ComboObservableValueTest.java (-16 / +22 lines)
Lines 8-20 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Ashley Cambrell - bug 198904
10
 *     Ashley Cambrell - bug 198904
11
 *     Matthew Hall - bug 194734, 195222
11
 ******************************************************************************/
12
 ******************************************************************************/
12
13
13
package org.eclipse.jface.tests.internal.databinding.swt;
14
package org.eclipse.jface.tests.internal.databinding.swt;
14
15
16
import org.eclipse.core.databinding.observable.Realm;
17
import org.eclipse.core.databinding.observable.value.IObservableValue;
18
import org.eclipse.core.databinding.property.value.IValueProperty;
15
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
19
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
16
import org.eclipse.jface.internal.databinding.swt.ComboObservableValue;
20
import org.eclipse.jface.databinding.swt.SWTObservables;
17
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
21
import org.eclipse.jface.databinding.swt.WidgetProperties;
22
import org.eclipse.jface.internal.databinding.swt.ComboSelectionProperty;
23
import org.eclipse.jface.internal.databinding.swt.ComboTextProperty;
18
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
24
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
19
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.widgets.Combo;
26
import org.eclipse.swt.widgets.Combo;
Lines 26-33 Link Here
26
public class ComboObservableValueTest extends AbstractSWTTestCase {
32
public class ComboObservableValueTest extends AbstractSWTTestCase {
27
	public void testDispose() throws Exception {
33
	public void testDispose() throws Exception {
28
		Combo combo = new Combo(getShell(), SWT.NONE);
34
		Combo combo = new Combo(getShell(), SWT.NONE);
29
		ComboObservableValue observableValue = new ComboObservableValue(combo,
35
		IObservableValue observableValue = SWTObservables.observeText(combo);
30
				SWTProperties.TEXT);
31
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
36
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
32
		observableValue.addValueChangeListener(testCounterValueChangeListener);
37
		observableValue.addValueChangeListener(testCounterValueChangeListener);
33
38
Lines 51-75 Link Here
51
	}
56
	}
52
57
53
	public void testSetValueWithNull() {
58
	public void testSetValueWithNull() {
54
		testSetValueWithNull(SWTProperties.TEXT);
59
		testSetValueWithNull(WidgetProperties.text());
55
		testSetValueWithNull(SWTProperties.SELECTION);
60
		testSetValueWithNull(WidgetProperties.selection());
56
	}
61
	}
57
62
58
	protected void testSetValueWithNull(String observableMode) {
63
	protected void testSetValueWithNull(IValueProperty property) {
59
		Combo combo = new Combo(getShell(), SWT.NONE);
64
		Combo combo = new Combo(getShell(), SWT.NONE);
60
		combo.setItems(new String[] {"one", "two", "three"});
65
		combo.setItems(new String[] { "one", "two", "three" });
61
		ComboObservableValue observable = new ComboObservableValue(
66
		IObservableValue observable = property.observe(Realm.getDefault(),
62
				combo, observableMode);
67
				combo);
63
68
64
		observable.doSetValue("two");
69
		observable.setValue("two");
65
		assertEquals("two", combo.getText());
70
		assertEquals("two", combo.getText());
66
		if (observableMode.equals(SWTProperties.SELECTION)) {
71
		if (property instanceof ComboSelectionProperty) {
67
			assertEquals("expect selection at index 1 in mode " + observableMode, 1, combo.getSelectionIndex());
72
			assertEquals("expect selection at index 1 in selection mode", 1,
73
					combo.getSelectionIndex());
68
		}
74
		}
69
75
70
		if (observableMode.equals(SWTProperties.TEXT)) {
76
		if (property instanceof ComboTextProperty) {
71
			observable.doSetValue(null);
77
			observable.setValue(null);
72
			assertEquals("expect empty text in mode " + observableMode, "", combo.getText());
78
			assertEquals("expect empty text in text mode", "", combo.getText());
73
		}
79
		}
74
	}
80
	}
75
}
81
}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/CComboObservableValueSelectionTest.java (-12 / +11 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 24-31 Link Here
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
25
import org.eclipse.jface.databinding.swt.ISWTObservable;
25
import org.eclipse.jface.databinding.swt.ISWTObservable;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
27
import org.eclipse.jface.internal.databinding.swt.CComboObservableValue;
27
import org.eclipse.jface.databinding.swt.WidgetProperties;
28
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
29
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.SWT;
30
import org.eclipse.swt.custom.CCombo;
29
import org.eclipse.swt.custom.CCombo;
31
import org.eclipse.swt.widgets.Display;
30
import org.eclipse.swt.widgets.Display;
Lines 57-72 Link Here
57
		IObservableValue observable = (IObservableValue) delegate
56
		IObservableValue observable = (IObservableValue) delegate
58
				.createObservable(SWTObservables.getRealm(Display.getDefault()));
57
				.createObservable(SWTObservables.getRealm(Display.getDefault()));
59
58
60
		ValueChangeEventTracker listener = ValueChangeEventTracker.observe(observable);
59
		ValueChangeEventTracker listener = ValueChangeEventTracker
60
				.observe(observable);
61
		combo.select(0);
61
		combo.select(0);
62
62
63
		assertEquals("Observable was not notified.", 1, listener.count);
63
		assertEquals("Observable was not notified.", 1, listener.count);
64
	}
64
	}
65
65
66
	public static Test suite() {
66
	public static Test suite() {
67
		TestSuite suite = new TestSuite(CComboObservableValueSelectionTest.class.getName());
67
		TestSuite suite = new TestSuite(
68
				CComboObservableValueSelectionTest.class.getName());
68
		suite.addTestSuite(CComboObservableValueSelectionTest.class);
69
		suite.addTestSuite(CComboObservableValueSelectionTest.class);
69
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
70
		suite.addTest(SWTMutableObservableValueContractTest
71
				.suite(new Delegate()));
70
		return suite;
72
		return suite;
71
	}
73
	}
72
74
Lines 88-102 Link Here
88
		}
90
		}
89
91
90
		public IObservableValue createObservableValue(Realm realm) {
92
		public IObservableValue createObservableValue(Realm realm) {
91
			return new CComboObservableValue(realm, combo,
93
			return WidgetProperties.selection().observe(realm, combo);
92
					SWTProperties.SELECTION);
93
		}
94
		}
94
95
95
		public void change(IObservable observable) {
96
		public void change(IObservable observable) {
96
			int index = combo
97
			IObservableValue ov = (IObservableValue) observable;
97
					.indexOf((String) createValue((IObservableValue) observable));
98
			ov.setValue(createValue(ov));
98
99
			combo.select(index);
100
		}
99
		}
101
100
102
		public Object getValueType(IObservableValue observable) {
101
		public Object getValueType(IObservableValue observable) {
(-)src/org/eclipse/jface/tests/internal/databinding/swt/CComboObservableValueTest.java (-12 / +16 lines)
Lines 9-21 Link Here
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Ashley Cambrell - bug 198904
10
 *     Ashley Cambrell - bug 198904
11
 *     Eric Rizzo - bug 134884
11
 *     Eric Rizzo - bug 134884
12
 *     Matthew Hall - bug 194734, 195222
12
 ******************************************************************************/
13
 ******************************************************************************/
13
14
14
package org.eclipse.jface.tests.internal.databinding.swt;
15
package org.eclipse.jface.tests.internal.databinding.swt;
15
16
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.core.databinding.property.value.IValueProperty;
16
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
20
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
17
import org.eclipse.jface.internal.databinding.swt.CComboObservableValue;
21
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
18
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
22
import org.eclipse.jface.databinding.swt.SWTObservables;
23
import org.eclipse.jface.databinding.swt.WidgetProperties;
19
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
24
import org.eclipse.jface.tests.databinding.AbstractSWTTestCase;
20
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.SWT;
21
import org.eclipse.swt.custom.CCombo;
26
import org.eclipse.swt.custom.CCombo;
Lines 26-33 Link Here
26
public class CComboObservableValueTest extends AbstractSWTTestCase {
31
public class CComboObservableValueTest extends AbstractSWTTestCase {
27
	public void testDispose() throws Exception {
32
	public void testDispose() throws Exception {
28
		CCombo combo = new CCombo(getShell(), SWT.NONE);
33
		CCombo combo = new CCombo(getShell(), SWT.NONE);
29
		CComboObservableValue observableValue = new CComboObservableValue(
34
		ISWTObservableValue observableValue = SWTObservables.observeText(combo);
30
				combo, SWTProperties.TEXT);
31
35
32
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
36
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
33
		observableValue.addValueChangeListener(testCounterValueChangeListener);
37
		observableValue.addValueChangeListener(testCounterValueChangeListener);
Lines 52-72 Link Here
52
	}
56
	}
53
57
54
	public void testSetValueWithNull() {
58
	public void testSetValueWithNull() {
55
		testSetValueWithNull(SWTProperties.TEXT);
59
		testSetValueWithNull(WidgetProperties.text());
56
		testSetValueWithNull(SWTProperties.SELECTION);
60
		testSetValueWithNull(WidgetProperties.selection());
57
	}
61
	}
58
62
59
	protected void testSetValueWithNull(String observableMode) {
63
	protected void testSetValueWithNull(IValueProperty property) {
60
		CCombo combo = new CCombo(getShell(), SWT.NONE);
64
		CCombo combo = new CCombo(getShell(), SWT.NONE);
61
		combo.setItems(new String[] {"one", "two", "three"});
65
		combo.setItems(new String[] { "one", "two", "three" });
62
		CComboObservableValue observable = new CComboObservableValue(
66
		IObservableValue observable = property.observe(Realm.getDefault(),
63
				combo, observableMode);
67
				combo);
64
68
65
		observable.doSetValue("two");
69
		observable.setValue("two");
66
		assertEquals("two", combo.getText());
70
		assertEquals("two", combo.getText());
67
		assertEquals(1, combo.getSelectionIndex());
71
		assertEquals(1, combo.getSelectionIndex());
68
72
69
		observable.doSetValue(null);
73
		observable.setValue(null);
70
		assertEquals("", combo.getText());
74
		assertEquals("", combo.getText());
71
		assertEquals(-1, combo.getSelectionIndex());
75
		assertEquals(-1, combo.getSelectionIndex());
72
	}
76
	}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/TextObservableValueModifyTest.java (-7 / +9 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 21-27 Link Here
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
23
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
24
import org.eclipse.jface.internal.databinding.swt.TextObservableValue;
24
import org.eclipse.jface.databinding.swt.WidgetProperties;
25
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.widgets.Shell;
26
import org.eclipse.swt.widgets.Shell;
27
import org.eclipse.swt.widgets.Text;
27
import org.eclipse.swt.widgets.Text;
Lines 31-38 Link Here
31
 */
31
 */
32
public class TextObservableValueModifyTest extends TestCase {
32
public class TextObservableValueModifyTest extends TestCase {
33
	public static Test suite() {
33
	public static Test suite() {
34
		TestSuite suite = new TestSuite(TextObservableValueModifyTest.class.toString());
34
		TestSuite suite = new TestSuite(TextObservableValueModifyTest.class
35
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
35
				.toString());
36
		suite.addTest(SWTMutableObservableValueContractTest
37
				.suite(new Delegate()));
36
		return suite;
38
		return suite;
37
	}
39
	}
38
40
Lines 41-47 Link Here
41
		private Shell shell;
43
		private Shell shell;
42
44
43
		private Text text;
45
		private Text text;
44
		
46
45
		public void setUp() {
47
		public void setUp() {
46
			shell = new Shell();
48
			shell = new Shell();
47
			text = new Text(shell, SWT.NONE);
49
			text = new Text(shell, SWT.NONE);
Lines 52-58 Link Here
52
		}
54
		}
53
55
54
		public IObservableValue createObservableValue(Realm realm) {
56
		public IObservableValue createObservableValue(Realm realm) {
55
			return new TextObservableValue(realm, text, SWT.Modify);
57
			return WidgetProperties.text(SWT.Modify).observe(realm, text);
56
		}
58
		}
57
59
58
		public Object getValueType(IObservableValue observable) {
60
		public Object getValueType(IObservableValue observable) {
Lines 61-67 Link Here
61
63
62
		public void change(IObservable observable) {
64
		public void change(IObservable observable) {
63
			text.setFocus();
65
			text.setFocus();
64
			
66
65
			IObservableValue observableValue = (IObservableValue) observable;
67
			IObservableValue observableValue = (IObservableValue) observable;
66
			text.setText((String) createValue(observableValue));
68
			text.setText((String) createValue(observableValue));
67
		}
69
		}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/ComboObservableValueSelectionTest.java (-10 / +9 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.jface.tests.internal.databinding.swt;
13
package org.eclipse.jface.tests.internal.databinding.swt;
Lines 24-31 Link Here
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
24
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
25
import org.eclipse.jface.databinding.swt.ISWTObservable;
25
import org.eclipse.jface.databinding.swt.ISWTObservable;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
26
import org.eclipse.jface.databinding.swt.SWTObservables;
27
import org.eclipse.jface.internal.databinding.swt.ComboObservableValue;
27
import org.eclipse.jface.databinding.swt.WidgetProperties;
28
import org.eclipse.jface.internal.databinding.swt.SWTProperties;
29
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.SWT;
30
import org.eclipse.swt.widgets.Combo;
29
import org.eclipse.swt.widgets.Combo;
31
import org.eclipse.swt.widgets.Display;
30
import org.eclipse.swt.widgets.Display;
Lines 33-39 Link Here
33
32
34
/**
33
/**
35
 * @since 3.2
34
 * @since 3.2
36
 *
35
 * 
37
 */
36
 */
38
public class ComboObservableValueSelectionTest extends TestCase {
37
public class ComboObservableValueSelectionTest extends TestCase {
39
	private Delegate delegate;
38
	private Delegate delegate;
Lines 67-75 Link Here
67
	}
66
	}
68
67
69
	public static Test suite() {
68
	public static Test suite() {
70
		TestSuite suite = new TestSuite(ComboObservableValueSelectionTest.class.toString());
69
		TestSuite suite = new TestSuite(ComboObservableValueSelectionTest.class
70
				.toString());
71
		suite.addTestSuite(ComboObservableValueSelectionTest.class);
71
		suite.addTestSuite(ComboObservableValueSelectionTest.class);
72
		suite.addTest(SWTMutableObservableValueContractTest.suite(new Delegate()));
72
		suite.addTest(SWTMutableObservableValueContractTest
73
				.suite(new Delegate()));
73
		return suite;
74
		return suite;
74
	}
75
	}
75
76
Lines 91-106 Link Here
91
		}
92
		}
92
93
93
		public IObservableValue createObservableValue(Realm realm) {
94
		public IObservableValue createObservableValue(Realm realm) {
94
			return new ComboObservableValue(realm, combo,
95
			return WidgetProperties.selection().observe(realm, combo);
95
					SWTProperties.SELECTION);
96
		}
96
		}
97
97
98
		public void change(IObservable observable) {
98
		public void change(IObservable observable) {
99
			int index = combo
99
			int index = combo
100
					.indexOf((String) createValue((IObservableValue) observable));
100
					.indexOf((String) createValue((IObservableValue) observable));
101
101
102
			combo.select(index);
102
			((IObservableValue) observable).setValue(combo.getItem(index));
103
			combo.notifyListeners(SWT.Selection, null);
104
		}
103
		}
105
104
106
		public Object getValueType(IObservableValue observable) {
105
		public Object getValueType(IObservableValue observable) {
(-)src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedListTest.java (-64 / +76 lines)
Lines 7-18 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bugs 221351, 213145, 244098, 246103
10
 *     Matthew Hall - bugs 221351, 213145, 244098, 246103, 194734
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.core.tests.internal.databinding.beans;
13
package org.eclipse.core.tests.internal.databinding.beans;
14
14
15
import java.beans.IntrospectionException;
16
import java.beans.PropertyChangeEvent;
15
import java.beans.PropertyChangeEvent;
17
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyChangeListener;
18
import java.beans.PropertyDescriptor;
17
import java.beans.PropertyDescriptor;
Lines 25-38 Link Here
25
import junit.framework.Test;
24
import junit.framework.Test;
26
import junit.framework.TestSuite;
25
import junit.framework.TestSuite;
27
26
27
import org.eclipse.core.databinding.beans.BeanProperties;
28
import org.eclipse.core.databinding.beans.BeansObservables;
28
import org.eclipse.core.databinding.beans.BeansObservables;
29
import org.eclipse.core.databinding.beans.IBeanObservable;
30
import org.eclipse.core.databinding.beans.IBeanProperty;
29
import org.eclipse.core.databinding.observable.IObservable;
31
import org.eclipse.core.databinding.observable.IObservable;
30
import org.eclipse.core.databinding.observable.IObservableCollection;
32
import org.eclipse.core.databinding.observable.IObservableCollection;
31
import org.eclipse.core.databinding.observable.Realm;
33
import org.eclipse.core.databinding.observable.Realm;
32
import org.eclipse.core.databinding.observable.list.IObservableList;
34
import org.eclipse.core.databinding.observable.list.IObservableList;
33
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
35
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
34
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
36
import org.eclipse.core.databinding.observable.list.ListDiff;
35
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList;
36
import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest;
37
import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest;
37
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
38
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
38
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
39
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
Lines 46-52 Link Here
46
 */
47
 */
47
public class JavaBeanObservableArrayBasedListTest extends
48
public class JavaBeanObservableArrayBasedListTest extends
48
		AbstractDefaultRealmTestCase {
49
		AbstractDefaultRealmTestCase {
49
	private JavaBeanObservableList list;
50
	private IObservableList list;
51
	private IBeanObservable beanObservable;
50
52
51
	private PropertyDescriptor propertyDescriptor;
53
	private PropertyDescriptor propertyDescriptor;
52
54
Lines 63-91 Link Here
63
		super.setUp();
65
		super.setUp();
64
66
65
		propertyName = "array";
67
		propertyName = "array";
66
		propertyDescriptor = new PropertyDescriptor(propertyName, Bean.class);
68
		propertyDescriptor = ((IBeanProperty) BeanProperties.list(
69
				Bean.class, propertyName)).getPropertyDescriptor();
67
		bean = new Bean(new Object[0]);
70
		bean = new Bean(new Object[0]);
68
71
69
		list = new JavaBeanObservableList(SWTObservables.getRealm(Display
72
		list = BeansObservables.observeList(SWTObservables.getRealm(Display
70
				.getDefault()), bean, propertyDescriptor, Bean.class);
73
				.getDefault()), bean, propertyName);
74
		beanObservable = (IBeanObservable) list;
71
	}
75
	}
72
76
73
	public void testGetObserved() throws Exception {
77
	public void testGetObserved() throws Exception {
74
		assertSame(bean, list.getObserved());
78
		assertSame(bean, beanObservable.getObserved());
75
	}
79
	}
76
80
77
	public void testGetPropertyDescriptor() throws Exception {
81
	public void testGetPropertyDescriptor() throws Exception {
78
		assertSame(propertyDescriptor, list.getPropertyDescriptor());
82
		assertEquals(propertyDescriptor, beanObservable.getPropertyDescriptor());
79
	}
83
	}
80
84
81
	public void testRegistersListenerOnCreation()
85
	public void testRegistersListenerAfterFirstListenerIsAdded()
82
			throws Exception {
86
			throws Exception {
87
		assertFalse(bean.changeSupport.hasListeners(propertyName));
88
		list.addListChangeListener(new ListChangeEventTracker());
83
		assertTrue(bean.changeSupport.hasListeners(propertyName));
89
		assertTrue(bean.changeSupport.hasListeners(propertyName));
84
	}
90
	}
85
91
86
	public void testRemovesListenerOnDisposal()
92
	public void testRemovesListenerAfterLastListenerIsRemoved()
87
			throws Exception {
93
			throws Exception {
88
		list.dispose();
94
		ListChangeEventTracker listener = new ListChangeEventTracker();
95
		list.addListChangeListener(listener);
96
97
		assertTrue(bean.changeSupport.hasListeners(propertyName));
98
		list.removeListChangeListener(listener);
89
		assertFalse(bean.changeSupport.hasListeners(propertyName));
99
		assertFalse(bean.changeSupport.hasListeners(propertyName));
90
	}
100
	}
91
101
Lines 120-127 Link Here
120
		assertEquals(1, listener.count);
130
		assertEquals(1, listener.count);
121
		ListChangeEvent event = listener.event;
131
		ListChangeEvent event = listener.event;
122
132
123
		assertEquals(list, event.getObservableList());
133
		assertSame(list, event.getObservableList());
124
		assertEntry(event.diff.getDifferences()[0], true, 0, element);
134
		assertDiff(event.diff, Collections.EMPTY_LIST, Collections
135
				.singletonList("1"));
125
	}
136
	}
126
137
127
	public void testAdd_FiresPropertyChangeEvent() throws Exception {
138
	public void testAdd_FiresPropertyChangeEvent() throws Exception {
Lines 150-156 Link Here
150
		list.add(0, element);
161
		list.add(0, element);
151
162
152
		ListChangeEvent event = listener.event;
163
		ListChangeEvent event = listener.event;
153
		assertEntry(event.diff.getDifferences()[0], true, 0, element);
164
		assertDiff(event.diff, Collections.EMPTY_LIST, Collections
165
				.singletonList("1"));
154
	}
166
	}
155
167
156
	public void testAddAtIndexPropertyChangeEvent() throws Exception {
168
	public void testAddAtIndexPropertyChangeEvent() throws Exception {
Lines 182-189 Link Here
182
194
183
		assertEquals(1, listener.count);
195
		assertEquals(1, listener.count);
184
		ListChangeEvent event = listener.event;
196
		ListChangeEvent event = listener.event;
185
		assertEquals(list, event.getObservableList());
197
		assertSame(list, event.getObservableList());
186
		assertEntry(event.diff.getDifferences()[0], false, 0, element);
198
199
		assertDiff(event.diff, Collections.singletonList("1"),
200
				Collections.EMPTY_LIST);
187
	}
201
	}
188
202
189
	public void testRemovePropertyChangeEvent() throws Exception {
203
	public void testRemovePropertyChangeEvent() throws Exception {
Lines 218-225 Link Here
218
232
219
		assertEquals(1, listener.count);
233
		assertEquals(1, listener.count);
220
		ListChangeEvent event = listener.event;
234
		ListChangeEvent event = listener.event;
221
		assertEquals(list, event.getObservableList());
235
		assertSame(list, event.getObservableList());
222
		assertEntry(event.diff.getDifferences()[0], false, 0, element);
236
237
		assertDiff(event.diff, Collections.singletonList(element),
238
				Collections.EMPTY_LIST);
223
	}
239
	}
224
240
225
	public void testRemoveAtIndexPropertyChangeEvent() throws Exception {
241
	public void testRemoveAtIndexPropertyChangeEvent() throws Exception {
Lines 252-261 Link Here
252
268
253
		assertEquals(1, listener.count);
269
		assertEquals(1, listener.count);
254
		ListChangeEvent event = listener.event;
270
		ListChangeEvent event = listener.event;
255
		assertEquals(list, event.getObservableList());
271
		assertSame(list, event.getObservableList());
256
272
257
		assertEntry(event.diff.getDifferences()[0], true, 0, elements.get(0));
273
		assertDiff(event.diff, Collections.EMPTY_LIST, Arrays
258
		assertEntry(event.diff.getDifferences()[1], true, 1, elements.get(1));
274
				.asList(new String[] { "1", "2" }));
259
	}
275
	}
260
276
261
	public void testAddAllPropertyChangeEvent() throws Exception {
277
	public void testAddAllPropertyChangeEvent() throws Exception {
Lines 292-300 Link Here
292
308
293
		assertEquals(1, listener.count);
309
		assertEquals(1, listener.count);
294
		ListChangeEvent event = listener.event;
310
		ListChangeEvent event = listener.event;
295
		assertEquals(list, event.getObservableList());
311
		assertSame(list, event.getObservableList());
296
		assertEntry(event.diff.getDifferences()[0], true, 2, elements.get(0));
312
297
		assertEntry(event.diff.getDifferences()[1], true, 3, elements.get(1));
313
		assertDiff(event.diff, Arrays.asList(new Object[] { "1", "2" }), Arrays
314
				.asList(new Object[] { "1", "2", "1", "2" }));
298
	}
315
	}
299
316
300
	public void testAddAllAtIndexPropertyChangeEvent() throws Exception {
317
	public void testAddAllAtIndexPropertyChangeEvent() throws Exception {
Lines 306-321 Link Here
306
	}
323
	}
307
324
308
	public void testRemoveAll() throws Exception {
325
	public void testRemoveAll() throws Exception {
309
		List elements = Arrays.asList(new String[] { "1", "2" });
326
		list.addAll(Arrays.asList(new String[] { "1", "2", "3", "4" }));
310
		list.addAll(elements);
311
		list.addAll(elements);
312
313
		assertEquals(4, bean.getArray().length);
327
		assertEquals(4, bean.getArray().length);
314
		list.removeAll(elements);
328
329
		list.removeAll(Arrays.asList(new String[] { "2", "4" }));
315
330
316
		assertEquals(2, bean.getArray().length);
331
		assertEquals(2, bean.getArray().length);
317
		assertEquals(elements.get(0), bean.getArray()[0]);
332
		assertEquals("1", bean.getArray()[0]);
318
		assertEquals(elements.get(1), bean.getArray()[1]);
333
		assertEquals("3", bean.getArray()[1]);
319
	}
334
	}
320
335
321
	public void testRemoveAllListChangeEvent() throws Exception {
336
	public void testRemoveAllListChangeEvent() throws Exception {
Lines 330-338 Link Here
330
		list.removeAll(elements);
345
		list.removeAll(elements);
331
346
332
		ListChangeEvent event = listener.event;
347
		ListChangeEvent event = listener.event;
333
		assertEquals(list, event.getObservableList());
348
		assertSame(list, event.getObservableList());
334
		assertEntry(event.diff.getDifferences()[0], false, 0, elements.get(0));
349
335
		assertEntry(event.diff.getDifferences()[1], false, 0, elements.get(1));
350
		assertDiff(event.diff, Arrays
351
				.asList(new Object[] { "1", "2", "1", "2" }),
352
				Collections.EMPTY_LIST);
336
	}
353
	}
337
354
338
	public void testRemoveAllPropertyChangeEvent() throws Exception {
355
	public void testRemoveAllPropertyChangeEvent() throws Exception {
Lines 369-377 Link Here
369
386
370
		assertEquals(1, listener.count);
387
		assertEquals(1, listener.count);
371
		ListChangeEvent event = listener.event;
388
		ListChangeEvent event = listener.event;
372
		assertEquals(list, event.getObservableList());
389
		assertSame(list, event.getObservableList());
373
		assertEntry(event.diff.getDifferences()[0], false, 2, elements.get(2));
390
374
		assertEntry(event.diff.getDifferences()[1], false, 2, elements.get(3));
391
		assertDiff(event.diff, Arrays
392
				.asList(new Object[] { "0", "1", "2", "3" }), Arrays
393
				.asList(new Object[] { "0", "1" }));
375
	}
394
	}
376
395
377
	public void testRetainAllPropertyChangeEvent() throws Exception {
396
	public void testRetainAllPropertyChangeEvent() throws Exception {
Lines 425-433 Link Here
425
444
426
		assertEquals(1, listener.count);
445
		assertEquals(1, listener.count);
427
		ListChangeEvent event = listener.event;
446
		ListChangeEvent event = listener.event;
428
		assertEquals(list, event.getObservableList());
447
		assertSame(list, event.getObservableList());
429
		assertEntry(event.diff.getDifferences()[0], false, 0, oldElement);
448
430
		assertEntry(event.diff.getDifferences()[1], true, 0, newElement);
449
		assertDiff(event.diff, Collections.singletonList(oldElement),
450
				Collections.singletonList(newElement));
431
	}
451
	}
432
452
433
	public void testSetPropertyChangeEvent() throws Exception {
453
	public void testSetPropertyChangeEvent() throws Exception {
Lines 473-483 Link Here
473
		assertEquals(Collections.singletonList("new"), list);
493
		assertEquals(Collections.singletonList("new"), list);
474
	}
494
	}
475
495
476
	private static void assertEntry(ListDiffEntry entry, boolean addition,
496
	private static void assertDiff(ListDiff diff, List oldList, List newList) {
477
			int position, Object element) {
497
		oldList = new ArrayList(oldList); // defensive copy in case arg is
478
		assertEquals("addition", addition, entry.isAddition());
498
		// unmodifiable
479
		assertEquals("position", position, entry.getPosition());
499
		diff.applyTo(oldList);
480
		assertEquals("element", element, entry.getElement());
500
		assertEquals("applying diff to list did not produce expected result",
501
				newList, oldList);
481
	}
502
	}
482
503
483
	private static void assertPropertyChangeEvent(Bean bean, Runnable runnable) {
504
	private static void assertPropertyChangeEvent(Bean bean, Runnable runnable) {
Lines 492-499 Link Here
492
		PropertyChangeEvent event = listener.evt;
513
		PropertyChangeEvent event = listener.evt;
493
		assertEquals("event did not fire", 1, listener.count);
514
		assertEquals("event did not fire", 1, listener.count);
494
		assertEquals("array", event.getPropertyName());
515
		assertEquals("array", event.getPropertyName());
495
		assertTrue("old value", Arrays.equals(old, (Object[]) event.getOldValue()));
516
		assertTrue("old value", Arrays.equals(old, (Object[]) event
496
		assertTrue("new value", Arrays.equals(bean.getArray(), (Object[]) event.getNewValue()));
517
				.getOldValue()));
518
		assertTrue("new value", Arrays.equals(bean.getArray(), (Object[]) event
519
				.getNewValue()));
497
		assertFalse("lists are equal", Arrays.equals(bean.getArray(), old));
520
		assertFalse("lists are equal", Arrays.equals(bean.getArray(), old));
498
	}
521
	}
499
522
Lines 503-513 Link Here
503
526
504
		PropertyChangeEvent evt;
527
		PropertyChangeEvent evt;
505
528
506
		/*
507
		 * (non-Javadoc)
508
		 * 
509
		 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
510
		 */
511
		public void propertyChange(PropertyChangeEvent evt) {
529
		public void propertyChange(PropertyChangeEvent evt) {
512
			count++;
530
			count++;
513
			this.evt = evt;
531
			this.evt = evt;
Lines 515-521 Link Here
515
	}
533
	}
516
534
517
	public static Test suite() {
535
	public static Test suite() {
518
		TestSuite suite = new TestSuite(JavaBeanObservableArrayBasedListTest.class.getName());
536
		TestSuite suite = new TestSuite(
537
				JavaBeanObservableArrayBasedListTest.class.getName());
519
		suite.addTestSuite(JavaBeanObservableArrayBasedListTest.class);
538
		suite.addTestSuite(JavaBeanObservableArrayBasedListTest.class);
520
		suite.addTest(MutableObservableListContractTest.suite(new Delegate()));
539
		suite.addTest(MutableObservableListContractTest.suite(new Delegate()));
521
		return suite;
540
		return suite;
Lines 525-541 Link Here
525
		public IObservableCollection createObservableCollection(Realm realm,
544
		public IObservableCollection createObservableCollection(Realm realm,
526
				int elementCount) {
545
				int elementCount) {
527
			String propertyName = "array";
546
			String propertyName = "array";
528
			PropertyDescriptor propertyDescriptor;
529
			try {
530
				propertyDescriptor = new PropertyDescriptor(propertyName,
531
						Bean.class);
532
			} catch (IntrospectionException e) {
533
				throw new RuntimeException(e);
534
			}
535
			Object bean = new Bean(new Object[0]);
547
			Object bean = new Bean(new Object[0]);
536
548
537
			IObservableList list = new JavaBeanObservableList(realm, bean,
549
			IObservableList list = BeansObservables.observeList(realm, bean,
538
					propertyDescriptor, String.class);
550
					propertyName, String.class);
539
			for (int i = 0; i < elementCount; i++)
551
			for (int i = 0; i < elementCount; i++)
540
				list.add(createElement(list));
552
				list.add(createElement(list));
541
			return list;
553
			return list;
(-)src/org/eclipse/core/tests/internal/databinding/beans/BeanObservableListDecoratorTest.java (-14 / +8 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bugs 208858, 213145, 246625
10
 *     Matthew Hall - bugs 208858, 213145, 246625, 194734
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.core.tests.internal.databinding.beans;
13
package org.eclipse.core.tests.internal.databinding.beans;
Lines 18-30 Link Here
18
import junit.framework.TestCase;
18
import junit.framework.TestCase;
19
import junit.framework.TestSuite;
19
import junit.framework.TestSuite;
20
20
21
import org.eclipse.core.databinding.beans.BeansObservables;
21
import org.eclipse.core.databinding.observable.IObservable;
22
import org.eclipse.core.databinding.observable.IObservable;
22
import org.eclipse.core.databinding.observable.IObservableCollection;
23
import org.eclipse.core.databinding.observable.IObservableCollection;
23
import org.eclipse.core.databinding.observable.Realm;
24
import org.eclipse.core.databinding.observable.Realm;
24
import org.eclipse.core.databinding.observable.list.IObservableList;
25
import org.eclipse.core.databinding.observable.list.IObservableList;
25
import org.eclipse.core.databinding.observable.list.WritableList;
26
import org.eclipse.core.databinding.observable.list.WritableList;
26
import org.eclipse.core.internal.databinding.beans.BeanObservableListDecorator;
27
import org.eclipse.core.internal.databinding.beans.BeanObservableListDecorator;
27
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList;
28
import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest;
28
import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest;
29
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
29
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
30
import org.eclipse.jface.databinding.swt.SWTObservables;
30
import org.eclipse.jface.databinding.swt.SWTObservables;
Lines 36-71 Link Here
36
public class BeanObservableListDecoratorTest extends TestCase {
36
public class BeanObservableListDecoratorTest extends TestCase {
37
	private Bean bean;
37
	private Bean bean;
38
	private PropertyDescriptor propertyDescriptor;
38
	private PropertyDescriptor propertyDescriptor;
39
	private JavaBeanObservableList observableList;
39
	private IObservableList observableList;
40
	private BeanObservableListDecorator decorator;
40
	private BeanObservableListDecorator decorator;
41
41
42
	/*
43
	 * (non-Javadoc)
44
	 * 
45
	 * @see junit.framework.TestCase#setUp()
46
	 */
47
	protected void setUp() throws Exception {
42
	protected void setUp() throws Exception {
48
		super.setUp();
43
		super.setUp();
49
		
44
		
50
		bean = new Bean();
45
		bean = new Bean();
51
		propertyDescriptor = new PropertyDescriptor(
46
		propertyDescriptor = new PropertyDescriptor(
52
				"list", Bean.class,"getList","setList");
47
				"list", Bean.class,"getList","setList");
53
		observableList = new JavaBeanObservableList(
48
		observableList = BeansObservables.observeList(
54
				SWTObservables.getRealm(Display.getDefault()), bean,
49
				SWTObservables.getRealm(Display.getDefault()), bean, "list");
55
				propertyDescriptor, Bean.class);
56
		decorator = new BeanObservableListDecorator(observableList, propertyDescriptor);
50
		decorator = new BeanObservableListDecorator(observableList, propertyDescriptor);
57
	}
51
	}
58
52
59
	public void testGetDelegate() throws Exception {
53
	public void testGetDelegate() throws Exception {
60
		assertEquals(observableList, decorator.getDecorated());
54
		assertSame(observableList, decorator.getDecorated());
61
	}
55
	}
62
56
63
	public void testGetObserved() throws Exception {
57
	public void testGetObserved() throws Exception {
64
		assertEquals(bean, decorator.getObserved());
58
		assertSame(bean, decorator.getObserved());
65
	}
59
	}
66
60
67
	public void testGetPropertyDescriptor() throws Exception {
61
	public void testGetPropertyDescriptor() throws Exception {
68
		assertEquals(propertyDescriptor, decorator.getPropertyDescriptor());
62
		assertSame(propertyDescriptor, decorator.getPropertyDescriptor());
69
	}
63
	}
70
64
71
	public static Test suite() {
65
	public static Test suite() {
(-)src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableListTest.java (-97 / +112 lines)
Lines 7-18 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bugs 221351, 213145, 244098, 246103
10
 *     Matthew Hall - bugs 221351, 213145, 244098, 246103, 194734
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.core.tests.internal.databinding.beans;
13
package org.eclipse.core.tests.internal.databinding.beans;
14
14
15
import java.beans.IntrospectionException;
16
import java.beans.PropertyChangeEvent;
15
import java.beans.PropertyChangeEvent;
17
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyChangeListener;
18
import java.beans.PropertyDescriptor;
17
import java.beans.PropertyDescriptor;
Lines 25-38 Link Here
25
import junit.framework.Test;
24
import junit.framework.Test;
26
import junit.framework.TestSuite;
25
import junit.framework.TestSuite;
27
26
27
import org.eclipse.core.databinding.beans.BeanProperties;
28
import org.eclipse.core.databinding.beans.BeansObservables;
28
import org.eclipse.core.databinding.beans.BeansObservables;
29
import org.eclipse.core.databinding.beans.IBeanObservable;
30
import org.eclipse.core.databinding.beans.IBeanProperty;
31
import org.eclipse.core.databinding.beans.PojoObservables;
29
import org.eclipse.core.databinding.observable.IObservable;
32
import org.eclipse.core.databinding.observable.IObservable;
30
import org.eclipse.core.databinding.observable.IObservableCollection;
33
import org.eclipse.core.databinding.observable.IObservableCollection;
31
import org.eclipse.core.databinding.observable.Realm;
34
import org.eclipse.core.databinding.observable.Realm;
32
import org.eclipse.core.databinding.observable.list.IObservableList;
35
import org.eclipse.core.databinding.observable.list.IObservableList;
33
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
36
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
34
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
37
import org.eclipse.core.databinding.observable.list.ListDiff;
35
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList;
36
import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest;
38
import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest;
37
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
39
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
38
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
40
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
Lines 46-52 Link Here
46
 * @since 1.1
48
 * @since 1.1
47
 */
49
 */
48
public class JavaBeanObservableListTest extends AbstractDefaultRealmTestCase {
50
public class JavaBeanObservableListTest extends AbstractDefaultRealmTestCase {
49
	private JavaBeanObservableList list;
51
	private IObservableList list;
52
	private IBeanObservable beanObservable;
50
53
51
	private PropertyDescriptor propertyDescriptor;
54
	private PropertyDescriptor propertyDescriptor;
52
55
Lines 63-89 Link Here
63
		super.setUp();
66
		super.setUp();
64
67
65
		propertyName = "list";
68
		propertyName = "list";
66
		propertyDescriptor = new PropertyDescriptor(propertyName, Bean.class);
69
		propertyDescriptor = ((IBeanProperty) BeanProperties.list(
70
				Bean.class, propertyName)).getPropertyDescriptor();
67
		bean = new Bean(new ArrayList());
71
		bean = new Bean(new ArrayList());
68
72
69
		list = new JavaBeanObservableList(SWTObservables.getRealm(Display
73
		list = BeansObservables.observeList(SWTObservables.getRealm(Display
70
				.getDefault()), bean, propertyDescriptor, String.class);
74
				.getDefault()), bean, propertyName);
75
		beanObservable = (IBeanObservable) list;
71
	}
76
	}
72
77
73
	public void testGetObserved() throws Exception {
78
	public void testGetObserved() throws Exception {
74
		assertEquals(bean, list.getObserved());
79
		assertEquals(bean, beanObservable.getObserved());
75
	}
80
	}
76
81
77
	public void testGetPropertyDescriptor() throws Exception {
82
	public void testGetPropertyDescriptor() throws Exception {
78
		assertEquals(propertyDescriptor, list.getPropertyDescriptor());
83
		assertEquals(propertyDescriptor, beanObservable.getPropertyDescriptor());
79
	}
84
	}
80
85
81
	public void testRegistersListenerOnCreation() throws Exception {
86
	public void testRegistersListenerAfterFirstListenerIsAdded()
87
			throws Exception {
88
		assertFalse(bean.changeSupport.hasListeners(propertyName));
89
		list.addListChangeListener(new ListChangeEventTracker());
82
		assertTrue(bean.changeSupport.hasListeners(propertyName));
90
		assertTrue(bean.changeSupport.hasListeners(propertyName));
83
	}
91
	}
84
92
85
	public void testRemovesListenerOnDisposal() throws Exception {
93
	public void testRemovesListenerAfterLastListenerIsRemoved()
86
		list.dispose();
94
			throws Exception {
95
		ListChangeEventTracker listener = new ListChangeEventTracker();
96
		list.addListChangeListener(listener);
97
98
		assertTrue(bean.changeSupport.hasListeners(propertyName));
99
		list.removeListChangeListener(listener);
87
		assertFalse(bean.changeSupport.hasListeners(propertyName));
100
		assertFalse(bean.changeSupport.hasListeners(propertyName));
88
	}
101
	}
89
102
Lines 118-132 Link Here
118
		assertEquals(1, listener.count);
131
		assertEquals(1, listener.count);
119
		ListChangeEvent event = listener.event;
132
		ListChangeEvent event = listener.event;
120
133
121
		assertEquals(list, event.getObservableList());
134
		assertSame(list, event.getObservableList());
122
		assertEntry(event.diff.getDifferences()[0], true, 0, element);
135
		assertDiff(event.diff, Collections.EMPTY_LIST, Collections
136
				.singletonList("1"));
123
	}
137
	}
124
138
125
	public void testAddFiresPropertyChangeEvent() throws Exception {
139
	public void testAddFiresPropertyChangeEvent() throws Exception {
126
		assertPropertyChangeEvent(bean, new Runnable() {
140
		assertPropertyChangeEvent(bean, new Runnable() {
127
			public void run() {
141
			public void run() {
128
				list.add("0");
142
				list.add("0");
129
			}			
143
			}
130
		});
144
		});
131
	}
145
	}
132
146
Lines 148-161 Link Here
148
		list.add(0, element);
162
		list.add(0, element);
149
163
150
		ListChangeEvent event = listener.event;
164
		ListChangeEvent event = listener.event;
151
		assertEntry(event.diff.getDifferences()[0], true, 0, element);
165
		assertDiff(event.diff, Collections.EMPTY_LIST, Collections
166
				.singletonList("1"));
152
	}
167
	}
153
	
168
154
	public void testAddAtIndexPropertyChangeEvent() throws Exception {
169
	public void testAddAtIndexPropertyChangeEvent() throws Exception {
155
		assertPropertyChangeEvent(bean, new Runnable() {
170
		assertPropertyChangeEvent(bean, new Runnable() {
156
			public void run() {
171
			public void run() {
157
				list.add(0, "0");
172
				list.add(0, "0");
158
			}			
173
			}
159
		});
174
		});
160
	}
175
	}
161
176
Lines 164-170 Link Here
164
		list.add(element);
179
		list.add(element);
165
180
166
		assertEquals(1, bean.getList().size());
181
		assertEquals(1, bean.getList().size());
167
		assertPropertyChangeEvent(bean, new Runnable(){
182
		assertPropertyChangeEvent(bean, new Runnable() {
168
			public void run() {
183
			public void run() {
169
				list.clear();
184
				list.clear();
170
			}
185
			}
Lines 175-186 Link Here
175
	public void testRemove() throws Exception {
190
	public void testRemove() throws Exception {
176
		String element = "1";
191
		String element = "1";
177
		list.add(element);
192
		list.add(element);
178
		
193
179
		assertEquals(1, bean.getList().size());
194
		assertEquals(1, bean.getList().size());
180
		list.remove(element);
195
		list.remove(element);
181
		assertEquals(0, bean.getList().size());
196
		assertEquals(0, bean.getList().size());
182
	}
197
	}
183
	
198
184
	public void testRemoveListChangeEvent() throws Exception {
199
	public void testRemoveListChangeEvent() throws Exception {
185
		String element = "1";
200
		String element = "1";
186
		list.add(element);
201
		list.add(element);
Lines 193-209 Link Here
193
208
194
		assertEquals(1, listener.count);
209
		assertEquals(1, listener.count);
195
		ListChangeEvent event = listener.event;
210
		ListChangeEvent event = listener.event;
196
		assertEquals(list, event.getObservableList());
211
		assertSame(list, event.getObservableList());
197
		assertEntry(event.diff.getDifferences()[0], false, 0, element);
212
213
		assertDiff(event.diff, Collections.singletonList("1"),
214
				Collections.EMPTY_LIST);
198
	}
215
	}
199
	
216
200
	public void testRemovePropertyChangeEvent() throws Exception {
217
	public void testRemovePropertyChangeEvent() throws Exception {
201
		list.add("0");
218
		list.add("0");
202
		
219
203
		assertPropertyChangeEvent(bean, new Runnable() {
220
		assertPropertyChangeEvent(bean, new Runnable() {
204
			public void run() {
221
			public void run() {
205
				list.remove("0");
222
				list.remove("0");
206
			}			
223
			}
207
		});
224
		});
208
	}
225
	}
209
226
Lines 229-244 Link Here
229
246
230
		assertEquals(1, listener.count);
247
		assertEquals(1, listener.count);
231
		ListChangeEvent event = listener.event;
248
		ListChangeEvent event = listener.event;
232
		assertEquals(list, event.getObservableList());
249
		assertSame(list, event.getObservableList());
233
		assertEntry(event.diff.getDifferences()[0], false, 0, element);
250
251
		assertDiff(event.diff, Collections.singletonList(element),
252
				Collections.EMPTY_LIST);
234
	}
253
	}
235
	
254
236
	public void testRemoveAtIndexPropertyChangeEvent() throws Exception {
255
	public void testRemoveAtIndexPropertyChangeEvent() throws Exception {
237
		list.add("0");
256
		list.add("0");
238
		assertPropertyChangeEvent(bean, new Runnable() {
257
		assertPropertyChangeEvent(bean, new Runnable() {
239
			public void run() {
258
			public void run() {
240
				list.remove(0);
259
				list.remove(0);
241
			}			
260
			}
242
		});
261
		});
243
	}
262
	}
244
263
Lines 263-279 Link Here
263
282
264
		assertEquals(1, listener.count);
283
		assertEquals(1, listener.count);
265
		ListChangeEvent event = listener.event;
284
		ListChangeEvent event = listener.event;
266
		assertEquals(list, event.getObservableList());
285
		assertSame(list, event.getObservableList());
267
286
268
		assertEntry(event.diff.getDifferences()[0], true, 0, elements.get(0));
287
		assertDiff(event.diff, Collections.EMPTY_LIST, Arrays
269
		assertEntry(event.diff.getDifferences()[1], true, 1, elements.get(1));
288
				.asList(new String[] { "1", "2" }));
270
	}
289
	}
271
	
290
272
	public void testAddAllPropertyChangeEvent() throws Exception {
291
	public void testAddAllPropertyChangeEvent() throws Exception {
273
		assertPropertyChangeEvent(bean, new Runnable() {
292
		assertPropertyChangeEvent(bean, new Runnable() {
274
			public void run() {
293
			public void run() {
275
				list.addAll(Arrays.asList(new String[] {"0", "1"}));
294
				list.addAll(Arrays.asList(new String[] { "0", "1" }));
276
			}			
295
			}
277
		});
296
		});
278
	}
297
	}
279
298
Lines 303-332 Link Here
303
322
304
		assertEquals(1, listener.count);
323
		assertEquals(1, listener.count);
305
		ListChangeEvent event = listener.event;
324
		ListChangeEvent event = listener.event;
306
		assertEquals(list, event.getObservableList());
325
		assertSame(list, event.getObservableList());
307
		assertEntry(event.diff.getDifferences()[0], true, 2, elements.get(0));
326
308
		assertEntry(event.diff.getDifferences()[1], true, 3, elements.get(1));
327
		assertDiff(event.diff, Arrays.asList(new Object[] { "1", "2" }), Arrays
328
				.asList(new Object[] { "1", "2", "1", "2" }));
309
	}
329
	}
310
	
330
311
	public void testAddAllAtIndexPropertyChangeEvent() throws Exception {
331
	public void testAddAllAtIndexPropertyChangeEvent() throws Exception {
312
		assertPropertyChangeEvent(bean, new Runnable() {
332
		assertPropertyChangeEvent(bean, new Runnable() {
313
			public void run() {
333
			public void run() {
314
				list.addAll(0, Arrays.asList(new String[] {"1", "2"}));
334
				list.addAll(0, Arrays.asList(new String[] { "1", "2" }));
315
			}			
335
			}
316
		});
336
		});
317
	}
337
	}
318
338
319
	public void testRemoveAll() throws Exception {
339
	public void testRemoveAll() throws Exception {
320
		List elements = Arrays.asList(new String[] { "1", "2" });
340
		list.addAll(Arrays.asList(new String[] { "1", "2", "3", "4" }));
321
		list.addAll(elements);
322
		list.addAll(elements);
323
324
		assertEquals(4, bean.getList().size());
341
		assertEquals(4, bean.getList().size());
325
		list.removeAll(elements);
342
343
		list.removeAll(Arrays.asList(new String[] { "2", "4" }));
326
344
327
		assertEquals(2, bean.getList().size());
345
		assertEquals(2, bean.getList().size());
328
		assertEquals(elements.get(0), bean.getList().get(0));
346
		assertEquals("1", bean.getList().get(0));
329
		assertEquals(elements.get(1), bean.getList().get(1));
347
		assertEquals("3", bean.getList().get(1));
330
	}
348
	}
331
349
332
	public void testRemoveAllListChangeEvent() throws Exception {
350
	public void testRemoveAllListChangeEvent() throws Exception {
Lines 342-357 Link Here
342
360
343
		ListChangeEvent event = listener.event;
361
		ListChangeEvent event = listener.event;
344
		assertEquals(list, event.getObservableList());
362
		assertEquals(list, event.getObservableList());
345
		assertEntry(event.diff.getDifferences()[0], false, 0, elements.get(0));
363
		assertSame(list, event.getObservableList());
346
		assertEntry(event.diff.getDifferences()[1], false, 0, elements.get(1));
364
365
		assertDiff(event.diff, Arrays
366
				.asList(new Object[] { "1", "2", "1", "2" }),
367
				Collections.EMPTY_LIST);
347
	}
368
	}
348
	
369
349
	public void testRemoveAllPropertyChangeEvent() throws Exception {
370
	public void testRemoveAllPropertyChangeEvent() throws Exception {
350
		list.add("0");
371
		list.add("0");
351
		assertPropertyChangeEvent(bean, new Runnable() {
372
		assertPropertyChangeEvent(bean, new Runnable() {
352
			public void run() {
373
			public void run() {
353
				list.removeAll(Arrays.asList(new String[] {"0"}));
374
				list.removeAll(Arrays.asList(new String[] { "0" }));
354
			}			
375
			}
355
		});
376
		});
356
	}
377
	}
357
378
Lines 380-397 Link Here
380
401
381
		assertEquals(1, listener.count);
402
		assertEquals(1, listener.count);
382
		ListChangeEvent event = listener.event;
403
		ListChangeEvent event = listener.event;
383
		assertEquals(list, event.getObservableList());
404
		assertSame(list, event.getObservableList());
384
		assertEntry(event.diff.getDifferences()[0], false, 2, elements.get(2));
405
385
		assertEntry(event.diff.getDifferences()[1], false, 2, elements.get(3));
406
		assertDiff(event.diff, Arrays
407
				.asList(new Object[] { "0", "1", "2", "3" }), Arrays
408
				.asList(new Object[] { "0", "1" }));
386
	}
409
	}
387
	
410
388
	public void testRetainAllPropertyChangeEvent() throws Exception {
411
	public void testRetainAllPropertyChangeEvent() throws Exception {
389
		list.addAll(Arrays.asList(new String[] {"0", "1"}));
412
		list.addAll(Arrays.asList(new String[] { "0", "1" }));
390
		
413
391
		assertPropertyChangeEvent(bean, new Runnable() {
414
		assertPropertyChangeEvent(bean, new Runnable() {
392
			public void run() {
415
			public void run() {
393
				list.retainAll(Arrays.asList(new String[] {"0"}));
416
				list.retainAll(Arrays.asList(new String[] { "0" }));
394
			}			
417
			}
395
		});
418
		});
396
	}
419
	}
397
420
Lines 435-443 Link Here
435
458
436
		assertEquals(1, listener.count);
459
		assertEquals(1, listener.count);
437
		ListChangeEvent event = listener.event;
460
		ListChangeEvent event = listener.event;
438
		assertEquals(list, event.getObservableList());
461
		assertSame(list, event.getObservableList());
439
		assertEntry(event.diff.getDifferences()[0], false, 0, oldElement);
462
440
		assertEntry(event.diff.getDifferences()[1], true, 0, newElement);
463
		assertDiff(event.diff, Collections.singletonList(oldElement),
464
				Collections.singletonList(newElement));
441
	}
465
	}
442
466
443
	public void testSetPropertyChangeEvent() throws Exception {
467
	public void testSetPropertyChangeEvent() throws Exception {
Lines 445-451 Link Here
445
		assertPropertyChangeEvent(bean, new Runnable() {
469
		assertPropertyChangeEvent(bean, new Runnable() {
446
			public void run() {
470
			public void run() {
447
				list.set(0, "1");
471
				list.set(0, "1");
448
			}			
472
			}
449
		});
473
		});
450
	}
474
	}
451
475
Lines 462-478 Link Here
462
486
463
	public void testConstructor_RegistersListener() throws Exception {
487
	public void testConstructor_RegistersListener() throws Exception {
464
		Bean bean = new Bean();
488
		Bean bean = new Bean();
465
		new JavaBeanObservableList(Realm.getDefault(), bean,
489
		IObservableList observable = BeansObservables.observeList(Realm
466
				new PropertyDescriptor("list", Bean.class), Bean.class);
490
				.getDefault(), bean, "list");
467
491
492
		assertFalse(bean.hasListeners("list"));
493
		ChangeEventTracker.observe(observable);
468
		assertTrue(bean.hasListeners("list"));
494
		assertTrue(bean.hasListeners("list"));
469
	}
495
	}
470
496
471
	public void testConstructor_SkipsRegisterListener() throws Exception {
497
	public void testConstructor_SkipsRegisterListener() throws Exception {
472
		Bean bean = new Bean();
498
		Bean bean = new Bean();
473
		JavaBeanObservableList observable = new JavaBeanObservableList(Realm
499
		IObservableList observable = PojoObservables.observeList(Realm
474
				.getDefault(), bean,
500
				.getDefault(), bean, "list");
475
				new PropertyDescriptor("list", Bean.class), Bean.class, false);
476
501
477
		assertFalse(bean.hasListeners("list"));
502
		assertFalse(bean.hasListeners("list"));
478
		ChangeEventTracker.observe(observable);
503
		ChangeEventTracker.observe(observable);
Lines 496-524 Link Here
496
		bean.setList(Collections.singletonList("new"));
521
		bean.setList(Collections.singletonList("new"));
497
522
498
		assertEquals(1, tracker.count);
523
		assertEquals(1, tracker.count);
499
		
524
500
		List list = new ArrayList();
525
		List list = new ArrayList();
501
		list.add("old");
526
		list.add("old");
502
		tracker.event.diff.applyTo(list);
527
		tracker.event.diff.applyTo(list);
503
		assertEquals(Collections.singletonList("new"), list);
528
		assertEquals(Collections.singletonList("new"), list);
504
	}
529
	}
505
530
506
	private static void assertEntry(ListDiffEntry entry, boolean addition,
531
	private static void assertDiff(ListDiff diff, List oldList, List newList) {
507
			int position, Object element) {
532
		oldList = new ArrayList(oldList); // defensive copy in case arg is
508
		assertEquals("addition", addition, entry.isAddition());
533
		// unmodifiable
509
		assertEquals("position", position, entry.getPosition());
534
		diff.applyTo(oldList);
510
		assertEquals("element", element, entry.getElement());
535
		assertEquals("applying diff to list did not produce expected result",
536
				newList, oldList);
511
	}
537
	}
512
538
513
	private static void assertPropertyChangeEvent(Bean bean, Runnable runnable) {
539
	private static void assertPropertyChangeEvent(Bean bean, Runnable runnable) {
514
		PropertyChangeTracker listener = new PropertyChangeTracker();
540
		PropertyChangeTracker listener = new PropertyChangeTracker();
515
		bean.addPropertyChangeListener(listener);
541
		bean.addPropertyChangeListener(listener);
516
		
542
517
		List old = bean.getList();
543
		List old = bean.getList();
518
		assertEquals(0, listener.count);
544
		assertEquals(0, listener.count);
519
		
545
520
		runnable.run();
546
		runnable.run();
521
		
547
522
		PropertyChangeEvent event = listener.evt;
548
		PropertyChangeEvent event = listener.evt;
523
		assertEquals("event did not fire", 1, listener.count);
549
		assertEquals("event did not fire", 1, listener.count);
524
		assertEquals("list", event.getPropertyName());
550
		assertEquals("list", event.getPropertyName());
Lines 526-543 Link Here
526
		assertEquals("new value", bean.getList(), event.getNewValue());
552
		assertEquals("new value", bean.getList(), event.getNewValue());
527
		assertFalse("lists are equal", bean.getList().equals(old));
553
		assertFalse("lists are equal", bean.getList().equals(old));
528
	}
554
	}
529
	
555
530
	private static class PropertyChangeTracker implements
556
	private static class PropertyChangeTracker implements
531
			PropertyChangeListener {
557
			PropertyChangeListener {
532
		int count;
558
		int count;
533
559
534
		PropertyChangeEvent evt;
560
		PropertyChangeEvent evt;
535
561
536
		/*
537
		 * (non-Javadoc)
538
		 * 
539
		 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
540
		 */
541
		public void propertyChange(PropertyChangeEvent evt) {
562
		public void propertyChange(PropertyChangeEvent evt) {
542
			count++;
563
			count++;
543
			this.evt = evt;
564
			this.evt = evt;
Lines 545-551 Link Here
545
	}
566
	}
546
567
547
	public static Test suite() {
568
	public static Test suite() {
548
		TestSuite suite = new TestSuite(JavaBeanObservableListTest.class.getName());
569
		TestSuite suite = new TestSuite(JavaBeanObservableListTest.class
570
				.getName());
549
		suite.addTestSuite(JavaBeanObservableListTest.class);
571
		suite.addTestSuite(JavaBeanObservableListTest.class);
550
		suite.addTest(MutableObservableListContractTest.suite(new Delegate()));
572
		suite.addTest(MutableObservableListContractTest.suite(new Delegate()));
551
		return suite;
573
		return suite;
Lines 555-571 Link Here
555
		public IObservableCollection createObservableCollection(Realm realm,
577
		public IObservableCollection createObservableCollection(Realm realm,
556
				int elementCount) {
578
				int elementCount) {
557
			String propertyName = "list";
579
			String propertyName = "list";
558
			PropertyDescriptor propertyDescriptor;
559
			try {
560
				propertyDescriptor = new PropertyDescriptor(propertyName,
561
						Bean.class);
562
			} catch (IntrospectionException e) {
563
				throw new RuntimeException(e);
564
			}
565
			Object bean = new Bean(new ArrayList());
580
			Object bean = new Bean(new ArrayList());
566
581
567
			IObservableList list = new JavaBeanObservableList(realm, bean,
582
			IObservableList list = BeansObservables.observeList(realm, bean,
568
					propertyDescriptor, String.class);
583
					propertyName, String.class);
569
			for (int i = 0; i < elementCount; i++)
584
			for (int i = 0; i < elementCount; i++)
570
				list.add(createElement(list));
585
				list.add(createElement(list));
571
			return list;
586
			return list;
(-)src/org/eclipse/core/tests/internal/databinding/beans/BeanObservableValueDecoratorTest.java (-18 / +11 lines)
Lines 7-21 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bug 246625
10
 *     Matthew Hall - bug 246625, 194734
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.core.tests.internal.databinding.beans;
13
package org.eclipse.core.tests.internal.databinding.beans;
14
14
15
import java.beans.PropertyDescriptor;
15
import java.beans.PropertyDescriptor;
16
16
17
import org.eclipse.core.databinding.beans.BeansObservables;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
17
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator;
19
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator;
18
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableValue;
19
import org.eclipse.jface.databinding.swt.SWTObservables;
20
import org.eclipse.jface.databinding.swt.SWTObservables;
20
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
21
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
21
import org.eclipse.swt.widgets.Display;
22
import org.eclipse.swt.widgets.Display;
Lines 25-62 Link Here
25
 */
26
 */
26
public class BeanObservableValueDecoratorTest extends AbstractDefaultRealmTestCase {
27
public class BeanObservableValueDecoratorTest extends AbstractDefaultRealmTestCase {
27
	private Bean bean;
28
	private Bean bean;
28
	private JavaBeanObservableValue observableValue;
29
	private IObservableValue observableValue;
29
	private BeanObservableValueDecorator decorator;
30
	private BeanObservableValueDecorator decorator;
30
	private PropertyDescriptor propertyDescriptor;
31
	private PropertyDescriptor propertyDescriptor;
31
	
32
	
32
	/*
33
	 * (non-Javadoc)
34
	 * 
35
	 * @see junit.framework.TestCase#setUp()
36
	 */
37
	protected void setUp() throws Exception {
33
	protected void setUp() throws Exception {
38
		super.setUp();
34
		super.setUp();
39
		
35
		
40
		bean = new Bean();
36
		bean = new Bean();
41
		propertyDescriptor = new PropertyDescriptor("value",
37
		propertyDescriptor = new PropertyDescriptor("value", Bean.class);
42
				Bean.class);
38
		observableValue = BeansObservables.observeValue(SWTObservables
43
		observableValue = new JavaBeanObservableValue(
39
				.getRealm(Display.getDefault()), bean, "value");
44
				SWTObservables.getRealm(Display.getDefault()), bean,
40
		decorator = new BeanObservableValueDecorator(observableValue,
45
				propertyDescriptor);
41
				propertyDescriptor);
46
		decorator = new BeanObservableValueDecorator(
47
				observableValue, observableValue
48
						.getPropertyDescriptor());
49
	}
42
	}
50
43
51
	public void testGetDelegate() throws Exception {
44
	public void testGetDelegate() throws Exception {
52
		assertEquals(observableValue, decorator.getDecorated());
45
		assertSame(observableValue, decorator.getDecorated());
53
	}
46
	}
54
	
47
	
55
	public void testGetObserved() throws Exception {
48
	public void testGetObserved() throws Exception {
56
		assertEquals(bean, decorator.getObserved());
49
		assertSame(bean, decorator.getObserved());
57
	}
50
	}
58
51
59
	public void testGetPropertyDescriptor() throws Exception {
52
	public void testGetPropertyDescriptor() throws Exception {
60
		assertEquals(propertyDescriptor, decorator.getPropertyDescriptor());
53
		assertSame(propertyDescriptor, decorator.getPropertyDescriptor());
61
	}
54
	}
62
}
55
}
(-)src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableMapTest.java (-9 / +20 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bugs 213145, 241585, 246103
10
 *     Matthew Hall - bugs 213145, 241585, 246103, 194734
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.core.tests.internal.databinding.beans;
13
package org.eclipse.core.tests.internal.databinding.beans;
Lines 20-33 Link Here
20
import junit.framework.TestCase;
20
import junit.framework.TestCase;
21
import junit.framework.TestSuite;
21
import junit.framework.TestSuite;
22
22
23
import org.eclipse.core.databinding.beans.BeanProperties;
23
import org.eclipse.core.databinding.beans.BeansObservables;
24
import org.eclipse.core.databinding.beans.BeansObservables;
25
import org.eclipse.core.databinding.beans.IBeanObservable;
26
import org.eclipse.core.databinding.beans.IBeanProperty;
27
import org.eclipse.core.databinding.beans.PojoObservables;
24
import org.eclipse.core.databinding.observable.Realm;
28
import org.eclipse.core.databinding.observable.Realm;
25
import org.eclipse.core.databinding.observable.map.IMapChangeListener;
29
import org.eclipse.core.databinding.observable.map.IMapChangeListener;
26
import org.eclipse.core.databinding.observable.map.IObservableMap;
30
import org.eclipse.core.databinding.observable.map.IObservableMap;
27
import org.eclipse.core.databinding.observable.map.MapChangeEvent;
31
import org.eclipse.core.databinding.observable.map.MapChangeEvent;
28
import org.eclipse.core.databinding.observable.map.MapDiff;
32
import org.eclipse.core.databinding.observable.map.MapDiff;
29
import org.eclipse.core.databinding.observable.set.WritableSet;
33
import org.eclipse.core.databinding.observable.set.WritableSet;
30
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableMap;
31
import org.eclipse.core.tests.databinding.observable.ThreadRealm;
34
import org.eclipse.core.tests.databinding.observable.ThreadRealm;
32
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
35
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
33
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
36
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
Lines 46-52 Link Here
46
49
47
	private PropertyDescriptor propertyDescriptor;
50
	private PropertyDescriptor propertyDescriptor;
48
51
49
	private JavaBeanObservableMap map;
52
	private IObservableMap map;
53
	private IBeanObservable beanObservable;
50
54
51
	protected void setUp() throws Exception {
55
	protected void setUp() throws Exception {
52
		ThreadRealm realm = new ThreadRealm();
56
		ThreadRealm realm = new ThreadRealm();
Lines 58-65 Link Here
58
		set.add(model1);
62
		set.add(model1);
59
		set.add(model2);
63
		set.add(model2);
60
64
61
		propertyDescriptor = new PropertyDescriptor("value", Bean.class);
65
		String propertyName = "value";
62
		map = new JavaBeanObservableMap(set, propertyDescriptor);
66
		propertyDescriptor = ((IBeanProperty) BeanProperties.value(
67
				Bean.class, propertyName)).getPropertyDescriptor();
68
		map = BeansObservables.observeMap(set, Bean.class, propertyName);
69
		beanObservable = (IBeanObservable) map;
63
	}
70
	}
64
71
65
	public void testGetValue() throws Exception {
72
	public void testGetValue() throws Exception {
Lines 139-149 Link Here
139
	}
146
	}
140
	
147
	
141
	public void testGetObserved() throws Exception {
148
	public void testGetObserved() throws Exception {
142
		assertEquals(set, map.getObserved());
149
		assertEquals(set, beanObservable.getObserved());
143
	}
150
	}
144
	
151
	
145
	public void testGetPropertyDescriptor() throws Exception {
152
	public void testGetPropertyDescriptor() throws Exception {
146
		assertEquals(propertyDescriptor, map.getPropertyDescriptor());
153
		assertEquals(propertyDescriptor, beanObservable.getPropertyDescriptor());
147
	}
154
	}
148
	
155
	
149
	public void testConstructor_SkipRegisterListeners() throws Exception {
156
	public void testConstructor_SkipRegisterListeners() throws Exception {
Lines 152-158 Link Here
152
		Bean bean = new Bean();
159
		Bean bean = new Bean();
153
		set.add(bean);
160
		set.add(bean);
154
		
161
		
155
		JavaBeanObservableMap observable = new JavaBeanObservableMap(set, new PropertyDescriptor("value", Bean.class), false);
162
		IObservableMap observable = PojoObservables.observeMap(set, Bean.class,
163
				"value");
164
		assertFalse(bean.hasListeners("value"));
156
		ChangeEventTracker.observe(observable);
165
		ChangeEventTracker.observe(observable);
157
166
158
		assertFalse(bean.hasListeners("value"));
167
		assertFalse(bean.hasListeners("value"));
Lines 164-170 Link Here
164
		Bean bean = new Bean();
173
		Bean bean = new Bean();
165
		set.add(bean);
174
		set.add(bean);
166
		
175
		
167
		JavaBeanObservableMap observable = new JavaBeanObservableMap(set, new PropertyDescriptor("value", Bean.class));
176
		IObservableMap observable = BeansObservables.observeMap(set,
177
				Bean.class, "value");
178
		assertFalse(bean.hasListeners("value"));
168
		ChangeEventTracker.observe(observable);
179
		ChangeEventTracker.observe(observable);
169
180
170
		assertTrue(bean.hasListeners("value"));
181
		assertTrue(bean.hasListeners("value"));
(-)src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableValueTest.java (-26 / +22 lines)
Lines 9-33 Link Here
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Brad Reynolds - bug 171616
10
 *     Brad Reynolds - bug 171616
11
 *     Katarzyna Marszalek - test case for bug 198519
11
 *     Katarzyna Marszalek - test case for bug 198519
12
 *     Matthew Hall - bug 213145, 246103
12
 *     Matthew Hall - bug 213145, 246103, 194734
13
 ******************************************************************************/
13
 ******************************************************************************/
14
14
15
package org.eclipse.core.tests.internal.databinding.beans;
15
package org.eclipse.core.tests.internal.databinding.beans;
16
16
17
import java.beans.IntrospectionException;
18
import java.beans.PropertyDescriptor;
17
import java.beans.PropertyDescriptor;
19
18
20
import junit.framework.Test;
19
import junit.framework.Test;
21
import junit.framework.TestSuite;
20
import junit.framework.TestSuite;
22
21
22
import org.eclipse.core.databinding.beans.BeanProperties;
23
import org.eclipse.core.databinding.beans.BeansObservables;
23
import org.eclipse.core.databinding.beans.BeansObservables;
24
import org.eclipse.core.databinding.beans.IBeanObservable;
25
import org.eclipse.core.databinding.beans.IBeanProperty;
26
import org.eclipse.core.databinding.beans.PojoObservables;
24
import org.eclipse.core.databinding.observable.ChangeEvent;
27
import org.eclipse.core.databinding.observable.ChangeEvent;
25
import org.eclipse.core.databinding.observable.IChangeListener;
28
import org.eclipse.core.databinding.observable.IChangeListener;
26
import org.eclipse.core.databinding.observable.IObservable;
29
import org.eclipse.core.databinding.observable.IObservable;
27
import org.eclipse.core.databinding.observable.Realm;
30
import org.eclipse.core.databinding.observable.Realm;
28
import org.eclipse.core.databinding.observable.value.ComputedValue;
31
import org.eclipse.core.databinding.observable.value.ComputedValue;
29
import org.eclipse.core.databinding.observable.value.IObservableValue;
32
import org.eclipse.core.databinding.observable.value.IObservableValue;
30
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableValue;
31
import org.eclipse.jface.databinding.conformance.MutableObservableValueContractTest;
33
import org.eclipse.jface.databinding.conformance.MutableObservableValueContractTest;
32
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
34
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
33
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
35
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
Lines 40-74 Link Here
40
 */
42
 */
41
public class JavaBeanObservableValueTest extends AbstractDefaultRealmTestCase {
43
public class JavaBeanObservableValueTest extends AbstractDefaultRealmTestCase {
42
	private Bean bean;
44
	private Bean bean;
43
	private JavaBeanObservableValue observableValue;
45
	private IObservableValue observableValue;
46
	private IBeanObservable beanObservable;
44
	private PropertyDescriptor propertyDescriptor;
47
	private PropertyDescriptor propertyDescriptor;
45
	private String propertyName;
48
	private String propertyName;
46
49
47
	/* (non-Javadoc)
48
	 * @see junit.framework.TestCase#setUp()
49
	 */
50
	protected void setUp() throws Exception {
50
	protected void setUp() throws Exception {
51
		super.setUp();
51
		super.setUp();
52
		
52
		
53
		bean = new Bean();
53
		bean = new Bean();
54
		propertyName = "value";
54
		propertyName = "value";
55
		propertyDescriptor = new PropertyDescriptor(propertyName, Bean.class);
55
		propertyDescriptor = ((IBeanProperty) BeanProperties.value(
56
		observableValue = new JavaBeanObservableValue(Realm.getDefault(), bean, propertyDescriptor);
56
				Bean.class, propertyName)).getPropertyDescriptor();
57
		observableValue = BeansObservables.observeValue(bean, propertyName);
58
		beanObservable = (IBeanObservable) observableValue;
57
	}
59
	}
58
60
59
	public void testGetObserved() throws Exception {
61
	public void testGetObserved() throws Exception {
60
		assertEquals(bean, observableValue.getObserved());
62
		assertEquals(bean, beanObservable.getObserved());
61
	}
63
	}
62
64
63
	public void testGetPropertyDescriptor() throws Exception {
65
	public void testGetPropertyDescriptor() throws Exception {
64
    	assertEquals(propertyDescriptor, observableValue.getPropertyDescriptor());
66
    	assertEquals(propertyDescriptor, beanObservable.getPropertyDescriptor());
65
	}
67
	}
66
68
67
	public void testSetValueThrowsExceptionThrownByBean() throws Exception {
69
	public void testSetValueThrowsExceptionThrownByBean() throws Exception {
68
		ThrowsSetException temp = new ThrowsSetException();
70
		ThrowsSetException temp = new ThrowsSetException();
69
		JavaBeanObservableValue observable = new JavaBeanObservableValue(Realm
71
		IObservableValue observable = BeansObservables.observeValue(temp,
70
				.getDefault(), temp,
72
				"value");
71
				new PropertyDescriptor("value", ThrowsSetException.class));
72
73
73
		try {
74
		try {
74
			observable.setValue("");
75
			observable.setValue("");
Lines 80-88 Link Here
80
	
81
	
81
	public void testGetValueThrowsExceptionThrownByBean() throws Exception {
82
	public void testGetValueThrowsExceptionThrownByBean() throws Exception {
82
		ThrowsGetException temp = new ThrowsGetException();
83
		ThrowsGetException temp = new ThrowsGetException();
83
		JavaBeanObservableValue observable = new JavaBeanObservableValue(Realm
84
		IObservableValue observable = BeansObservables.observeValue(temp,
84
				.getDefault(), temp,
85
				"value");
85
				new PropertyDescriptor("value", ThrowsGetException.class));
86
86
87
		try {
87
		try {
88
			observable.getValue();
88
			observable.getValue();
Lines 109-122 Link Here
109
	}
109
	}
110
110
111
	public void testConstructor_RegistersListeners() throws Exception {
111
	public void testConstructor_RegistersListeners() throws Exception {
112
		JavaBeanObservableValue observable = new JavaBeanObservableValue(Realm.getDefault(), bean, propertyDescriptor);
112
		IObservableValue observable = BeansObservables.observeValue(bean,
113
				propertyName);
113
		ChangeEventTracker.observe(observable);
114
		ChangeEventTracker.observe(observable);
114
		
115
		
115
		assertTrue(bean.hasListeners(propertyName));
116
		assertTrue(bean.hasListeners(propertyName));
116
	}
117
	}
117
	
118
	
118
	public void testConstructor_SkipRegisterListeners() throws Exception {
119
	public void testConstructor_SkipRegisterListeners() throws Exception {
119
		JavaBeanObservableValue observable = new JavaBeanObservableValue(Realm.getDefault(), bean, propertyDescriptor, false);
120
		IObservableValue observable = PojoObservables.observeValue(bean,
121
				propertyName);
120
		ChangeEventTracker.observe(observable);
122
		ChangeEventTracker.observe(observable);
121
		
123
		
122
		assertFalse(bean.hasListeners(propertyName));
124
		assertFalse(bean.hasListeners(propertyName));
Lines 156-168 Link Here
156
		}
158
		}
157
		
159
		
158
		public IObservableValue createObservableValue(Realm realm) {
160
		public IObservableValue createObservableValue(Realm realm) {
159
			try {
161
			return BeansObservables.observeValue(realm, bean, "value");
160
				PropertyDescriptor propertyDescriptor = new PropertyDescriptor("value", Bean.class);
161
				return new JavaBeanObservableValue(realm, bean,
162
						propertyDescriptor);					
163
			} catch (IntrospectionException e) {
164
				throw new RuntimeException(e);
165
			}
166
		}
162
		}
167
		
163
		
168
		public void change(IObservable observable) {
164
		public void change(IObservable observable) {
(-)src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableSetTest.java (-31 / +31 lines)
Lines 7-18 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bugs 221351, 213145, 244098, 246103
10
 *     Matthew Hall - bugs 221351, 213145, 244098, 246103, 194734
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.core.tests.internal.databinding.beans;
13
package org.eclipse.core.tests.internal.databinding.beans;
14
14
15
import java.beans.IntrospectionException;
16
import java.beans.PropertyDescriptor;
15
import java.beans.PropertyDescriptor;
17
import java.util.Arrays;
16
import java.util.Arrays;
18
import java.util.Collections;
17
import java.util.Collections;
Lines 22-35 Link Here
22
import junit.framework.TestCase;
21
import junit.framework.TestCase;
23
import junit.framework.TestSuite;
22
import junit.framework.TestSuite;
24
23
24
import org.eclipse.core.databinding.beans.BeanProperties;
25
import org.eclipse.core.databinding.beans.BeansObservables;
25
import org.eclipse.core.databinding.beans.BeansObservables;
26
import org.eclipse.core.databinding.beans.IBeanObservable;
27
import org.eclipse.core.databinding.beans.IBeanProperty;
28
import org.eclipse.core.databinding.beans.PojoObservables;
26
import org.eclipse.core.databinding.observable.IObservable;
29
import org.eclipse.core.databinding.observable.IObservable;
27
import org.eclipse.core.databinding.observable.IObservableCollection;
30
import org.eclipse.core.databinding.observable.IObservableCollection;
28
import org.eclipse.core.databinding.observable.Realm;
31
import org.eclipse.core.databinding.observable.Realm;
29
import org.eclipse.core.databinding.observable.set.IObservableSet;
32
import org.eclipse.core.databinding.observable.set.IObservableSet;
30
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
33
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
31
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
34
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
32
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet;
33
import org.eclipse.jface.databinding.conformance.MutableObservableSetContractTest;
35
import org.eclipse.jface.databinding.conformance.MutableObservableSetContractTest;
34
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
36
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
35
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
37
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
Lines 42-87 Link Here
42
 * @since 3.3
44
 * @since 3.3
43
 */
45
 */
44
public class JavaBeanObservableSetTest extends TestCase {
46
public class JavaBeanObservableSetTest extends TestCase {
45
	private JavaBeanObservableSet observableSet;
47
	private IObservableSet observableSet;
48
	private IBeanObservable beanObservable;
46
	private Bean bean;
49
	private Bean bean;
47
	private PropertyDescriptor propertyDescriptor;
50
	private PropertyDescriptor propertyDescriptor;
48
	private String propertyName;
51
	private String propertyName;
49
	private SetChangeListener listener;
52
	private SetChangeListener listener;
50
53
51
	/*
52
	 * (non-Javadoc)
53
	 * 
54
	 * @see junit.framework.TestCase#setUp()
55
	 */
56
	protected void setUp() throws Exception {
54
	protected void setUp() throws Exception {
57
		bean = new Bean();
55
		bean = new Bean();
58
		propertyName = "set";
56
		propertyName = "set";
59
		propertyDescriptor = new PropertyDescriptor(propertyName, Bean.class);
57
		propertyDescriptor = ((IBeanProperty) BeanProperties.set(
58
				Bean.class, propertyName)).getPropertyDescriptor();
60
59
61
		observableSet = new JavaBeanObservableSet(SWTObservables
60
		observableSet = BeansObservables
62
				.getRealm(Display.getDefault()), bean, propertyDescriptor,
61
				.observeSet(SWTObservables.getRealm(Display.getDefault()),
63
				Bean.class);
62
						bean, propertyName, Bean.class);
63
		beanObservable = (IBeanObservable) observableSet;
64
		listener = new SetChangeListener();
64
		listener = new SetChangeListener();
65
	}
65
	}
66
66
67
	public void testGetObserved() throws Exception {
67
	public void testGetObserved() throws Exception {
68
		assertEquals(bean, observableSet.getObserved());
68
		assertEquals(bean, beanObservable.getObserved());
69
	}
69
	}
70
70
71
	public void testGetPropertyDescriptor() throws Exception {
71
	public void testGetPropertyDescriptor() throws Exception {
72
		assertEquals(propertyDescriptor, observableSet.getPropertyDescriptor());
72
		assertEquals(propertyDescriptor, beanObservable.getPropertyDescriptor());
73
	}
73
	}
74
	
74
	
75
	public void testGetElementType() throws Exception {
75
	public void testGetElementType() throws Exception {
76
		assertEquals(Bean.class, observableSet.getElementType());
76
		assertEquals(Bean.class, observableSet.getElementType());
77
	}
77
	}
78
	
78
	
79
	public void testRegistersListenerOnCreation() throws Exception {
79
	public void testRegistersListenerAfterFirstListenerIsAdded() throws Exception {
80
		assertFalse(bean.changeSupport.hasListeners(propertyName));
81
		observableSet.addSetChangeListener(new SetChangeListener());
80
		assertTrue(bean.changeSupport.hasListeners(propertyName));
82
		assertTrue(bean.changeSupport.hasListeners(propertyName));
81
	}
83
	}
82
		
84
		
83
	public void testRemovesListenerOnDisposal() throws Exception {
85
    public void testRemovesListenerAfterLastListenerIsRemoved() throws Exception {
84
		observableSet.dispose();
86
		observableSet.addSetChangeListener(listener);
87
		
88
		assertTrue(bean.changeSupport.hasListeners(propertyName));
89
		observableSet.removeSetChangeListener(listener);
85
		assertFalse(bean.changeSupport.hasListeners(propertyName));
90
		assertFalse(bean.changeSupport.hasListeners(propertyName));
86
	}
91
	}
87
	
92
	
Lines 94-109 Link Here
94
99
95
	public void testConstructor_RegisterListeners() throws Exception {
100
	public void testConstructor_RegisterListeners() throws Exception {
96
		bean = new Bean();
101
		bean = new Bean();
97
		new JavaBeanObservableSet(new CurrentRealm(true), bean,
102
		observableSet = BeansObservables.observeSet(new CurrentRealm(true), bean,
98
				propertyDescriptor, Bean.class);
103
				propertyName);
104
		assertFalse(bean.hasListeners(propertyName));
105
		ChangeEventTracker.observe(observableSet);
99
		assertTrue(bean.hasListeners(propertyName));
106
		assertTrue(bean.hasListeners(propertyName));
100
	}
107
	}
101
108
102
	public void testConstructor_SkipsRegisterListeners() throws Exception {
109
	public void testConstructor_SkipsRegisterListeners() throws Exception {
103
		bean = new Bean();
110
		bean = new Bean();
104
111
105
		observableSet = new JavaBeanObservableSet(new CurrentRealm(true), bean,
112
		observableSet = PojoObservables.observeSet(new CurrentRealm(true),
106
				propertyDescriptor, Bean.class, false);
113
				bean, propertyName);
107
		assertFalse(bean.hasListeners(propertyName));
114
		assertFalse(bean.hasListeners(propertyName));
108
		ChangeEventTracker.observe(observableSet);
115
		ChangeEventTracker.observe(observableSet);
109
		assertFalse(bean.hasListeners(propertyName));
116
		assertFalse(bean.hasListeners(propertyName));
Lines 151-166 Link Here
151
				int elementCount) {
158
				int elementCount) {
152
			Bean bean = new Bean();
159
			Bean bean = new Bean();
153
			String propertyName = "set";
160
			String propertyName = "set";
154
			PropertyDescriptor propertyDescriptor;
155
			try {
156
				propertyDescriptor = new PropertyDescriptor(propertyName,
157
						Bean.class);
158
			} catch (IntrospectionException e) {
159
				throw new RuntimeException(e);
160
			}
161
161
162
			IObservableSet set = new JavaBeanObservableSet(realm,
162
			IObservableSet set = BeansObservables.observeSet(realm, bean,
163
					bean, propertyDescriptor, String.class);
163
					propertyName, String.class);
164
			for (int i = 0; i < elementCount; i++)
164
			for (int i = 0; i < elementCount; i++)
165
				set.add(createElement(set));
165
				set.add(createElement(set));
166
			return set;
166
			return set;
(-)src/org/eclipse/core/tests/internal/databinding/beans/BeanObservableSetDecoratorTest.java (-19 / +13 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Brad Reynolds - initial API and implementation
9
 *     Brad Reynolds - initial API and implementation
10
 *     Matthew Hall - bug 246625
10
 *     Matthew Hall - bug 246625, 194734
11
 ******************************************************************************/
11
 ******************************************************************************/
12
12
13
package org.eclipse.core.tests.internal.databinding.beans;
13
package org.eclipse.core.tests.internal.databinding.beans;
Lines 16-23 Link Here
16
16
17
import junit.framework.TestCase;
17
import junit.framework.TestCase;
18
18
19
import org.eclipse.core.databinding.beans.BeansObservables;
20
import org.eclipse.core.databinding.observable.set.IObservableSet;
19
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator;
21
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator;
20
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet;
21
import org.eclipse.jface.databinding.swt.SWTObservables;
22
import org.eclipse.jface.databinding.swt.SWTObservables;
22
import org.eclipse.swt.widgets.Display;
23
import org.eclipse.swt.widgets.Display;
23
24
Lines 26-62 Link Here
26
 */
27
 */
27
public class BeanObservableSetDecoratorTest extends TestCase {
28
public class BeanObservableSetDecoratorTest extends TestCase {
28
	private PropertyDescriptor propertyDescriptor;
29
	private PropertyDescriptor propertyDescriptor;
29
	private JavaBeanObservableSet observableSet;
30
	private IObservableSet observableSet;
30
	private BeanObservableSetDecorator decorator;
31
	private BeanObservableSetDecorator decorator;
31
	private Bean bean;
32
	private Bean bean;
32
33
33
	/*
34
	 * (non-Javadoc)
35
	 * 
36
	 * @see junit.framework.TestCase#setUp()
37
	 */
38
	protected void setUp() throws Exception {
34
	protected void setUp() throws Exception {
39
		super.setUp();
35
		super.setUp();
40
36
41
		bean = new Bean();
37
		bean = new Bean();
42
		propertyDescriptor = new PropertyDescriptor("set",
38
		propertyDescriptor = new PropertyDescriptor("set", Bean.class);
43
				Bean.class);
39
		observableSet = BeansObservables.observeSet(SWTObservables
44
		observableSet = new JavaBeanObservableSet(
40
				.getRealm(Display.getDefault()), bean, "set");
45
				SWTObservables.getRealm(Display.getDefault()), bean,
41
		decorator = new BeanObservableSetDecorator(observableSet,
46
				propertyDescriptor, String.class);
42
				propertyDescriptor);
47
		decorator = new BeanObservableSetDecorator(
48
				observableSet, propertyDescriptor);
49
	}
43
	}
50
44
51
	public void testGetDelegate() throws Exception {
45
	public void testGetDecorated() throws Exception {
52
		assertEquals(observableSet, decorator.getDecorated());
46
		assertSame(observableSet, decorator.getDecorated());
53
	}
47
	}
54
48
55
	public void testGetObserved() throws Exception {
49
	public void testGetObserved() throws Exception {
56
		assertEquals(bean, decorator.getObserved());
50
		assertSame(bean, decorator.getObserved());
57
	}
51
	}
58
52
59
	public void testGetPropertyDescriptor() throws Exception {
53
	public void testGetPropertyDescriptor() throws Exception {
60
		assertEquals(propertyDescriptor, decorator.getPropertyDescriptor());
54
		assertSame(propertyDescriptor, decorator.getPropertyDescriptor());
61
	}
55
	}
62
}
56
}
(-)src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedSetTest.java (-28 / +29 lines)
Lines 8-19 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     Matthew Hall - initial API and implementation (bug 221351)
9
 *     Matthew Hall - initial API and implementation (bug 221351)
10
 *     Brad Reynolds - through JavaBeanObservableArrayBasedListTest.java
10
 *     Brad Reynolds - through JavaBeanObservableArrayBasedListTest.java
11
 *     Matthew Hall - bug 213145, 244098, 246103
11
 *     Matthew Hall - bug 213145, 244098, 246103, 194734
12
 ******************************************************************************/
12
 ******************************************************************************/
13
13
14
package org.eclipse.core.tests.internal.databinding.beans;
14
package org.eclipse.core.tests.internal.databinding.beans;
15
15
16
import java.beans.IntrospectionException;
17
import java.beans.PropertyChangeEvent;
16
import java.beans.PropertyChangeEvent;
18
import java.beans.PropertyChangeListener;
17
import java.beans.PropertyChangeListener;
19
import java.beans.PropertyDescriptor;
18
import java.beans.PropertyDescriptor;
Lines 25-37 Link Here
25
import junit.framework.Test;
24
import junit.framework.Test;
26
import junit.framework.TestSuite;
25
import junit.framework.TestSuite;
27
26
27
import org.eclipse.core.databinding.beans.BeanProperties;
28
import org.eclipse.core.databinding.beans.BeansObservables;
28
import org.eclipse.core.databinding.beans.BeansObservables;
29
import org.eclipse.core.databinding.beans.IBeanObservable;
30
import org.eclipse.core.databinding.beans.IBeanProperty;
29
import org.eclipse.core.databinding.observable.IObservable;
31
import org.eclipse.core.databinding.observable.IObservable;
30
import org.eclipse.core.databinding.observable.IObservableCollection;
32
import org.eclipse.core.databinding.observable.IObservableCollection;
31
import org.eclipse.core.databinding.observable.Realm;
33
import org.eclipse.core.databinding.observable.Realm;
32
import org.eclipse.core.databinding.observable.set.IObservableSet;
34
import org.eclipse.core.databinding.observable.set.IObservableSet;
33
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
35
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
34
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet;
35
import org.eclipse.jface.databinding.conformance.MutableObservableSetContractTest;
36
import org.eclipse.jface.databinding.conformance.MutableObservableSetContractTest;
36
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
37
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate;
37
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
38
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
Lines 45-51 Link Here
45
 */
46
 */
46
public class JavaBeanObservableArrayBasedSetTest extends
47
public class JavaBeanObservableArrayBasedSetTest extends
47
		AbstractDefaultRealmTestCase {
48
		AbstractDefaultRealmTestCase {
48
	private JavaBeanObservableSet set;
49
	private IObservableSet set;
50
	private IBeanObservable beanObservable;
49
51
50
	private PropertyDescriptor propertyDescriptor;
52
	private PropertyDescriptor propertyDescriptor;
51
53
Lines 57-83 Link Here
57
		super.setUp();
59
		super.setUp();
58
60
59
		propertyName = "array";
61
		propertyName = "array";
60
		propertyDescriptor = new PropertyDescriptor(propertyName, Bean.class);
62
		propertyDescriptor = ((IBeanProperty) BeanProperties.set(
63
				Bean.class, propertyName)).getPropertyDescriptor();
61
		bean = new Bean(new HashSet());
64
		bean = new Bean(new HashSet());
62
65
63
		set = new JavaBeanObservableSet(SWTObservables.getRealm(Display
66
		set = BeansObservables.observeSet(SWTObservables.getRealm(Display
64
				.getDefault()), bean, propertyDescriptor, String.class);
67
				.getDefault()), bean, propertyName);
68
		beanObservable = (IBeanObservable) set;
65
	}
69
	}
66
70
67
	public void testGetObserved() throws Exception {
71
	public void testGetObserved() throws Exception {
68
		assertEquals(bean, set.getObserved());
72
		assertEquals(bean, beanObservable.getObserved());
69
	}
73
	}
70
74
71
	public void testGetPropertyDescriptor() throws Exception {
75
	public void testGetPropertyDescriptor() throws Exception {
72
		assertEquals(propertyDescriptor, set.getPropertyDescriptor());
76
		assertEquals(propertyDescriptor, beanObservable.getPropertyDescriptor());
73
	}
77
	}
74
78
75
	public void testRegistersListenerOnCreation() throws Exception {
79
	public void testRegistersListenerAfterFirstListenerIsAdded()
80
			throws Exception {
81
		assertFalse(bean.changeSupport.hasListeners(propertyName));
82
		SetChangeEventTracker.observe(set);
76
		assertTrue(bean.changeSupport.hasListeners(propertyName));
83
		assertTrue(bean.changeSupport.hasListeners(propertyName));
77
	}
84
	}
78
85
79
	public void testRemovesListenerOnDisposal() throws Exception {
86
	public void testRemovesListenerAfterLastListenerIsRemoved()
80
		set.dispose();
87
			throws Exception {
88
		SetChangeEventTracker listener = SetChangeEventTracker.observe(set);
89
90
		assertTrue(bean.changeSupport.hasListeners(propertyName));
91
		set.removeSetChangeListener(listener);
81
		assertFalse(bean.changeSupport.hasListeners(propertyName));
92
		assertFalse(bean.changeSupport.hasListeners(propertyName));
82
	}
93
	}
83
94
Lines 309-315 Link Here
309
		assertEquals("array", event.getPropertyName());
320
		assertEquals("array", event.getPropertyName());
310
		assertTrue("old value", Arrays.equals(old, (Object[]) event
321
		assertTrue("old value", Arrays.equals(old, (Object[]) event
311
				.getOldValue()));
322
				.getOldValue()));
312
		assertTrue("new value", Arrays.equals(bean.getArray(), (Object[]) event.getNewValue()));
323
		assertTrue("new value", Arrays.equals(bean.getArray(), (Object[]) event
324
				.getNewValue()));
313
		assertFalse("sets are equal", Arrays.equals(bean.getArray(), old));
325
		assertFalse("sets are equal", Arrays.equals(bean.getArray(), old));
314
	}
326
	}
315
327
Lines 319-329 Link Here
319
331
320
		PropertyChangeEvent evt;
332
		PropertyChangeEvent evt;
321
333
322
		/*
323
		 * (non-Javadoc)
324
		 * 
325
		 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
326
		 */
327
		public void propertyChange(PropertyChangeEvent evt) {
334
		public void propertyChange(PropertyChangeEvent evt) {
328
			count++;
335
			count++;
329
			this.evt = evt;
336
			this.evt = evt;
Lines 331-337 Link Here
331
	}
338
	}
332
339
333
	public static Test suite() {
340
	public static Test suite() {
334
		TestSuite suite = new TestSuite(JavaBeanObservableArrayBasedSetTest.class.getName());
341
		TestSuite suite = new TestSuite(
342
				JavaBeanObservableArrayBasedSetTest.class.getName());
335
		suite.addTestSuite(JavaBeanObservableArrayBasedSetTest.class);
343
		suite.addTestSuite(JavaBeanObservableArrayBasedSetTest.class);
336
		suite.addTest(MutableObservableSetContractTest.suite(new Delegate()));
344
		suite.addTest(MutableObservableSetContractTest.suite(new Delegate()));
337
		return suite;
345
		return suite;
Lines 341-357 Link Here
341
		public IObservableCollection createObservableCollection(Realm realm,
349
		public IObservableCollection createObservableCollection(Realm realm,
342
				int elementCount) {
350
				int elementCount) {
343
			String propertyName = "array";
351
			String propertyName = "array";
344
			PropertyDescriptor propertyDescriptor;
345
			try {
346
				propertyDescriptor = new PropertyDescriptor(propertyName,
347
						Bean.class);
348
			} catch (IntrospectionException e) {
349
				throw new RuntimeException(e);
350
			}
351
			Object bean = new Bean(new Object[0]);
352
			Object bean = new Bean(new Object[0]);
352
353
353
			IObservableSet set = new JavaBeanObservableSet(realm, bean,
354
			IObservableSet set = BeansObservables.observeSet(realm, bean,
354
					propertyDescriptor, String.class);
355
					propertyName, String.class);
355
			for (int i = 0; i < elementCount; i++)
356
			for (int i = 0; i < elementCount; i++)
356
				set.add(createElement(set));
357
				set.add(createElement(set));
357
			return set;
358
			return set;
(-)src/org/eclipse/core/tests/internal/databinding/beans/ListenerSupportTest.java (-231 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.core.tests.internal.databinding.beans;
13
14
import java.beans.PropertyChangeEvent;
15
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyChangeSupport;
17
import java.util.Arrays;
18
19
import org.eclipse.core.databinding.util.ILogger;
20
import org.eclipse.core.databinding.util.Policy;
21
import org.eclipse.core.internal.databinding.beans.ListenerSupport;
22
import org.eclipse.core.runtime.IStatus;
23
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
24
25
/**
26
 * @since 1.1
27
 */
28
public class ListenerSupportTest extends AbstractDefaultRealmTestCase {
29
	private PropertyChangeListenerStub listener;
30
	private String propertyName;
31
32
	protected void setUp() throws Exception {
33
		super.setUp();
34
35
		listener = new PropertyChangeListenerStub();
36
		propertyName = "value";
37
	}
38
39
	public void testAddPropertyChangeListenerWithPropertyName()
40
			throws Exception {
41
		SpecificListenerBean bean = new SpecificListenerBean();
42
43
		ListenerSupport support = new ListenerSupport(listener, propertyName);
44
		assertFalse(bean.changeSupport.hasListeners(propertyName));
45
		assertNull(support.getHookedTargets());
46
		
47
		support.hookListener(bean);
48
		assertTrue("has listeners", bean.changeSupport.hasListeners(propertyName));
49
		assertTrue("hooked target", Arrays.asList(support.getHookedTargets()).contains(bean));
50
	}
51
52
	public void testAddPropertyChangeListenerWithoutPropertyName()
53
			throws Exception {
54
		GenericListenerBean bean = new GenericListenerBean();
55
56
		ListenerSupport support = new ListenerSupport(listener, propertyName);
57
		assertFalse(bean.changeSupport.hasListeners(propertyName));
58
		assertNull(support.getHookedTargets());
59
		
60
		support.hookListener(bean);
61
		assertTrue("has listeners", bean.changeSupport.hasListeners(propertyName));
62
		assertTrue("hooked target", Arrays.asList(support.getHookedTargets()).contains(bean));
63
	}
64
65
	public void testChangeListenerIsOnlyNotifiedWhenWatchedPropertyChanges()
66
			throws Exception {
67
		GenericListenerBean bean = new GenericListenerBean();
68
		ListenerSupport support = new ListenerSupport(listener, propertyName);
69
		support.hookListener(bean);
70
71
		assertEquals(0, listener.count);
72
		bean.setValue("1");
73
		assertEquals(1, listener.count);
74
		assertEquals("value", listener.event.getPropertyName());
75
76
		bean.setOther("2");
77
		assertEquals(1, listener.count);
78
	}
79
80
	public void testLogStatusWhenAddPropertyChangeListenerMethodIsNotFound()
81
			throws Exception {
82
		class BeanStub {
83
		}
84
85
		class Log implements ILogger {
86
			int count;
87
			IStatus status;
88
89
			public void log(IStatus status) {
90
				count++;
91
				this.status = status;
92
			}
93
		}
94
95
		Log log = new Log();
96
		Policy.setLog(log);
97
98
		ListenerSupport support = new ListenerSupport(listener, "value");
99
		BeanStub bean = new BeanStub();
100
101
		assertEquals(0, log.count);
102
		support.hookListener(bean);
103
		assertEquals(1, log.count);
104
		assertEquals(IStatus.WARNING, log.status.getSeverity());
105
	}
106
107
	public void testRemovePropertyChangeListenerWithPropertyName()
108
			throws Exception {
109
		SpecificListenerBean bean = new SpecificListenerBean();
110
		ListenerSupport support = new ListenerSupport(listener, propertyName);
111
		support.hookListener(bean);
112
113
		assertTrue(bean.changeSupport.hasListeners(propertyName));
114
		assertTrue(Arrays.asList(support.getHookedTargets()).contains(bean));
115
		
116
		support.unhookListener(bean);
117
		assertFalse("has listeners", bean.changeSupport.hasListeners(propertyName));
118
		assertNull("unhooked target", support.getHookedTargets());
119
	}
120
121
	public void testRemovePropertyChangeListenerWithoutPropertyName()
122
			throws Exception {
123
		GenericListenerBean bean = new GenericListenerBean();
124
		ListenerSupport support = new ListenerSupport(listener, propertyName);
125
		support.hookListener(bean);
126
127
		assertTrue(bean.changeSupport.hasListeners(propertyName));
128
		assertTrue(Arrays.asList(support.getHookedTargets()).contains(bean));
129
		
130
		support.unhookListener(bean);
131
		assertFalse("has listeners", bean.changeSupport.hasListeners(propertyName));
132
		assertNull("unhooked target", support.getHookedTargets());
133
	}
134
135
	public void testLogStatusWhenRemovePropertyChangeListenerMethodIsNotFound()
136
			throws Exception {
137
		class InvalidBean {
138
		}
139
140
		class Log implements ILogger {
141
			int count;
142
			IStatus status;
143
144
			public void log(IStatus status) {
145
				count++;
146
				this.status = status;
147
			}
148
		}
149
150
		Log log = new Log();
151
		Policy.setLog(log);
152
153
		ListenerSupport support = new ListenerSupport(listener, "value");
154
		InvalidBean bean = new InvalidBean();
155
156
		support.hookListener(bean);
157
		log.count = 0;
158
		log.status = null;
159
		assertEquals(0, log.count);
160
		support.unhookListener(bean);
161
		assertEquals(1, log.count);
162
		assertEquals(IStatus.WARNING, log.status.getSeverity());
163
	}
164
165
	static class GenericListenerBean {
166
		private String other;
167
		PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
168
		private String value;
169
170
		public String getValue() {
171
			return value;
172
		}
173
174
		public void setValue(String value) {
175
			changeSupport.firePropertyChange("value", this.value,
176
					this.value = value);
177
		}
178
179
		public String getOther() {
180
			return other;
181
		}
182
183
		public void setOther(String other) {
184
			changeSupport.firePropertyChange("other", this.other,
185
					this.other = other);
186
		}
187
188
		public void addPropertyChangeListener(PropertyChangeListener listener) {
189
			changeSupport.addPropertyChangeListener(listener);
190
		}
191
192
		public void removePropertyChangeListener(PropertyChangeListener listener) {
193
			changeSupport.removePropertyChangeListener(listener);
194
		}
195
	}
196
197
	static class SpecificListenerBean {
198
		PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
199
		String propertyName;
200
		String value;
201
202
		public void addPropertyChangeListener(String name,
203
				PropertyChangeListener listener) {
204
			this.propertyName = name;
205
			changeSupport.addPropertyChangeListener(name, listener);
206
		}
207
208
		public void removePropertyChangeListener(String name,
209
				PropertyChangeListener listener) {
210
			changeSupport.removePropertyChangeListener(name, listener);
211
		}
212
213
		public String getValue() {
214
			return value;
215
		}
216
217
		public void setValue(String value) {
218
			this.value = value;
219
		}
220
	}
221
222
	static class PropertyChangeListenerStub implements PropertyChangeListener {
223
		PropertyChangeEvent event;
224
		int count;
225
226
		public void propertyChange(PropertyChangeEvent evt) {
227
			count++;
228
			this.event = evt;
229
		}
230
	}
231
}
(-)src/org/eclipse/jface/tests/databinding/BindingTestSuite.java (-28 / +33 lines)
Lines 77-82 Link Here
77
import org.eclipse.core.tests.internal.databinding.beans.BeanObservableListDecoratorTest;
77
import org.eclipse.core.tests.internal.databinding.beans.BeanObservableListDecoratorTest;
78
import org.eclipse.core.tests.internal.databinding.beans.BeanObservableSetDecoratorTest;
78
import org.eclipse.core.tests.internal.databinding.beans.BeanObservableSetDecoratorTest;
79
import org.eclipse.core.tests.internal.databinding.beans.BeanObservableValueDecoratorTest;
79
import org.eclipse.core.tests.internal.databinding.beans.BeanObservableValueDecoratorTest;
80
import org.eclipse.core.tests.internal.databinding.beans.BeanPropertyListenerSupportTest;
81
import org.eclipse.core.tests.internal.databinding.beans.BeanValuePropertyTest;
80
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableArrayBasedListTest;
82
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableArrayBasedListTest;
81
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableArrayBasedSetTest;
83
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableArrayBasedSetTest;
82
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableListTest;
84
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableListTest;
Lines 84-90 Link Here
84
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableSetTest;
86
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableSetTest;
85
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableValueTest;
87
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableValueTest;
86
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanPropertyObservableMapTest;
88
import org.eclipse.core.tests.internal.databinding.beans.JavaBeanPropertyObservableMapTest;
87
import org.eclipse.core.tests.internal.databinding.beans.ListenerSupportTest;
88
import org.eclipse.core.tests.internal.databinding.conversion.DateConversionSupportTest;
89
import org.eclipse.core.tests.internal.databinding.conversion.DateConversionSupportTest;
89
import org.eclipse.core.tests.internal.databinding.conversion.IdentityConverterTest;
90
import org.eclipse.core.tests.internal.databinding.conversion.IdentityConverterTest;
90
import org.eclipse.core.tests.internal.databinding.conversion.IntegerToStringConverterTest;
91
import org.eclipse.core.tests.internal.databinding.conversion.IntegerToStringConverterTest;
Lines 163-169 Link Here
163
import org.eclipse.jface.tests.internal.databinding.swt.LabelObservableValueTest;
164
import org.eclipse.jface.tests.internal.databinding.swt.LabelObservableValueTest;
164
import org.eclipse.jface.tests.internal.databinding.swt.ListSingleSelectionObservableValueTest;
165
import org.eclipse.jface.tests.internal.databinding.swt.ListSingleSelectionObservableValueTest;
165
import org.eclipse.jface.tests.internal.databinding.swt.SWTDelayedObservableValueDecoratorTest;
166
import org.eclipse.jface.tests.internal.databinding.swt.SWTDelayedObservableValueDecoratorTest;
166
import org.eclipse.jface.tests.internal.databinding.swt.SWTObservableListTest;
167
import org.eclipse.jface.tests.internal.databinding.swt.ScaleObservableValueMaxTest;
167
import org.eclipse.jface.tests.internal.databinding.swt.ScaleObservableValueMaxTest;
168
import org.eclipse.jface.tests.internal.databinding.swt.ScaleObservableValueMinTest;
168
import org.eclipse.jface.tests.internal.databinding.swt.ScaleObservableValueMinTest;
169
import org.eclipse.jface.tests.internal.databinding.swt.ScaleObservableValueSelectionTest;
169
import org.eclipse.jface.tests.internal.databinding.swt.ScaleObservableValueSelectionTest;
Lines 172-177 Link Here
172
import org.eclipse.jface.tests.internal.databinding.swt.SpinnerObservableValueMinTest;
172
import org.eclipse.jface.tests.internal.databinding.swt.SpinnerObservableValueMinTest;
173
import org.eclipse.jface.tests.internal.databinding.swt.SpinnerObservableValueSelectionTest;
173
import org.eclipse.jface.tests.internal.databinding.swt.SpinnerObservableValueSelectionTest;
174
import org.eclipse.jface.tests.internal.databinding.swt.SpinnerObservableValueTest;
174
import org.eclipse.jface.tests.internal.databinding.swt.SpinnerObservableValueTest;
175
import org.eclipse.jface.tests.internal.databinding.swt.StyledTextObservableValueFocusOutTest;
176
import org.eclipse.jface.tests.internal.databinding.swt.StyledTextObservableValueModifyTest;
177
import org.eclipse.jface.tests.internal.databinding.swt.StyledTextObservableValueTest;
175
import org.eclipse.jface.tests.internal.databinding.swt.TableObservableValueTest;
178
import org.eclipse.jface.tests.internal.databinding.swt.TableObservableValueTest;
176
import org.eclipse.jface.tests.internal.databinding.swt.TableSingleSelectionObservableValueTest;
179
import org.eclipse.jface.tests.internal.databinding.swt.TableSingleSelectionObservableValueTest;
177
import org.eclipse.jface.tests.internal.databinding.swt.TextEditableObservableValueTest;
180
import org.eclipse.jface.tests.internal.databinding.swt.TextEditableObservableValueTest;
Lines 198-204 Link Here
198
	}
201
	}
199
202
200
	public BindingTestSuite() {
203
	public BindingTestSuite() {
201
		
204
202
		// org.eclipse.core.tests.databinding
205
		// org.eclipse.core.tests.databinding
203
		addTestSuite(AggregateValidationStatusTest.class);
206
		addTestSuite(AggregateValidationStatusTest.class);
204
		addTestSuite(BindingTest.class);
207
		addTestSuite(BindingTest.class);
Lines 253-271 Link Here
253
		addTest(ObservableSetTest.suite());
256
		addTest(ObservableSetTest.suite());
254
		addTest(UnionSetTest.suite());
257
		addTest(UnionSetTest.suite());
255
		addTest(WritableSetTest.suite());
258
		addTest(WritableSetTest.suite());
256
		
259
257
		//org.eclipse.core.tests.databinding.observable.value
260
		// org.eclipse.core.tests.databinding.observable.value
258
		addTestSuite(AbstractObservableValueTest.class);
261
		addTestSuite(AbstractObservableValueTest.class);
259
		addTestSuite(AbstractVetoableValueTest.class);
262
		addTestSuite(AbstractVetoableValueTest.class);
260
		addTestSuite(ComputedValueTest.class);
263
		addTestSuite(ComputedValueTest.class);
261
		addTest(DecoratingObservableValueTest.suite());
264
		addTest(DecoratingObservableValueTest.suite());
262
		addTest(SelectObservableValueTest.suite());
265
		addTest(SelectObservableValueTest.suite());
263
		addTest(WritableValueTest.suite());
266
		addTest(WritableValueTest.suite());
264
		
267
265
		//org.eclipse.core.tests.databinding.validation
268
		// org.eclipse.core.tests.databinding.validation
266
		addTestSuite(MultiValidatorTest.class);
269
		addTestSuite(MultiValidatorTest.class);
267
		addTestSuite(ValidationStatusTest.class);
270
		addTestSuite(ValidationStatusTest.class);
268
		
271
269
		// org.eclipse.core.tests.internal.databinding
272
		// org.eclipse.core.tests.internal.databinding
270
		addTestSuite(BindingMessagesTest.class);
273
		addTestSuite(BindingMessagesTest.class);
271
		addTestSuite(BindingStatusTest.class);
274
		addTestSuite(BindingStatusTest.class);
Lines 298-308 Link Here
298
		addTestSuite(StringToNumberParserTest.class);
301
		addTestSuite(StringToNumberParserTest.class);
299
		addTestSuite(StringToShortConverterTest.class);
302
		addTestSuite(StringToShortConverterTest.class);
300
303
301
		//org.eclipse.core.tests.internal.databinding.internal.beans
304
		// org.eclipse.core.tests.internal.databinding.internal.beans
302
		addTest(BeanObservableListDecoratorTest.suite());
305
		addTest(BeanObservableListDecoratorTest.suite());
303
		addTestSuite(BeanObservableSetDecoratorTest.class);
306
		addTestSuite(BeanObservableSetDecoratorTest.class);
304
		addTestSuite(BeanObservableValueDecoratorTest.class);
307
		addTestSuite(BeanObservableValueDecoratorTest.class);
305
		addTestSuite(BeanObservableListDecoratorTest.class);
308
		addTestSuite(BeanObservableListDecoratorTest.class);
309
		addTestSuite(BeanValuePropertyTest.class);
306
		addTest(JavaBeanObservableArrayBasedListTest.suite());
310
		addTest(JavaBeanObservableArrayBasedListTest.suite());
307
		addTest(JavaBeanObservableArrayBasedSetTest.suite());
311
		addTest(JavaBeanObservableArrayBasedSetTest.suite());
308
		addTest(JavaBeanObservableListTest.suite());
312
		addTest(JavaBeanObservableListTest.suite());
Lines 310-318 Link Here
310
		addTest(JavaBeanObservableSetTest.suite());
314
		addTest(JavaBeanObservableSetTest.suite());
311
		addTest(JavaBeanObservableValueTest.suite());
315
		addTest(JavaBeanObservableValueTest.suite());
312
		addTestSuite(JavaBeanPropertyObservableMapTest.class);
316
		addTestSuite(JavaBeanPropertyObservableMapTest.class);
313
		addTestSuite(ListenerSupportTest.class);
317
		addTestSuite(BeanPropertyListenerSupportTest.class);
314
		
318
315
		//org.eclipse.core.tests.internal.databinding.observable
319
		// org.eclipse.core.tests.internal.databinding.observable
316
		addTest(ConstantObservableValueTest.suite());
320
		addTest(ConstantObservableValueTest.suite());
317
		addTest(DelayedObservableValueTest.suite());
321
		addTest(DelayedObservableValueTest.suite());
318
		addTest(EmptyObservableListTest.suite());
322
		addTest(EmptyObservableListTest.suite());
Lines 325-332 Link Here
325
		addTest(ValidatedObservableValueTest.suite());
329
		addTest(ValidatedObservableValueTest.suite());
326
		addTest(ValidatedObservableListTest.suite());
330
		addTest(ValidatedObservableListTest.suite());
327
		addTest(ValidatedObservableSetTest.suite());
331
		addTest(ValidatedObservableSetTest.suite());
328
//		addTest(ValidatedObservableMapTest.suite());
332
		// addTest(ValidatedObservableMapTest.suite());
329
		
333
330
		// org.eclipse.core.tests.internal.databinding.observable.masterdetail
334
		// org.eclipse.core.tests.internal.databinding.observable.masterdetail
331
		addTest(DetailObservableListTest.suite());
335
		addTest(DetailObservableListTest.suite());
332
		addTest(DetailObservableSetTest.suite());
336
		addTest(DetailObservableSetTest.suite());
Lines 353-376 Link Here
353
		addTest(BindingScenariosTestSuite.suite());
357
		addTest(BindingScenariosTestSuite.suite());
354
		// The files in this package are in the above test suite
358
		// The files in this package are in the above test suite
355
359
356
		//org.eclipse.jface.tests.databinding.swt
360
		// org.eclipse.jface.tests.databinding.swt
357
		addTestSuite(SWTObservablesTest.class);
361
		addTestSuite(SWTObservablesTest.class);
358
		
362
359
		// org.eclipse.jface.tests.databinding.viewers
363
		// org.eclipse.jface.tests.databinding.viewers
360
		addTestSuite(ObservableListTreeContentProviderTest.class);
364
		addTestSuite(ObservableListTreeContentProviderTest.class);
361
		addTestSuite(ObservableMapLabelProviderTest.class);
365
		addTestSuite(ObservableMapLabelProviderTest.class);
362
		addTestSuite(ObservableSetContentProviderTest.class);
366
		addTestSuite(ObservableSetContentProviderTest.class);
363
		addTestSuite(ObservableSetTreeContentProviderTest.class);
367
		addTestSuite(ObservableSetTreeContentProviderTest.class);
364
		addTestSuite(ViewersObservablesTest.class);
368
		addTestSuite(ViewersObservablesTest.class);
365
		
369
366
		// org.eclipse.jface.tests.databinding.wizard
370
		// org.eclipse.jface.tests.databinding.wizard
367
		addTestSuite(WizardPageSupportTest.class);
371
		addTestSuite(WizardPageSupportTest.class);
368
		
372
369
		//org.eclipse.jface.tests.example.databinding.mask.internal
373
		// org.eclipse.jface.tests.example.databinding.mask.internal
370
		addTestSuite(EditMaskLexerAndTokenTest.class);
374
		addTestSuite(EditMaskLexerAndTokenTest.class);
371
		addTestSuite(EditMaskParserTest.class);
375
		addTestSuite(EditMaskParserTest.class);
372
376
373
		//org.eclipse.jface.tests.internal.databinding.internal.swt
377
		// org.eclipse.jface.tests.internal.databinding.internal.swt
374
		addTest(ButtonObservableValueTest.suite());
378
		addTest(ButtonObservableValueTest.suite());
375
		addTestSuite(CComboObservableValueTest.class);
379
		addTestSuite(CComboObservableValueTest.class);
376
		addTest(CComboObservableValueSelectionTest.suite());
380
		addTest(CComboObservableValueSelectionTest.suite());
Lines 383-413 Link Here
383
		addTest(ComboObservableValueTextTest.suite());
387
		addTest(ComboObservableValueTextTest.suite());
384
		addTestSuite(ComboSingleSelectionObservableValueTest.class);
388
		addTestSuite(ComboSingleSelectionObservableValueTest.class);
385
		addTest(SWTDelayedObservableValueDecoratorTest.suite());
389
		addTest(SWTDelayedObservableValueDecoratorTest.suite());
386
		
390
387
		addTest(SWTObservableListTest.suite());
388
		
389
		addTestSuite(ControlObservableValueTest.class);
391
		addTestSuite(ControlObservableValueTest.class);
390
		addTest(LabelObservableValueTest.suite());
392
		addTest(LabelObservableValueTest.suite());
391
		addTestSuite(ListSingleSelectionObservableValueTest.class);
393
		addTestSuite(ListSingleSelectionObservableValueTest.class);
392
		addTest(ScaleObservableValueMinTest.suite());
394
		addTest(ScaleObservableValueMinTest.suite());
393
		addTest(ScaleObservableValueMaxTest.suite());
395
		addTest(ScaleObservableValueMaxTest.suite());
394
		addTest(ScaleObservableValueSelectionTest.suite());
396
		addTest(ScaleObservableValueSelectionTest.suite());
395
		
397
396
		addTest(ShellObservableValueTest.suite());
398
		addTest(ShellObservableValueTest.suite());
397
		
399
398
		addTestSuite(SpinnerObservableValueTest.class);
400
		addTestSuite(SpinnerObservableValueTest.class);
399
		addTest(SpinnerObservableValueMinTest.suite());
401
		addTest(SpinnerObservableValueMinTest.suite());
400
		addTest(SpinnerObservableValueMaxTest.suite());
402
		addTest(SpinnerObservableValueMaxTest.suite());
401
		addTest(SpinnerObservableValueSelectionTest.suite());
403
		addTest(SpinnerObservableValueSelectionTest.suite());
402
		
404
403
		addTestSuite(TableObservableValueTest.class);
405
		addTestSuite(TableObservableValueTest.class);
404
		addTest(TableSingleSelectionObservableValueTest.suite());
406
		addTest(TableSingleSelectionObservableValueTest.suite());
405
		addTest(TextEditableObservableValueTest.suite());
407
		addTest(TextEditableObservableValueTest.suite());
406
		addTest(TextObservableValueFocusOutTest.suite());
408
		addTest(TextObservableValueFocusOutTest.suite());
407
		addTest(TextObservableValueModifyTest.suite());
409
		addTest(TextObservableValueModifyTest.suite());
408
		addTestSuite(TextObservableValueTest.class);
410
		addTestSuite(TextObservableValueTest.class);
409
		
411
		addTest(StyledTextObservableValueFocusOutTest.suite());
410
		//org.eclipse.jface.tests.internal.databinding.internal.viewers
412
		addTest(StyledTextObservableValueModifyTest.suite());
413
		addTestSuite(StyledTextObservableValueTest.class);
414
415
		// org.eclipse.jface.tests.internal.databinding.internal.viewers
411
		addTest(ObservableViewerElementSetTest.suite());
416
		addTest(ObservableViewerElementSetTest.suite());
412
		addTestSuite(ObservableCollectionTreeContentProviderTest.class);
417
		addTestSuite(ObservableCollectionTreeContentProviderTest.class);
413
		addTestSuite(SelectionProviderMultiSelectionObservableListTest.class);
418
		addTestSuite(SelectionProviderMultiSelectionObservableListTest.class);
(-)src/org/eclipse/core/tests/databinding/beans/PojoObservablesTest.java (-18 / +16 lines)
Lines 7-16 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 194734
10
 *******************************************************************************/
11
 *******************************************************************************/
11
12
12
package org.eclipse.core.tests.databinding.beans;
13
package org.eclipse.core.tests.databinding.beans;
13
14
15
import org.eclipse.core.databinding.beans.IBeanObservable;
14
import org.eclipse.core.databinding.beans.PojoObservables;
16
import org.eclipse.core.databinding.beans.PojoObservables;
15
import org.eclipse.core.databinding.observable.Realm;
17
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
18
import org.eclipse.core.databinding.observable.list.IObservableList;
Lines 19-28 Link Here
19
import org.eclipse.core.databinding.observable.set.IObservableSet;
21
import org.eclipse.core.databinding.observable.set.IObservableSet;
20
import org.eclipse.core.databinding.observable.set.WritableSet;
22
import org.eclipse.core.databinding.observable.set.WritableSet;
21
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.core.databinding.observable.value.IObservableValue;
22
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList;
23
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableMap;
24
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet;
25
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableValue;
26
import org.eclipse.core.tests.internal.databinding.beans.Bean;
24
import org.eclipse.core.tests.internal.databinding.beans.Bean;
27
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
25
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
28
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
26
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
Lines 47-58 Link Here
47
		propertyName = "value";
45
		propertyName = "value";
48
	}
46
	}
49
47
50
	public void testObserveValue_ReturnsJavaBeanObservableValue()
48
	public void testObserveValue_ReturnsIBeanObservable()
51
			throws Exception {
49
			throws Exception {
52
		IObservableValue value = PojoObservables.observeValue(pojo, propertyName);
50
		IObservableValue value = PojoObservables.observeValue(pojo, propertyName);
53
51
54
		assertNotNull(value);
52
		assertNotNull(value);
55
		assertTrue(value instanceof JavaBeanObservableValue);
53
		assertTrue(value instanceof IBeanObservable);
56
	}
54
	}
57
55
58
	public void testObserveValue_DoesNotAttachListeners() throws Exception {
56
	public void testObserveValue_DoesNotAttachListeners() throws Exception {
Lines 62-78 Link Here
62
		assertFalse(pojo.hasListeners(propertyName));
60
		assertFalse(pojo.hasListeners(propertyName));
63
	}
61
	}
64
62
65
	public void testObservableValueWithRealm_ReturnsJavaBeanObservable()
63
	public void testObservableValueWithRealm_ReturnsIBeanObservable()
66
			throws Exception {
64
			throws Exception {
67
		CurrentRealm realm = new CurrentRealm(true);
65
		CurrentRealm realm = new CurrentRealm(true);
68
		IObservableValue value = PojoObservables.observeValue(realm, pojo,
66
		IObservableValue value = PojoObservables.observeValue(realm, pojo,
69
				propertyName);
67
				propertyName);
70
68
71
		assertNotNull(value);
69
		assertNotNull(value);
72
		assertTrue(value instanceof JavaBeanObservableValue);
70
		assertTrue(value instanceof IBeanObservable);
73
	}
71
	}
74
72
75
	public void testObservableMap_ReturnsJavaBeanObservableMap()
73
	public void testObservableMap_ReturnsIBeanObservable()
76
			throws Exception {
74
			throws Exception {
77
		IObservableSet set = new WritableSet();
75
		IObservableSet set = new WritableSet();
78
		set.add(new Bean());
76
		set.add(new Bean());
Lines 80-86 Link Here
80
		IObservableMap map = PojoObservables.observeMap(set, Bean.class,
78
		IObservableMap map = PojoObservables.observeMap(set, Bean.class,
81
				propertyName);
79
				propertyName);
82
		assertNotNull(map);
80
		assertNotNull(map);
83
		assertTrue(map instanceof JavaBeanObservableMap);
81
		assertTrue(map instanceof IBeanObservable);
84
	}
82
	}
85
	
83
	
86
	public void testObservableMap_DoesNotAttachListeners() throws Exception {
84
	public void testObservableMap_DoesNotAttachListeners() throws Exception {
Lines 101-109 Link Here
101
		assertEquals(2, maps.length);
99
		assertEquals(2, maps.length);
102
	}
100
	}
103
	
101
	
104
	public void testObserveListWithElementType_ReturnsJavaBeanObservableList() throws Exception {
102
	public void testObserveListWithElementType_ReturnsIBeanObservable() throws Exception {
105
		IObservableList list = PojoObservables.observeList(Realm.getDefault(), pojo, "list", String.class);
103
		IObservableList list = PojoObservables.observeList(Realm.getDefault(), pojo, "list", String.class);
106
		assertTrue(list instanceof JavaBeanObservableList);
104
		assertTrue(list instanceof IBeanObservable);
107
	}
105
	}
108
	
106
	
109
	public void testObserveListWithElementType_DoesNotAttachListeners() throws Exception {
107
	public void testObserveListWithElementType_DoesNotAttachListeners() throws Exception {
Lines 113-121 Link Here
113
		assertFalse(pojo.hasListeners("list"));
111
		assertFalse(pojo.hasListeners("list"));
114
	}
112
	}
115
	
113
	
116
	public void testObserveList_ReturnsJavaBeanObservableList() throws Exception {
114
	public void testObserveList_ReturnsIBeanObservable() throws Exception {
117
		IObservableList observable = PojoObservables.observeList(Realm.getDefault(), pojo, "list");
115
		IObservableList observable = PojoObservables.observeList(Realm.getDefault(), pojo, "list");
118
		assertTrue(observable instanceof JavaBeanObservableList);
116
		assertTrue(observable instanceof IBeanObservable);
119
	}
117
	}
120
	
118
	
121
	public void testObserveList_DoesNotAttachListeners() throws Exception {
119
	public void testObserveList_DoesNotAttachListeners() throws Exception {
Lines 125-133 Link Here
125
		assertFalse(pojo.hasListeners("list"));
123
		assertFalse(pojo.hasListeners("list"));
126
	}
124
	}
127
	
125
	
128
	public void testObserveSetWithElementType_ReturnsJavaBeanObservableList() throws Exception {
126
	public void testObserveSetWithElementType_ReturnsIBeanObservable() throws Exception {
129
		IObservableSet list = PojoObservables.observeSet(Realm.getDefault(), pojo, "set", String.class);
127
		IObservableSet list = PojoObservables.observeSet(Realm.getDefault(), pojo, "set", String.class);
130
		assertTrue(list instanceof JavaBeanObservableSet);
128
		assertTrue(list instanceof IBeanObservable);
131
	}
129
	}
132
	
130
	
133
	public void testObserveSetWithElementType_DoesNotAttachListeners() throws Exception {
131
	public void testObserveSetWithElementType_DoesNotAttachListeners() throws Exception {
Lines 137-145 Link Here
137
		assertFalse(pojo.hasListeners("set"));
135
		assertFalse(pojo.hasListeners("set"));
138
	}
136
	}
139
	
137
	
140
	public void testObserveSet_ReturnsJavaBeanObservableList() throws Exception {
138
	public void testObserveSet_ReturnsIBeanObservable() throws Exception {
141
		IObservableSet list = PojoObservables.observeSet(Realm.getDefault(), pojo, "set");
139
		IObservableSet list = PojoObservables.observeSet(Realm.getDefault(), pojo, "set");
142
		assertTrue(list instanceof JavaBeanObservableSet);
140
		assertTrue(list instanceof IBeanObservable);
143
	}
141
	}
144
	
142
	
145
	public void testObserveSet_DoesNotAttachListeners() throws Exception {
143
	public void testObserveSet_DoesNotAttachListeners() throws Exception {
(-)src/org/eclipse/jface/tests/databinding/viewers/ViewersObservablesTest.java (-4 / +11 lines)
Lines 7-21 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     Matthew Hall - initial API and implementation (bug 206839)
9
 *     Matthew Hall - initial API and implementation (bug 206839)
10
 *     Matthew Hall - bug 194734
10
 ******************************************************************************/
11
 ******************************************************************************/
11
12
12
package org.eclipse.jface.tests.databinding.viewers;
13
package org.eclipse.jface.tests.databinding.viewers;
13
14
15
import org.eclipse.core.databinding.observable.IDecoratingObservable;
14
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.value.IObservableValue;
17
import org.eclipse.core.databinding.property.IPropertyObservable;
16
import org.eclipse.jface.databinding.swt.SWTObservables;
18
import org.eclipse.jface.databinding.swt.SWTObservables;
19
import org.eclipse.jface.databinding.viewers.IViewerObservableValue;
17
import org.eclipse.jface.databinding.viewers.ViewersObservables;
20
import org.eclipse.jface.databinding.viewers.ViewersObservables;
18
import org.eclipse.jface.internal.databinding.viewers.ViewerInputObservableValue;
21
import org.eclipse.jface.internal.databinding.viewers.ViewerInputProperty;
19
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
22
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
20
import org.eclipse.jface.viewers.TableViewer;
23
import org.eclipse.jface.viewers.TableViewer;
21
import org.eclipse.swt.SWT;
24
import org.eclipse.swt.SWT;
Lines 48-54 Link Here
48
	}
51
	}
49
52
50
	public void testObserveInput_InstanceOfViewerInputObservableValue() {
53
	public void testObserveInput_InstanceOfViewerInputObservableValue() {
51
		IObservableValue observable = ViewersObservables.observeInput(viewer);
54
		IViewerObservableValue observable = (IViewerObservableValue) ViewersObservables
52
		assertTrue(observable instanceof ViewerInputObservableValue);
55
				.observeInput(viewer);
56
		assertTrue(observable.getViewer() == viewer);
57
		IPropertyObservable propertyObservable = (IPropertyObservable) ((IDecoratingObservable) observable)
58
				.getDecorated();
59
		assertTrue(propertyObservable.getProperty() instanceof ViewerInputProperty);
53
	}
60
	}
54
}
61
}
(-)src/org/eclipse/jface/tests/internal/databinding/viewers/ViewerInputObservableValueTest.java (-19 / +23 lines)
Lines 6-13 Link Here
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *    Matthew Hall - initial API and implementation (bug 206839)
9
 *     Matthew Hall - initial API and implementation (bug 206839)
10
 *     Matthew Hall - bug 213145
10
 *     Matthew Hall - bug 213145, 194734, 195222
11
 *******************************************************************************/
11
 *******************************************************************************/
12
package org.eclipse.jface.tests.internal.databinding.viewers;
12
package org.eclipse.jface.tests.internal.databinding.viewers;
13
13
Lines 21-27 Link Here
21
import org.eclipse.jface.databinding.conformance.MutableObservableValueContractTest;
21
import org.eclipse.jface.databinding.conformance.MutableObservableValueContractTest;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
22
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
23
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
23
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
24
import org.eclipse.jface.internal.databinding.viewers.ViewerInputObservableValue;
24
import org.eclipse.jface.databinding.viewers.ViewerProperties;
25
import org.eclipse.jface.databinding.viewers.ViewersObservables;
25
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
26
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
26
import org.eclipse.jface.viewers.IStructuredContentProvider;
27
import org.eclipse.jface.viewers.IStructuredContentProvider;
27
import org.eclipse.jface.viewers.TableViewer;
28
import org.eclipse.jface.viewers.TableViewer;
Lines 55-88 Link Here
55
56
56
	public void testConstructor_IllegalArgumentException() {
57
	public void testConstructor_IllegalArgumentException() {
57
		try {
58
		try {
58
			new ViewerInputObservableValue(Realm.getDefault(), null);
59
			ViewersObservables.observeInput(null);
59
			fail("Expected IllegalArgumentException for null argument");
60
			fail("Expected IllegalArgumentException for null argument");
60
		} catch (IllegalArgumentException expected) {
61
		} catch (IllegalArgumentException expected) {
61
		}
62
		}
62
	}
63
	}
63
64
64
	public void testSetInputOnViewer_FiresNoChangeEvents() {
65
	public void testSetInputOnViewer_FiresChangeEventOnGetValue() {
65
		IObservableValue observable = new ViewerInputObservableValue(Realm
66
		IObservableValue observable = ViewersObservables.observeInput(viewer);
66
				.getDefault(), viewer);
67
		ValueChangeEventTracker listener = ValueChangeEventTracker
67
		ValueChangeEventTracker listener = ValueChangeEventTracker.observe(observable);
68
				.observe(observable);
68
69
69
		assertNull(viewer.getInput());
70
		assertNull(viewer.getInput());
70
		assertEquals(0, listener.count);
71
		assertEquals(0, listener.count);
71
72
72
		viewer.setInput(model);
73
		viewer.setInput(model);
73
74
74
		assertEquals(model, observable.getValue());
75
		assertEquals(model, viewer.getInput());
75
		assertEquals(0, listener.count);
76
		assertEquals(0, listener.count);
76
77
78
		// Call to getValue() causes observable to discover change
79
		assertEquals(model, observable.getValue());
80
		assertEquals(1, listener.count);
81
77
		viewer.setInput(null);
82
		viewer.setInput(null);
83
		assertEquals(null, viewer.getInput());
78
84
79
		assertEquals(null, observable.getValue());
85
		assertEquals(null, observable.getValue());
80
		assertEquals(0, listener.count);
86
		assertEquals(2, listener.count);
81
	}
87
	}
82
88
83
	public void testGetSetValue_FiresChangeEvents() {
89
	public void testGetSetValue_FiresChangeEvents() {
84
		IObservableValue observable = new ViewerInputObservableValue(Realm
90
		IObservableValue observable = ViewersObservables.observeInput(viewer);
85
				.getDefault(), viewer);
86
		ValueChangeEventTracker listener = new ValueChangeEventTracker();
91
		ValueChangeEventTracker listener = new ValueChangeEventTracker();
87
		observable.addValueChangeListener(listener);
92
		observable.addValueChangeListener(listener);
88
93
Lines 103-116 Link Here
103
	}
108
	}
104
109
105
	public void testGetValueType_AlwaysNull() throws Exception {
110
	public void testGetValueType_AlwaysNull() throws Exception {
106
		IObservableValue observable = new ViewerInputObservableValue(Realm
111
		IObservableValue observable = ViewersObservables.observeInput(viewer);
107
				.getDefault(), viewer);
108
		assertEquals(null, observable.getValueType());
112
		assertEquals(null, observable.getValueType());
109
	}
113
	}
110
114
111
	public void testDispose() throws Exception {
115
	public void testDispose() throws Exception {
112
		IObservableValue observable = new ViewerInputObservableValue(Realm
116
		IObservableValue observable = ViewersObservables.observeInput(viewer);
113
				.getDefault(), viewer);
114
		observable.dispose();
117
		observable.dispose();
115
		assertNull(observable.getRealm());
118
		assertNull(observable.getRealm());
116
		try {
119
		try {
Lines 141-147 Link Here
141
	}
144
	}
142
145
143
	public static Test suite() {
146
	public static Test suite() {
144
		TestSuite suite = new TestSuite(ViewerInputObservableValueTest.class.getName());
147
		TestSuite suite = new TestSuite(ViewerInputObservableValueTest.class
148
				.getName());
145
		suite.addTestSuite(ViewerInputObservableValueTest.class);
149
		suite.addTestSuite(ViewerInputObservableValueTest.class);
146
		suite.addTest(MutableObservableValueContractTest.suite(new Delegate()));
150
		suite.addTest(MutableObservableValueContractTest.suite(new Delegate()));
147
		return suite;
151
		return suite;
Lines 165-175 Link Here
165
		}
169
		}
166
170
167
		public IObservableValue createObservableValue(Realm realm) {
171
		public IObservableValue createObservableValue(Realm realm) {
168
			return new ViewerInputObservableValue(realm, viewer);
172
			return ViewerProperties.input().observe(realm, viewer);
169
		}
173
		}
170
174
171
		public void change(IObservable observable) {
175
		public void change(IObservable observable) {
172
			IObservableValue value = (IObservableValue)observable;
176
			IObservableValue value = (IObservableValue) observable;
173
			value.setValue(createValue(value));
177
			value.setValue(createValue(value));
174
		}
178
		}
175
179
(-)src/org/eclipse/jface/tests/internal/databinding/viewers/SelectionProviderMultiSelectionObservableListTest.java (-43 / +46 lines)
Lines 8-22 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *    Brad Reynolds - initial API and implementation
9
 *    Brad Reynolds - initial API and implementation
10
 *     Brad Reynolds - bug 116920
10
 *     Brad Reynolds - bug 116920
11
 *     Matthew Hall - bug 194734
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.jface.tests.internal.databinding.viewers;
13
package org.eclipse.jface.tests.internal.databinding.viewers;
13
14
15
import java.util.ArrayList;
16
import java.util.Arrays;
17
import java.util.Collections;
18
import java.util.List;
19
14
import junit.framework.TestCase;
20
import junit.framework.TestCase;
15
21
16
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
22
import org.eclipse.core.databinding.observable.list.IObservableList;
23
import org.eclipse.core.databinding.observable.list.ListDiff;
17
import org.eclipse.jface.databinding.conformance.util.ListChangeEventTracker;
24
import org.eclipse.jface.databinding.conformance.util.ListChangeEventTracker;
18
import org.eclipse.jface.databinding.swt.SWTObservables;
25
import org.eclipse.jface.databinding.viewers.ViewersObservables;
19
import org.eclipse.jface.internal.databinding.viewers.SelectionProviderMultipleSelectionObservableList;
20
import org.eclipse.jface.viewers.ISelectionProvider;
26
import org.eclipse.jface.viewers.ISelectionProvider;
21
import org.eclipse.jface.viewers.IStructuredContentProvider;
27
import org.eclipse.jface.viewers.IStructuredContentProvider;
22
import org.eclipse.jface.viewers.IStructuredSelection;
28
import org.eclipse.jface.viewers.IStructuredSelection;
Lines 24-30 Link Here
24
import org.eclipse.jface.viewers.TableViewer;
30
import org.eclipse.jface.viewers.TableViewer;
25
import org.eclipse.jface.viewers.Viewer;
31
import org.eclipse.jface.viewers.Viewer;
26
import org.eclipse.swt.SWT;
32
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.widgets.Display;
28
import org.eclipse.swt.widgets.Shell;
33
import org.eclipse.swt.widgets.Shell;
29
34
30
/**
35
/**
Lines 37-43 Link Here
37
42
38
	private TableViewer viewer;
43
	private TableViewer viewer;
39
44
40
	private static String[] model = new String[] { "0", "1", "2", "3" };
45
	private static String[] model = new String[] { "element0", "element1",
46
			"element2", "element3" };
41
47
42
	protected void setUp() throws Exception {
48
	protected void setUp() throws Exception {
43
		Shell shell = new Shell();
49
		Shell shell = new Shell();
Lines 55-62 Link Here
55
61
56
	public void testConstructorIllegalArgumentException() {
62
	public void testConstructorIllegalArgumentException() {
57
		try {
63
		try {
58
			new SelectionProviderMultipleSelectionObservableList(SWTObservables
64
			ViewersObservables.observeMultiSelection(null);
59
					.getRealm(Display.getDefault()), null, Object.class);
60
			fail();
65
			fail();
61
		} catch (IllegalArgumentException e) {
66
		} catch (IllegalArgumentException e) {
62
		}
67
		}
Lines 70-86 Link Here
70
	 * </ul>
75
	 * </ul>
71
	 */
76
	 */
72
	public void testAddRemove() {
77
	public void testAddRemove() {
73
		SelectionProviderMultipleSelectionObservableList observable = new SelectionProviderMultipleSelectionObservableList(
78
		IObservableList observable = ViewersObservables
74
				SWTObservables.getRealm(Display.getDefault()),
79
				.observeMultiSelection(selectionProvider);
75
				selectionProvider, Object.class);
76
		ListChangeEventTracker listener = new ListChangeEventTracker();
80
		ListChangeEventTracker listener = new ListChangeEventTracker();
77
		observable.addListChangeListener(listener);
81
		observable.addListChangeListener(listener);
78
		assertEquals(0, observable.size());
82
		assertEquals(0, observable.size());
79
83
80
		selectionProvider.setSelection(new StructuredSelection(model[0]));
84
		selectionProvider.setSelection(new StructuredSelection(model[0]));
81
		assertEquals(1, listener.count);
85
		assertEquals(1, listener.count);
82
		assertEquals(1, listener.event.diff.getDifferences().length);
86
		assertDiff(listener.event.diff, Collections.EMPTY_LIST, Collections
83
		assertDiffEntry(listener.event.diff.getDifferences()[0], 0, model[0], true);
87
				.singletonList(model[0]));
84
		assertEquals(observable, listener.event.getObservableList());
88
		assertEquals(observable, listener.event.getObservableList());
85
		assertEquals(1, observable.size());
89
		assertEquals(1, observable.size());
86
		assertEquals(model[0], observable.get(0));
90
		assertEquals(model[0], observable.get(0));
Lines 88-155 Link Here
88
		selectionProvider.setSelection(new StructuredSelection(model[1]));
92
		selectionProvider.setSelection(new StructuredSelection(model[1]));
89
		assertEquals(2, listener.count);
93
		assertEquals(2, listener.count);
90
		assertEquals(2, listener.event.diff.getDifferences().length);
94
		assertEquals(2, listener.event.diff.getDifferences().length);
91
		assertDiffEntry(listener.event.diff.getDifferences()[0], 0, model[1], true);
95
		assertDiff(listener.event.diff, Collections.singletonList(model[0]),
92
		assertDiffEntry(listener.event.diff.getDifferences()[1], 1, model[0], false);
96
				Collections.singletonList(model[1]));
93
		assertEquals(observable, listener.event.getObservableList());
97
		assertEquals(observable, listener.event.getObservableList());
94
		assertEquals(1, observable.size());
98
		assertEquals(1, observable.size());
95
		assertEquals(model[1], observable.get(0));
99
		assertEquals(model[1], observable.get(0));
96
100
97
		selectionProvider.setSelection(new StructuredSelection(new Object[]{model[2],model[3]}));
101
		selectionProvider.setSelection(new StructuredSelection(new Object[] {
102
				model[2], model[3] }));
98
		assertEquals(3, listener.count);
103
		assertEquals(3, listener.count);
99
		assertEquals(3, listener.event.diff.getDifferences().length);
104
		assertEquals(3, listener.event.diff.getDifferences().length);
100
		assertDiffEntry(listener.event.diff.getDifferences()[0], 0, model[2], true);
105
		assertDiff(listener.event.diff, Collections.singletonList(model[1]),
101
		assertDiffEntry(listener.event.diff.getDifferences()[1], 1, model[3], true);
106
				Arrays.asList(new Object[] { model[2], model[3] }));
102
		assertDiffEntry(listener.event.diff.getDifferences()[2], 2, model[1], false);
103
		assertEquals(observable, listener.event.getObservableList());
107
		assertEquals(observable, listener.event.getObservableList());
104
		assertEquals(2, observable.size());
108
		assertEquals(2, observable.size());
105
		assertEquals(model[2], observable.get(0));
109
		assertEquals(model[2], observable.get(0));
106
		assertEquals(model[3], observable.get(1));
110
		assertEquals(model[3], observable.get(1));
107
		
111
108
		selectionProvider.setSelection(StructuredSelection.EMPTY);
112
		selectionProvider.setSelection(StructuredSelection.EMPTY);
109
		assertEquals(4, listener.count);
113
		assertEquals(4, listener.count);
110
		assertEquals(2, listener.event.diff.getDifferences().length);
114
		assertEquals(2, listener.event.diff.getDifferences().length);
111
		assertDiffEntry(listener.event.diff.getDifferences()[0], 1, model[3], false);
115
		assertDiff(listener.event.diff, Arrays.asList(new Object[] { model[2],
112
		assertDiffEntry(listener.event.diff.getDifferences()[1], 0, model[2], false);
116
				model[3] }), Collections.EMPTY_LIST);
113
		assertEquals(observable, listener.event.getObservableList());
117
		assertEquals(observable, listener.event.getObservableList());
114
		assertEquals(0, observable.size());
118
		assertEquals(0, observable.size());
115
		
119
116
		observable.add(model[1]);
120
		observable.add(model[1]);
117
		assertEquals(5, listener.count);
121
		assertEquals(5, listener.count);
118
		assertEquals(1, listener.event.diff.getDifferences().length);
122
		assertEquals(1, listener.event.diff.getDifferences().length);
119
		assertDiffEntry(listener.event.diff.getDifferences()[0], 0, model[1], true);
123
		assertDiff(listener.event.diff, Collections.EMPTY_LIST, Collections
124
				.singletonList(model[1]));
120
		assertEquals(observable, listener.event.getObservableList());
125
		assertEquals(observable, listener.event.getObservableList());
121
		assertEquals(1, ((IStructuredSelection)viewer.getSelection()).size());
126
		assertEquals(1, ((IStructuredSelection) viewer.getSelection()).size());
122
127
123
		observable.add(0, model[2]);
128
		observable.add(0, model[2]);
124
		assertEquals(6, listener.count);
129
		assertEquals(6, listener.count);
125
		assertEquals(1, listener.event.diff.getDifferences().length);
130
		assertEquals(1, listener.event.diff.getDifferences().length);
126
		// This is a bit surprising (we added at index 0 but the event says index 1).
131
		// This is a bit surprising (we added at index 0 but the event says
127
		// It is to the fact that the observable list tracks the underlying selection
132
		// index 1).
133
		// It is to the fact that the observable list tracks the underlying
134
		// selection
128
		// provider's notion of which element is at which index.
135
		// provider's notion of which element is at which index.
129
		assertDiffEntry(listener.event.diff.getDifferences()[0], 1, model[2], true);
136
		assertDiff(listener.event.diff, Collections.singletonList(model[1]),
137
				Arrays.asList(new Object[] { model[1], model[2] }));
130
		assertEquals(observable, listener.event.getObservableList());
138
		assertEquals(observable, listener.event.getObservableList());
131
		assertEquals(2, ((IStructuredSelection)viewer.getSelection()).size());
139
		assertEquals(2, ((IStructuredSelection) viewer.getSelection()).size());
132
140
133
		observable.clear();
141
		observable.clear();
134
		assertEquals(7, listener.count);
142
		assertEquals(7, listener.count);
135
		assertEquals(2, listener.event.diff.getDifferences().length);
143
		assertEquals(2, listener.event.diff.getDifferences().length);
136
		assertDiffEntry(listener.event.diff.getDifferences()[0], 1, model[2], false);
144
		assertDiff(listener.event.diff, Arrays.asList(new Object[] { model[1],
137
		assertDiffEntry(listener.event.diff.getDifferences()[1], 0, model[1], false);
145
				model[2] }), Collections.EMPTY_LIST);
138
		assertEquals(observable, listener.event.getObservableList());
146
		assertEquals(observable, listener.event.getObservableList());
139
		assertEquals(0, ((IStructuredSelection)viewer.getSelection()).size());
147
		assertEquals(0, ((IStructuredSelection) viewer.getSelection()).size());
140
}
148
	}
141
149
142
	/**
150
	private void assertDiff(ListDiff diff, List oldList, List newList) {
143
	 * @param diffEntry
151
		// defensive copy in case arg is unmodifiable
144
	 * @param position
152
		oldList = new ArrayList(oldList);
145
	 * @param element
153
		diff.applyTo(oldList);
146
	 * @param isAddition
154
		assertEquals("applying diff to list did not produce expected result",
147
	 */
155
				newList, oldList);
148
	private void assertDiffEntry(ListDiffEntry diffEntry, int position,
149
			String element, boolean isAddition) {
150
		assertEquals(isAddition, diffEntry.isAddition());
151
		assertEquals(position, diffEntry.getPosition());
152
		assertEquals(element, diffEntry.getElement());
153
	}
156
	}
154
157
155
	private class ContentProvider implements IStructuredContentProvider {
158
	private class ContentProvider implements IStructuredContentProvider {
(-)src/org/eclipse/jface/tests/internal/databinding/viewers/SelectionProviderSingleSelectionObservableValueTest.java (-11 / +8 lines)
Lines 9-29 Link Here
9
 *    Brad Reynolds - initial API and implementation
9
 *    Brad Reynolds - initial API and implementation
10
 *    Brad Reynolds - bug 116920
10
 *    Brad Reynolds - bug 116920
11
 *    Ashley Cambrell - bug 198906
11
 *    Ashley Cambrell - bug 198906
12
 *    Matthew Hall - bug 194734
12
 *******************************************************************************/
13
 *******************************************************************************/
13
package org.eclipse.jface.tests.internal.databinding.viewers;
14
package org.eclipse.jface.tests.internal.databinding.viewers;
14
15
15
import junit.framework.TestCase;
16
import junit.framework.TestCase;
16
17
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
17
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
19
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
18
import org.eclipse.jface.databinding.swt.SWTObservables;
20
import org.eclipse.jface.databinding.viewers.ViewersObservables;
19
import org.eclipse.jface.internal.databinding.viewers.SelectionProviderSingleSelectionObservableValue;
20
import org.eclipse.jface.viewers.ISelectionProvider;
21
import org.eclipse.jface.viewers.ISelectionProvider;
21
import org.eclipse.jface.viewers.IStructuredContentProvider;
22
import org.eclipse.jface.viewers.IStructuredContentProvider;
22
import org.eclipse.jface.viewers.StructuredSelection;
23
import org.eclipse.jface.viewers.StructuredSelection;
23
import org.eclipse.jface.viewers.TableViewer;
24
import org.eclipse.jface.viewers.TableViewer;
24
import org.eclipse.jface.viewers.Viewer;
25
import org.eclipse.jface.viewers.Viewer;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Shell;
27
import org.eclipse.swt.widgets.Shell;
28
28
29
/**
29
/**
Lines 65-72 Link Here
65
65
66
	public void testConstructorIllegalArgumentException() {
66
	public void testConstructorIllegalArgumentException() {
67
		try {
67
		try {
68
			new SelectionProviderSingleSelectionObservableValue(SWTObservables
68
			ViewersObservables.observeSingleSelection(null);
69
					.getRealm(Display.getDefault()), null);
70
			fail();
69
			fail();
71
		} catch (IllegalArgumentException e) {
70
		} catch (IllegalArgumentException e) {
72
		}
71
		}
Lines 80-88 Link Here
80
	 * </ul>
79
	 * </ul>
81
	 */
80
	 */
82
	public void testGetSetValue() {
81
	public void testGetSetValue() {
83
		SelectionProviderSingleSelectionObservableValue observable = new SelectionProviderSingleSelectionObservableValue(
82
		IObservableValue observable = ViewersObservables
84
				SWTObservables.getRealm(Display.getDefault()),
83
				.observeSingleSelection(selectionProvider);
85
				selectionProvider);
86
		ValueChangeEventTracker listener = new ValueChangeEventTracker();
84
		ValueChangeEventTracker listener = new ValueChangeEventTracker();
87
		observable.addValueChangeListener(listener);
85
		observable.addValueChangeListener(listener);
88
		assertNull(observable.getValue());
86
		assertNull(observable.getValue());
Lines 110-118 Link Here
110
	}
108
	}
111
109
112
	public void testDispose() throws Exception {
110
	public void testDispose() throws Exception {
113
		SelectionProviderSingleSelectionObservableValue observable = new SelectionProviderSingleSelectionObservableValue(
111
		IObservableValue observable = ViewersObservables
114
				SWTObservables.getRealm(Display.getDefault()),
112
				.observeSingleSelection(selectionProvider);
115
				selectionProvider);
116
		ValueChangeEventTracker listener = new ValueChangeEventTracker();
113
		ValueChangeEventTracker listener = new ValueChangeEventTracker();
117
		observable.addValueChangeListener(listener);
114
		observable.addValueChangeListener(listener);
118
115
(-)src/org/eclipse/core/tests/databinding/conversion/StringToNumberConverterTest.java (-1 / +1 lines)
Lines 112-118 Link Here
112
		assertEquals("Non-integer BigDecimal", input, result);
112
		assertEquals("Non-integer BigDecimal", input, result);
113
113
114
		// Test 2: Long
114
		// Test 2: Long
115
		input = new BigDecimal((long) (Integer.MAX_VALUE + 100));
115
		input = new BigDecimal(Integer.MAX_VALUE + 100L);
116
		result = (BigDecimal) converter.convert(formatBigDecimal(input));
116
		result = (BigDecimal) converter.convert(formatBigDecimal(input));
117
		assertEquals("Integral BigDecimal in long range", input, result);
117
		assertEquals("Integral BigDecimal in long range", input, result);
118
118
(-)src/org/eclipse/jface/tests/internal/databinding/swt/StyledTextObservableValueFocusOutTest.java (+79 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Code 9 Corporation 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
 *     Code 9 Corporation - initial API and implementation
10
 *     Chris Aniszczyk <zx@code9.com> - bug 131435
11
 *     Matthew Hall - bug 194734, 195222
12
 *******************************************************************************/
13
14
package org.eclipse.jface.tests.internal.databinding.swt;
15
16
import junit.framework.Test;
17
import junit.framework.TestCase;
18
import junit.framework.TestSuite;
19
20
import org.eclipse.core.databinding.observable.IObservable;
21
import org.eclipse.core.databinding.observable.Realm;
22
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
24
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.custom.StyledText;
28
import org.eclipse.swt.widgets.Shell;
29
30
/**
31
 * Tests for the FocusOut version of StyledTextObservableValue.
32
 */
33
public class StyledTextObservableValueFocusOutTest extends TestCase {
34
	public static Test suite() {
35
		TestSuite suite = new TestSuite(
36
				StyledTextObservableValueFocusOutTest.class.toString());
37
		suite.addTest(SWTMutableObservableValueContractTest
38
				.suite(new Delegate()));
39
		return suite;
40
	}
41
42
	/* package */static class Delegate extends
43
			AbstractObservableValueContractDelegate {
44
		private Shell shell;
45
46
		private StyledText text;
47
48
		public void setUp() {
49
			shell = new Shell();
50
			text = new StyledText(shell, SWT.NONE);
51
		}
52
53
		public void tearDown() {
54
			shell.dispose();
55
		}
56
57
		public IObservableValue createObservableValue(Realm realm) {
58
			return WidgetProperties.text(SWT.FocusOut).observe(realm, text);
59
		}
60
61
		public Object getValueType(IObservableValue observable) {
62
			return String.class;
63
		}
64
65
		public void change(IObservable observable) {
66
			text.setFocus();
67
68
			IObservableValue observableValue = (IObservableValue) observable;
69
			text.setText((String) createValue(observableValue));
70
71
			text.notifyListeners(SWT.FocusOut, null);
72
		}
73
74
		public Object createValue(IObservableValue observable) {
75
			String value = (String) observable.getValue();
76
			return value + "a";
77
		}
78
	}
79
}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/StyledTextObservableValueTest.java (+112 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Code 9 Corporation 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
 *     Code 9 Corporation - initial API and implementation
10
 *     Chris Aniszczyk <zx@code9.com> - bug 131435
11
 *     Matthew Hall - bug 194734
12
 *******************************************************************************/
13
14
package org.eclipse.jface.tests.internal.databinding.swt;
15
16
import org.eclipse.core.databinding.observable.value.IObservableValue;
17
import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker;
18
import org.eclipse.jface.databinding.swt.SWTObservables;
19
import org.eclipse.jface.internal.databinding.swt.StyledTextTextProperty;
20
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
21
import org.eclipse.swt.SWT;
22
import org.eclipse.swt.custom.StyledText;
23
import org.eclipse.swt.widgets.Shell;
24
25
/**
26
 * Tests to assert the inputs of the StyledTextObservableValue constructor.
27
 */
28
public class StyledTextObservableValueTest extends AbstractDefaultRealmTestCase {
29
	private StyledText text;
30
	private ValueChangeEventTracker listener;
31
32
	protected void setUp() throws Exception {
33
		super.setUp();
34
35
		Shell shell = new Shell();
36
		text = new StyledText(shell, SWT.NONE);
37
38
		listener = new ValueChangeEventTracker();
39
	}
40
41
	/**
42
	 * Asserts that only valid SWT event types are accepted on construction of
43
	 * StyledTextObservableValue.
44
	 */
45
	public void testConstructorUpdateEventTypes() {
46
		try {
47
			new StyledTextTextProperty(SWT.NONE);
48
			new StyledTextTextProperty(SWT.FocusOut);
49
			new StyledTextTextProperty(SWT.Modify);
50
			assertTrue(true);
51
		} catch (IllegalArgumentException e) {
52
			fail();
53
		}
54
55
		try {
56
			new StyledTextTextProperty(SWT.Verify);
57
			fail();
58
		} catch (IllegalArgumentException e) {
59
			assertTrue(true);
60
		}
61
	}
62
63
	/**
64
	 * s
65
	 * 
66
	 * @throws Exception
67
	 */
68
	public void testGetValueBeforeFocusOutChangeEventsFire() throws Exception {
69
		IObservableValue observableValue = SWTObservables.observeText(text,
70
				SWT.FocusOut);
71
		observableValue.addValueChangeListener(listener);
72
73
		String a = "a";
74
		String b = "b";
75
76
		text.setText(a);
77
		
78
		// fetching the value updates the buffered value
79
		assertEquals(a, observableValue.getValue()); 
80
		assertEquals(1, listener.count);
81
82
		text.setText(b);
83
84
		text.notifyListeners(SWT.FocusOut, null);
85
86
		assertEquals(2, listener.count);
87
		assertEquals(a, listener.event.diff.getOldValue());
88
		assertEquals(b, listener.event.diff.getNewValue());
89
	}
90
91
	public void testDispose() throws Exception {
92
		IObservableValue observableValue = SWTObservables.observeText(text,
93
				SWT.Modify);
94
		ValueChangeEventTracker testCounterValueChangeListener = new ValueChangeEventTracker();
95
		observableValue.addValueChangeListener(testCounterValueChangeListener);
96
97
		String expected1 = "Test123";
98
		text.setText(expected1);
99
100
		assertEquals(1, testCounterValueChangeListener.count);
101
		assertEquals(expected1, text.getText());
102
		assertEquals(expected1, observableValue.getValue());
103
104
		observableValue.dispose();
105
106
		String expected2 = "NewValue123";
107
		text.setText(expected2);
108
109
		assertEquals(1, testCounterValueChangeListener.count);
110
		assertEquals(expected2, text.getText());
111
	}
112
}
(-)src/org/eclipse/core/tests/internal/databinding/beans/BeanValuePropertyTest.java (+53 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.tests.internal.databinding.beans;
14
15
import org.eclipse.core.databinding.beans.BeanProperties;
16
import org.eclipse.core.databinding.observable.value.IObservableValue;
17
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
18
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
19
import org.eclipse.core.databinding.property.value.IValueProperty;
20
import org.eclipse.core.tests.internal.databinding.beans.BeanPropertyListenerSupportTest.GenericListenerBean;
21
import org.eclipse.jface.databinding.conformance.util.CurrentRealm;
22
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
23
24
/**
25
 * @since 3.2
26
 * 
27
 */
28
public class BeanValuePropertyTest extends AbstractDefaultRealmTestCase {
29
	public void testChangeListenerIsOnlyNotifiedWhenWatchedPropertyChanges()
30
			throws Exception {
31
		GenericListenerBean bean = new GenericListenerBean();
32
		IValueProperty property = BeanProperties
33
				.value(GenericListenerBean.class, "value");
34
		class Listener implements IValueChangeListener {
35
			private int count = 0;
36
37
			public void handleValueChange(ValueChangeEvent event) {
38
				count++;
39
			}
40
		}
41
		Listener listener = new Listener();
42
43
		IObservableValue observable = property.observe(new CurrentRealm(true), bean);
44
		observable.addValueChangeListener(listener);
45
46
		assertEquals(0, listener.count);
47
		bean.setValue("1");
48
		assertEquals(1, listener.count);
49
50
		bean.setOther("2");
51
		assertEquals(1, listener.count);
52
	}
53
}
(-)src/org/eclipse/jface/tests/internal/databinding/swt/StyledTextObservableValueModifyTest.java (+77 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Code 9 Corporation 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
 *     Code 9 Corporation - initial API and implementation
10
 *     Chris Aniszczyk <zx@code9.com> - bug 131435
11
 *     Matthew Hall - bug 194734, 195222
12
 *******************************************************************************/
13
14
package org.eclipse.jface.tests.internal.databinding.swt;
15
16
import junit.framework.Test;
17
import junit.framework.TestCase;
18
import junit.framework.TestSuite;
19
20
import org.eclipse.core.databinding.observable.IObservable;
21
import org.eclipse.core.databinding.observable.Realm;
22
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate;
24
import org.eclipse.jface.databinding.conformance.swt.SWTMutableObservableValueContractTest;
25
import org.eclipse.jface.databinding.swt.WidgetProperties;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.custom.StyledText;
28
import org.eclipse.swt.widgets.Shell;
29
30
/**
31
 * Tests for the Modify version of StyledTextObservableValue.
32
 */
33
public class StyledTextObservableValueModifyTest extends TestCase {
34
	public static Test suite() {
35
		TestSuite suite = new TestSuite(
36
				StyledTextObservableValueModifyTest.class.toString());
37
		suite.addTest(SWTMutableObservableValueContractTest
38
				.suite(new Delegate()));
39
		return suite;
40
	}
41
42
	/* package */static class Delegate extends
43
			AbstractObservableValueContractDelegate {
44
		private Shell shell;
45
46
		private StyledText text;
47
48
		public void setUp() {
49
			shell = new Shell();
50
			text = new StyledText(shell, SWT.NONE);
51
		}
52
53
		public void tearDown() {
54
			shell.dispose();
55
		}
56
57
		public IObservableValue createObservableValue(Realm realm) {
58
			return WidgetProperties.text(SWT.Modify).observe(realm, text);
59
		}
60
61
		public Object getValueType(IObservableValue observable) {
62
			return String.class;
63
		}
64
65
		public void change(IObservable observable) {
66
			text.setFocus();
67
68
			IObservableValue observableValue = (IObservableValue) observable;
69
			text.setText((String) createValue(observableValue));
70
		}
71
72
		public Object createValue(IObservableValue observable) {
73
			String value = (String) observable.getValue();
74
			return value + "a";
75
		}
76
	}
77
}
(-)src/org/eclipse/core/tests/internal/databinding/beans/BeanPropertyListenerSupportTest.java (+208 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.core.tests.internal.databinding.beans;
13
14
import java.beans.PropertyChangeEvent;
15
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyChangeSupport;
17
18
import org.eclipse.core.databinding.util.ILogger;
19
import org.eclipse.core.databinding.util.Policy;
20
import org.eclipse.core.internal.databinding.beans.BeanPropertyListenerSupport;
21
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase;
23
24
/**
25
 * @since 1.1
26
 */
27
public class BeanPropertyListenerSupportTest extends
28
		AbstractDefaultRealmTestCase {
29
	private PropertyChangeListenerStub listener;
30
	private String propertyName;
31
32
	protected void setUp() throws Exception {
33
		super.setUp();
34
35
		listener = new PropertyChangeListenerStub();
36
		propertyName = "value";
37
	}
38
39
	public void testAddPropertyChangeListenerWithPropertyName()
40
			throws Exception {
41
		SpecificListenerBean bean = new SpecificListenerBean();
42
43
		assertFalse(bean.changeSupport.hasListeners(propertyName));
44
45
		BeanPropertyListenerSupport.hookListener(bean, propertyName, listener);
46
		assertTrue("has listeners", bean.changeSupport
47
				.hasListeners(propertyName));
48
	}
49
50
	public void testAddPropertyChangeListenerWithoutPropertyName()
51
			throws Exception {
52
		GenericListenerBean bean = new GenericListenerBean();
53
54
		assertFalse(bean.changeSupport.hasListeners(propertyName));
55
56
		BeanPropertyListenerSupport.hookListener(bean, propertyName, listener);
57
		assertTrue("has listeners", bean.changeSupport
58
				.hasListeners(propertyName));
59
	}
60
61
	public void testLogStatusWhenAddPropertyChangeListenerMethodIsNotFound()
62
			throws Exception {
63
		class BeanStub {
64
		}
65
66
		class Log implements ILogger {
67
			int count;
68
			IStatus status;
69
70
			public void log(IStatus status) {
71
				count++;
72
				this.status = status;
73
			}
74
		}
75
76
		Log log = new Log();
77
		Policy.setLog(log);
78
79
		BeanStub bean = new BeanStub();
80
81
		assertEquals(0, log.count);
82
		BeanPropertyListenerSupport.hookListener(bean, "value", listener);
83
		assertEquals(1, log.count);
84
		assertEquals(IStatus.WARNING, log.status.getSeverity());
85
	}
86
87
	public void testRemovePropertyChangeListenerWithPropertyName()
88
			throws Exception {
89
		SpecificListenerBean bean = new SpecificListenerBean();
90
		BeanPropertyListenerSupport.hookListener(bean, propertyName, listener);
91
92
		assertTrue(bean.changeSupport.hasListeners(propertyName));
93
94
		BeanPropertyListenerSupport
95
				.unhookListener(bean, propertyName, listener);
96
		assertFalse("has listeners", bean.changeSupport
97
				.hasListeners(propertyName));
98
	}
99
100
	public void testRemovePropertyChangeListenerWithoutPropertyName()
101
			throws Exception {
102
		GenericListenerBean bean = new GenericListenerBean();
103
		BeanPropertyListenerSupport.hookListener(bean, propertyName, listener);
104
105
		assertTrue(bean.changeSupport.hasListeners(propertyName));
106
107
		BeanPropertyListenerSupport
108
				.unhookListener(bean, propertyName, listener);
109
		assertFalse("has listeners", bean.changeSupport
110
				.hasListeners(propertyName));
111
	}
112
113
	public void testLogStatusWhenRemovePropertyChangeListenerMethodIsNotFound()
114
			throws Exception {
115
		class InvalidBean {
116
		}
117
118
		class Log implements ILogger {
119
			int count;
120
			IStatus status;
121
122
			public void log(IStatus status) {
123
				count++;
124
				this.status = status;
125
			}
126
		}
127
128
		Log log = new Log();
129
		Policy.setLog(log);
130
131
		InvalidBean bean = new InvalidBean();
132
133
		BeanPropertyListenerSupport.hookListener(bean, "value", listener);
134
		log.count = 0;
135
		log.status = null;
136
		assertEquals(0, log.count);
137
		BeanPropertyListenerSupport.unhookListener(bean, "value", listener);
138
		assertEquals(1, log.count);
139
		assertEquals(IStatus.WARNING, log.status.getSeverity());
140
	}
141
142
	static class GenericListenerBean {
143
		private String other;
144
		PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
145
		private String value;
146
147
		public String getValue() {
148
			return value;
149
		}
150
151
		public void setValue(String value) {
152
			changeSupport.firePropertyChange("value", this.value,
153
					this.value = value);
154
		}
155
156
		public String getOther() {
157
			return other;
158
		}
159
160
		public void setOther(String other) {
161
			changeSupport.firePropertyChange("other", this.other,
162
					this.other = other);
163
		}
164
165
		public void addPropertyChangeListener(PropertyChangeListener listener) {
166
			changeSupport.addPropertyChangeListener(listener);
167
		}
168
169
		public void removePropertyChangeListener(PropertyChangeListener listener) {
170
			changeSupport.removePropertyChangeListener(listener);
171
		}
172
	}
173
174
	static class SpecificListenerBean {
175
		PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
176
		String propertyName;
177
		String value;
178
179
		public void addPropertyChangeListener(String name,
180
				PropertyChangeListener listener) {
181
			this.propertyName = name;
182
			changeSupport.addPropertyChangeListener(name, listener);
183
		}
184
185
		public void removePropertyChangeListener(String name,
186
				PropertyChangeListener listener) {
187
			changeSupport.removePropertyChangeListener(name, listener);
188
		}
189
190
		public String getValue() {
191
			return value;
192
		}
193
194
		public void setValue(String value) {
195
			this.value = value;
196
		}
197
	}
198
199
	static class PropertyChangeListenerStub implements PropertyChangeListener {
200
		PropertyChangeEvent event;
201
		int count;
202
203
		public void propertyChange(PropertyChangeEvent evt) {
204
			count++;
205
			this.event = evt;
206
		}
207
	}
208
}
(-)src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java (-28 / +4 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 208332
10
 *     Matthew Hall - bug 208332, 194734
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.core.databinding.observable.set;
13
package org.eclipse.core.databinding.observable.set;
Lines 17-23 Link Here
17
import java.util.Set;
17
import java.util.Set;
18
18
19
import org.eclipse.core.databinding.observable.AbstractObservable;
19
import org.eclipse.core.databinding.observable.AbstractObservable;
20
import org.eclipse.core.databinding.observable.ChangeSupport;
21
import org.eclipse.core.databinding.observable.ObservableTracker;
20
import org.eclipse.core.databinding.observable.ObservableTracker;
22
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.core.databinding.observable.Realm;
23
22
Lines 36-43 Link Here
36
public abstract class AbstractObservableSet extends AbstractObservable implements
35
public abstract class AbstractObservableSet extends AbstractObservable implements
37
		IObservableSet {
36
		IObservableSet {
38
37
39
	private ChangeSupport changeSupport;
40
41
	private boolean stale = false;
38
	private boolean stale = false;
42
39
43
	protected AbstractObservableSet() {
40
	protected AbstractObservableSet() {
Lines 54-75 Link Here
54
	
51
	
55
	protected AbstractObservableSet(Realm realm) {
52
	protected AbstractObservableSet(Realm realm) {
56
		super(realm);
53
		super(realm);
57
		changeSupport = new ChangeSupport(realm){
58
			protected void firstListenerAdded() {
59
				AbstractObservableSet.this.firstListenerAdded();
60
			}
61
			protected void lastListenerRemoved() {
62
				AbstractObservableSet.this.lastListenerRemoved();
63
			}
64
		};
65
	}
54
	}
66
	
55
	
67
	public synchronized void addSetChangeListener(ISetChangeListener listener) {
56
	public synchronized void addSetChangeListener(ISetChangeListener listener) {
68
		changeSupport.addListener(SetChangeEvent.TYPE, listener);
57
		addListener(SetChangeEvent.TYPE, listener);
69
	}
58
	}
70
59
71
	public synchronized void removeSetChangeListener(ISetChangeListener listener) {
60
	public synchronized void removeSetChangeListener(ISetChangeListener listener) {
72
		changeSupport.removeListener(SetChangeEvent.TYPE, listener);
61
		removeListener(SetChangeEvent.TYPE, listener);
73
	}
62
	}
74
63
75
	protected abstract Set getWrappedSet();
64
	protected abstract Set getWrappedSet();
Lines 78-84 Link Here
78
		// fire general change event first
67
		// fire general change event first
79
		super.fireChange();
68
		super.fireChange();
80
69
81
		changeSupport.fireEvent(new SetChangeEvent(this, diff));
70
		fireEvent(new SetChangeEvent(this, diff));
82
	}
71
	}
83
	
72
	
84
	public boolean contains(Object o) {
73
	public boolean contains(Object o) {
Lines 202-218 Link Here
202
	protected void fireChange() {
191
	protected void fireChange() {
203
		throw new RuntimeException("fireChange should not be called, use fireSetChange() instead"); //$NON-NLS-1$
192
		throw new RuntimeException("fireChange should not be called, use fireSetChange() instead"); //$NON-NLS-1$
204
	}
193
	}
205
	
206
	/* (non-Javadoc)
207
	 * @see org.eclipse.jface.provisional.databinding.observable.AbstractObservable#dispose()
208
	 */
209
	public synchronized void dispose() {
210
		super.dispose();
211
		
212
		if (changeSupport != null) {
213
			changeSupport.dispose();
214
			changeSupport = null;
215
		}
216
	}
217
	
218
}
194
}
(-)src/org/eclipse/core/databinding/observable/set/SetDiff.java (-2 / +4 lines)
Lines 7-24 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 251884
10
 *     Matthew Hall - bugs 251884, 194734
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.core.databinding.observable.set;
13
package org.eclipse.core.databinding.observable.set;
14
14
15
import java.util.Set;
15
import java.util.Set;
16
16
17
import org.eclipse.core.databinding.observable.IDiff;
18
17
/**
19
/**
18
 * @since 1.0
20
 * @since 1.0
19
 *
21
 *
20
 */
22
 */
21
public abstract class SetDiff {
23
public abstract class SetDiff implements IDiff {
22
	
24
	
23
	/**
25
	/**
24
	 * @return the set of added elements
26
	 * @return the set of added elements
(-)src/org/eclipse/core/databinding/observable/map/ComputedObservableMap.java (-1 / +15 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bugs 241585, 247394, 226289
10
 *     Matthew Hall - bugs 241585, 247394, 226289, 194734
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.core.databinding.observable.map;
13
package org.eclipse.core.databinding.observable.map;
Lines 21-26 Link Here
21
import java.util.Set;
21
import java.util.Set;
22
22
23
import org.eclipse.core.databinding.observable.Diffs;
23
import org.eclipse.core.databinding.observable.Diffs;
24
import org.eclipse.core.databinding.observable.IStaleListener;
25
import org.eclipse.core.databinding.observable.StaleEvent;
24
import org.eclipse.core.databinding.observable.set.IObservableSet;
26
import org.eclipse.core.databinding.observable.set.IObservableSet;
25
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
27
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
26
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
28
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
Lines 60-65 Link Here
60
		}
62
		}
61
	};
63
	};
62
64
65
	private IStaleListener staleListener = new IStaleListener() {
66
		public void handleStale(StaleEvent staleEvent) {
67
			fireStale();
68
		}
69
	};
70
63
	private Set entrySet = new EntrySet();
71
	private Set entrySet = new EntrySet();
64
72
65
	private class EntrySet extends AbstractSet {
73
	private class EntrySet extends AbstractSet {
Lines 137-142 Link Here
137
	private void hookListeners() {
145
	private void hookListeners() {
138
		if (keySet != null) {
146
		if (keySet != null) {
139
			keySet.addSetChangeListener(setChangeListener);
147
			keySet.addSetChangeListener(setChangeListener);
148
			keySet.addStaleListener(staleListener);
140
			for (Iterator it = this.keySet.iterator(); it.hasNext();) {
149
			for (Iterator it = this.keySet.iterator(); it.hasNext();) {
141
				Object key = it.next();
150
				Object key = it.next();
142
				hookListener(key);
151
				hookListener(key);
Lines 147-152 Link Here
147
	private void unhookListeners() {
156
	private void unhookListeners() {
148
		if (keySet != null) {
157
		if (keySet != null) {
149
			keySet.removeSetChangeListener(setChangeListener);
158
			keySet.removeSetChangeListener(setChangeListener);
159
			keySet.removeStaleListener(staleListener);
150
			Object[] keys = keySet.toArray();
160
			Object[] keys = keySet.toArray();
151
			for (int i = 0; i < keys.length; i++) {
161
			for (int i = 0; i < keys.length; i++) {
152
				unhookListener(keys[i]);
162
				unhookListener(keys[i]);
Lines 210-215 Link Here
210
	 */
220
	 */
211
	protected abstract Object doPut(Object key, Object value);
221
	protected abstract Object doPut(Object key, Object value);
212
222
223
	public boolean isStale() {
224
		return super.isStale() || keySet.isStale();
225
	}
226
213
	public synchronized void dispose() {
227
	public synchronized void dispose() {
214
		unhookListeners();
228
		unhookListeners();
215
		entrySet = null;
229
		entrySet = null;
(-)src/org/eclipse/core/databinding/observable/map/MapDiff.java (-2 / +4 lines)
Lines 7-13 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 251884
10
 *     Matthew Hall - bugs 251884, 194734
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.core.databinding.observable.map;
13
package org.eclipse.core.databinding.observable.map;
Lines 16-26 Link Here
16
import java.util.Map;
16
import java.util.Map;
17
import java.util.Set;
17
import java.util.Set;
18
18
19
import org.eclipse.core.databinding.observable.IDiff;
20
19
/**
21
/**
20
 * @since 1.1
22
 * @since 1.1
21
 * 
23
 * 
22
 */
24
 */
23
public abstract class MapDiff {
25
public abstract class MapDiff implements IDiff {
24
	/**
26
	/**
25
	 * Returns true if the diff has no added, removed or changed entries.
27
	 * Returns true if the diff has no added, removed or changed entries.
26
	 * 
28
	 * 
(-)src/org/eclipse/core/databinding/observable/value/ValueDiff.java (-1 / +3 lines)
Lines 7-23 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 194734
10
 *******************************************************************************/
11
 *******************************************************************************/
11
12
12
package org.eclipse.core.databinding.observable.value;
13
package org.eclipse.core.databinding.observable.value;
13
14
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.Diffs;
16
import org.eclipse.core.databinding.observable.IDiff;
15
17
16
/**
18
/**
17
 * @since 1.0
19
 * @since 1.0
18
 * 
20
 * 
19
 */
21
 */
20
public abstract class ValueDiff {
22
public abstract class ValueDiff implements IDiff {
21
	/**
23
	/**
22
	 * Creates a value diff.
24
	 * Creates a value diff.
23
	 */
25
	 */
(-)src/org/eclipse/core/databinding/observable/list/AbstractObservableList.java (-9 / +29 lines)
Lines 43-50 Link Here
43
 */
43
 */
44
public abstract class AbstractObservableList extends AbstractList implements
44
public abstract class AbstractObservableList extends AbstractList implements
45
		IObservableList {
45
		IObservableList {
46
	private final class PrivateChangeSupport extends ChangeSupport {
47
		private PrivateChangeSupport(Realm realm) {
48
			super(realm);
49
		}
50
51
		protected void firstListenerAdded() {
52
			AbstractObservableList.this.firstListenerAdded();
53
		}
54
55
		protected void lastListenerRemoved() {
56
			AbstractObservableList.this.lastListenerRemoved();
57
		}
46
58
47
	private ChangeSupport changeSupport;
59
		protected boolean hasListeners() {
60
			return super.hasListeners();
61
		}
62
	}
63
64
	private PrivateChangeSupport changeSupport;
48
	private boolean disposed = false;
65
	private boolean disposed = false;
49
66
50
	/**
67
	/**
Lines 54-67 Link Here
54
	public AbstractObservableList(Realm realm) {
71
	public AbstractObservableList(Realm realm) {
55
		Assert.isNotNull(realm, "Realm cannot be null"); //$NON-NLS-1$
72
		Assert.isNotNull(realm, "Realm cannot be null"); //$NON-NLS-1$
56
		ObservableTracker.observableCreated(this);
73
		ObservableTracker.observableCreated(this);
57
		changeSupport = new ChangeSupport(realm){
74
		changeSupport = new PrivateChangeSupport(realm);
58
			protected void firstListenerAdded() {
59
				AbstractObservableList.this.firstListenerAdded();
60
			}
61
			protected void lastListenerRemoved() {
62
				AbstractObservableList.this.lastListenerRemoved();
63
			}
64
		};
65
	}
75
	}
66
76
67
	/**
77
	/**
Lines 71-76 Link Here
71
		this(Realm.getDefault());
81
		this(Realm.getDefault());
72
	}
82
	}
73
	
83
	
84
	/**
85
	 * Returns whether this observable list has any registered listeners.
86
	 * 
87
	 * @return whether this observable list has any registered listeners.
88
	 * @since 1.2
89
	 */
90
	protected boolean hasListeners() {
91
		return changeSupport.hasListeners();
92
	}
93
74
	public boolean isStale() {
94
	public boolean isStale() {
75
		getterCalled();
95
		getterCalled();
76
		return false;
96
		return false;
(-)src/org/eclipse/core/databinding/observable/list/ListDiff.java (-2 / +3 lines)
Lines 7-19 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 208858, 251884
10
 *     Matthew Hall - bugs 208858, 251884, 194734
11
 *******************************************************************************/
11
 *******************************************************************************/
12
12
13
package org.eclipse.core.databinding.observable.list;
13
package org.eclipse.core.databinding.observable.list;
14
14
15
import java.util.List;
15
import java.util.List;
16
16
17
import org.eclipse.core.databinding.observable.IDiff;
17
import org.eclipse.core.internal.databinding.Util;
18
import org.eclipse.core.internal.databinding.Util;
18
19
19
/**
20
/**
Lines 21-27 Link Here
21
 * 
22
 * 
22
 * @since 1.0
23
 * @since 1.0
23
 */
24
 */
24
public abstract class ListDiff {
25
public abstract class ListDiff implements IDiff {
25
26
26
	/**
27
	/**
27
	 * Returns a ListDiffEntry array representing the differences in the list,
28
	 * Returns a ListDiffEntry array representing the differences in the list,
(-)META-INF/MANIFEST.MF (+6 lines)
Lines 14-19 Link Here
14
 org.eclipse.core.databinding.observable.masterdetail,
14
 org.eclipse.core.databinding.observable.masterdetail,
15
 org.eclipse.core.databinding.observable.set;x-internal:=false,
15
 org.eclipse.core.databinding.observable.set;x-internal:=false,
16
 org.eclipse.core.databinding.observable.value;x-internal:=false,
16
 org.eclipse.core.databinding.observable.value;x-internal:=false,
17
 org.eclipse.core.databinding.property,
18
 org.eclipse.core.databinding.property.list,
19
 org.eclipse.core.databinding.property.map,
20
 org.eclipse.core.databinding.property.set,
21
 org.eclipse.core.databinding.property.value,
17
 org.eclipse.core.databinding.util,
22
 org.eclipse.core.databinding.util,
18
 org.eclipse.core.databinding.validation;x-internal:=false,
23
 org.eclipse.core.databinding.validation;x-internal:=false,
19
 org.eclipse.core.internal.databinding;x-friends:="org.eclipse.core.databinding.beans",
24
 org.eclipse.core.internal.databinding;x-friends:="org.eclipse.core.databinding.beans",
Lines 21-26 Link Here
21
 org.eclipse.core.internal.databinding.observable;x-internal:=true,
26
 org.eclipse.core.internal.databinding.observable;x-internal:=true,
22
 org.eclipse.core.internal.databinding.observable.masterdetail;x-friends:="org.eclipse.jface.tests.databinding",
27
 org.eclipse.core.internal.databinding.observable.masterdetail;x-friends:="org.eclipse.jface.tests.databinding",
23
 org.eclipse.core.internal.databinding.observable.tree;x-friends:="org.eclipse.jface.databinding,org.eclipse.jface.tests.databinding",
28
 org.eclipse.core.internal.databinding.observable.tree;x-friends:="org.eclipse.jface.databinding,org.eclipse.jface.tests.databinding",
29
 org.eclipse.core.internal.databinding.property;x-friends:="org.eclipse.jface.databinding,org.eclipse.jface.tests.databinding",
24
 org.eclipse.core.internal.databinding.validation;x-friends:="org.eclipse.jface.tests.databinding"
30
 org.eclipse.core.internal.databinding.validation;x-friends:="org.eclipse.jface.tests.databinding"
25
Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.2.0,4.0.0)"
31
Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.2.0,4.0.0)"
26
Import-Package-Comment: see http://wiki.eclipse.org/
32
Import-Package-Comment: see http://wiki.eclipse.org/
(-)src/org/eclipse/core/internal/databinding/property/set/SimpleSetPropertyObservableSet.java (+408 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.set;
13
14
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.ConcurrentModificationException;
17
import java.util.HashSet;
18
import java.util.Iterator;
19
import java.util.Set;
20
21
import org.eclipse.core.databinding.observable.Diffs;
22
import org.eclipse.core.databinding.observable.Realm;
23
import org.eclipse.core.databinding.observable.set.AbstractObservableSet;
24
import org.eclipse.core.databinding.observable.set.SetDiff;
25
import org.eclipse.core.databinding.property.INativePropertyListener;
26
import org.eclipse.core.databinding.property.IProperty;
27
import org.eclipse.core.databinding.property.IPropertyObservable;
28
import org.eclipse.core.databinding.property.ISimplePropertyListener;
29
import org.eclipse.core.databinding.property.SimplePropertyEvent;
30
import org.eclipse.core.databinding.property.set.SimpleSetProperty;
31
32
/**
33
 * @since 1.2
34
 * 
35
 */
36
public class SimpleSetPropertyObservableSet extends AbstractObservableSet
37
		implements IPropertyObservable {
38
	private Object source;
39
	private SimpleSetProperty property;
40
41
	private volatile boolean updating = false;
42
43
	private volatile int modCount = 0;
44
45
	private INativePropertyListener listener;
46
47
	private Set cachedSet;
48
49
	/**
50
	 * @param realm
51
	 * @param source
52
	 * @param property
53
	 */
54
	public SimpleSetPropertyObservableSet(Realm realm, Object source,
55
			SimpleSetProperty property) {
56
		super(realm);
57
		this.source = source;
58
		this.property = property;
59
	}
60
61
	protected void firstListenerAdded() {
62
		if (!isDisposed()) {
63
			cachedSet = getSet();
64
65
			if (listener == null) {
66
				listener = property
67
						.adaptListener(new ISimplePropertyListener() {
68
							public void handlePropertyChange(
69
									final SimplePropertyEvent event) {
70
								modCount++;
71
								if (!isDisposed() && !updating) {
72
									getRealm().exec(new Runnable() {
73
										public void run() {
74
											notifyIfChanged((SetDiff) event.diff);
75
										}
76
									});
77
								}
78
							}
79
						});
80
			}
81
			property.addListener(source, listener);
82
		}
83
	}
84
85
	protected void lastListenerRemoved() {
86
		if (listener != null) {
87
			property.removeListener(source, listener);
88
		}
89
90
		cachedSet = null;
91
	}
92
93
	protected Set getWrappedSet() {
94
		return getSet();
95
	}
96
97
	public Object getElementType() {
98
		return property.getElementType();
99
	}
100
101
	// Queries
102
103
	private Set getSet() {
104
		return property.getSet(source);
105
	}
106
107
	public boolean contains(Object o) {
108
		getterCalled();
109
		return getSet().contains(o);
110
	}
111
112
	public boolean containsAll(Collection c) {
113
		getterCalled();
114
		return getSet().containsAll(c);
115
	}
116
117
	public boolean isEmpty() {
118
		getterCalled();
119
		return getSet().isEmpty();
120
	}
121
122
	public Object[] toArray() {
123
		getterCalled();
124
		return getSet().toArray();
125
	}
126
127
	public Object[] toArray(Object[] a) {
128
		getterCalled();
129
		return getSet().toArray(a);
130
	}
131
132
	// Single change operations
133
134
	public boolean add(Object o) {
135
		checkRealm();
136
137
		Set set = new HashSet(getSet());
138
		if (!set.add(o))
139
			return false;
140
141
		SetDiff diff = Diffs.createSetDiff(Collections.singleton(o),
142
				Collections.EMPTY_SET);
143
144
		boolean wasUpdating = updating;
145
		updating = true;
146
		try {
147
			property.setSet(source, set, diff);
148
			modCount++;
149
		} finally {
150
			updating = wasUpdating;
151
		}
152
153
		notifyIfChanged(null);
154
155
		return true;
156
	}
157
158
	public Iterator iterator() {
159
		getterCalled();
160
		return new Iterator() {
161
			int expectedModCount = modCount;
162
			Set set = new HashSet(getSet());
163
			Iterator iterator = set.iterator();
164
			Object last = null;
165
166
			public boolean hasNext() {
167
				getterCalled();
168
				checkForComodification();
169
				return iterator.hasNext();
170
			}
171
172
			public Object next() {
173
				getterCalled();
174
				checkForComodification();
175
				last = iterator.next();
176
				return last;
177
			}
178
179
			public void remove() {
180
				checkRealm();
181
				checkForComodification();
182
183
				iterator.remove(); // stay in sync
184
				SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET,
185
						Collections.singleton(last));
186
187
				boolean wasUpdating = updating;
188
				updating = true;
189
				try {
190
					property.setSet(source, set, diff);
191
					modCount++;
192
				} finally {
193
					updating = wasUpdating;
194
				}
195
196
				notifyIfChanged(null);
197
198
				last = null;
199
				expectedModCount = modCount;
200
			}
201
202
			private void checkForComodification() {
203
				if (expectedModCount != modCount)
204
					throw new ConcurrentModificationException();
205
			}
206
		};
207
	}
208
209
	public boolean remove(Object o) {
210
		getterCalled();
211
212
		Set set = new HashSet(getSet());
213
		if (!set.remove(o))
214
			return false;
215
216
		SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, Collections
217
				.singleton(o));
218
219
		boolean wasUpdating = updating;
220
		updating = true;
221
		try {
222
			property.setSet(source, set, diff);
223
			modCount++;
224
		} finally {
225
			updating = wasUpdating;
226
		}
227
228
		notifyIfChanged(null);
229
230
		return true;
231
	}
232
233
	// Bulk change operations
234
235
	public boolean addAll(Collection c) {
236
		getterCalled();
237
238
		if (c.isEmpty())
239
			return false;
240
241
		Set set = new HashSet(getSet());
242
243
		Set additions = new HashSet(c);
244
		for (Iterator it = c.iterator(); it.hasNext();) {
245
			Object element = it.next();
246
			if (set.add(element))
247
				additions.add(element);
248
		}
249
250
		if (additions.isEmpty())
251
			return false;
252
253
		SetDiff diff = Diffs.createSetDiff(additions, Collections.EMPTY_SET);
254
255
		boolean wasUpdating = updating;
256
		updating = true;
257
		try {
258
			property.setSet(source, set, diff);
259
			modCount++;
260
		} finally {
261
			updating = wasUpdating;
262
		}
263
264
		notifyIfChanged(null);
265
266
		return true;
267
	}
268
269
	public boolean removeAll(Collection c) {
270
		getterCalled();
271
272
		Set set = getSet();
273
		if (set.isEmpty())
274
			return false;
275
		if (c.isEmpty())
276
			return false;
277
278
		set = new HashSet(set);
279
280
		Set removals = new HashSet(c);
281
		for (Iterator it = c.iterator(); it.hasNext();) {
282
			Object element = it.next();
283
			if (set.remove(element))
284
				removals.add(element);
285
		}
286
287
		if (removals.isEmpty())
288
			return false;
289
290
		SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals);
291
292
		boolean wasUpdating = updating;
293
		updating = true;
294
		try {
295
			property.setSet(source, set, diff);
296
			modCount++;
297
		} finally {
298
			updating = wasUpdating;
299
		}
300
301
		notifyIfChanged(null);
302
303
		return true;
304
	}
305
306
	public boolean retainAll(Collection c) {
307
		getterCalled();
308
309
		Set set = getSet();
310
		if (set.isEmpty())
311
			return false;
312
313
		if (c.isEmpty()) {
314
			clear();
315
			return true;
316
		}
317
318
		set = new HashSet(set);
319
320
		Set removals = new HashSet();
321
		for (Iterator it = set.iterator(); it.hasNext();) {
322
			Object element = it.next();
323
			if (!c.contains(element)) {
324
				it.remove();
325
				removals.add(element);
326
			}
327
		}
328
329
		if (removals.isEmpty())
330
			return false;
331
332
		SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals);
333
334
		boolean wasUpdating = updating;
335
		updating = true;
336
		try {
337
			property.setSet(source, set, diff);
338
			modCount++;
339
		} finally {
340
			updating = wasUpdating;
341
		}
342
343
		notifyIfChanged(null);
344
345
		return true;
346
	}
347
348
	public void clear() {
349
		getterCalled();
350
351
		Set set = getSet();
352
		if (set.isEmpty())
353
			return;
354
355
		SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, set);
356
357
		boolean wasUpdating = updating;
358
		updating = true;
359
		try {
360
			property.setSet(source, Collections.EMPTY_SET, diff);
361
			modCount++;
362
		} finally {
363
			updating = wasUpdating;
364
		}
365
366
		notifyIfChanged(null);
367
	}
368
369
	private void notifyIfChanged(SetDiff diff) {
370
		if (hasListeners()) {
371
			Set oldSet = cachedSet;
372
			Set newSet = cachedSet = property.getSet(source);
373
			if (diff == null)
374
				diff = Diffs.computeSetDiff(oldSet, newSet);
375
			if (!diff.isEmpty())
376
				fireSetChange(diff);
377
		}
378
	}
379
380
	public boolean equals(Object o) {
381
		getterCalled();
382
		return getSet().equals(o);
383
	}
384
385
	public int hashCode() {
386
		getterCalled();
387
		return getSet().hashCode();
388
	}
389
390
	public Object getObserved() {
391
		return source;
392
	}
393
394
	public IProperty getProperty() {
395
		return property;
396
	}
397
398
	public synchronized void dispose() {
399
		if (!isDisposed()) {
400
			if (listener != null)
401
				property.removeListener(source, listener);
402
			property = null;
403
			source = null;
404
			listener = null;
405
		}
406
		super.dispose();
407
	}
408
}
(-)src/org/eclipse/core/databinding/property/value/IValueProperty.java (+189 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.value;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
17
import org.eclipse.core.databinding.observable.map.IObservableMap;
18
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
19
import org.eclipse.core.databinding.observable.set.IObservableSet;
20
import org.eclipse.core.databinding.observable.value.IObservableValue;
21
import org.eclipse.core.databinding.property.IProperty;
22
import org.eclipse.core.databinding.property.list.IListProperty;
23
import org.eclipse.core.databinding.property.map.IMapProperty;
24
import org.eclipse.core.databinding.property.set.ISetProperty;
25
26
/**
27
 * Interface for value-typed properties
28
 * 
29
 * @since 1.2
30
 * @noimplement This interface is not intended to be implemented by clients.
31
 *              Clients should instead subclass one of the classes that
32
 *              implement this interface. Note that direct implementers of this
33
 *              interface outside of the framework will be broken in future
34
 *              releases when methods are added to this interface.
35
 * @see ValueProperty
36
 * @see SimpleValueProperty
37
 */
38
public interface IValueProperty extends IProperty {
39
	/**
40
	 * Returns the value type of the property, or <code>null</code> if untyped.
41
	 * 
42
	 * @return the value type of the property, or <code>null</code> if untyped.
43
	 */
44
	public Object getValueType();
45
46
	/**
47
	 * Returns an observable value observing this value property on the given
48
	 * property source.
49
	 * 
50
	 * @param source
51
	 *            the property source
52
	 * @return an observable value observing this value property on the given
53
	 *         property source
54
	 */
55
	public IObservableValue observe(Object source);
56
57
	/**
58
	 * Returns an observable value observing this value property on the given
59
	 * property source
60
	 * 
61
	 * @param realm
62
	 *            the observable's realm
63
	 * @param source
64
	 *            the property source
65
	 * @return an observable value observing this value property on the given
66
	 *         property source
67
	 */
68
	public IObservableValue observe(Realm realm, Object source);
69
70
	/**
71
	 * Returns a factory for creating observable values tracking this property
72
	 * of a particular property source.
73
	 * 
74
	 * @return a factory for creating observable values tracking this property
75
	 *         of a particular property source.
76
	 */
77
	public IObservableFactory valueFactory();
78
79
	/**
80
	 * Returns a factory for creating observable values in the given realm,
81
	 * tracking this property of a particular property source.
82
	 * 
83
	 * @param realm
84
	 *            the realm
85
	 * 
86
	 * @return a factory for creating observable values in the given realm,
87
	 *         tracking this property of a particular property source.
88
	 */
89
	public IObservableFactory valueFactory(Realm realm);
90
91
	/**
92
	 * Returns an observable value on the master observable's realm which tracks
93
	 * this property on the current value of <code>master</code>.
94
	 * 
95
	 * @param master
96
	 *            the master observable
97
	 * @return an observable value which tracks this property of the current
98
	 *         value of <code>master</code>.
99
	 */
100
	public IObservableValue observeDetail(IObservableValue master);
101
102
	/**
103
	 * Returns an observable list on the master observable's realm which tracks
104
	 * this property on each element of <code>master</code>.
105
	 * 
106
	 * @param master
107
	 *            the master observable
108
	 * @return an observable list which tracks this property on each element of
109
	 *         the master observable.
110
	 */
111
	public IObservableList observeDetail(IObservableList master);
112
113
	/**
114
	 * Returns an observable map on the master observable's realm where the
115
	 * map's key set is the specified master set, and where each key maps to the
116
	 * current property value for each element.
117
	 * 
118
	 * @param master
119
	 *            the master observable
120
	 * @return an observable map that tracks the current value of this property
121
	 *         for the elements in the given set.
122
	 */
123
	public IObservableMap observeDetail(IObservableSet master);
124
125
	/**
126
	 * Returns an observable map on the master observable's realm where the
127
	 * map's key set is the same as the master observable map, and where each
128
	 * value is the property value of the corresponding value in the master
129
	 * observable map.
130
	 * 
131
	 * @param master
132
	 *            the master observable
133
	 * @return an observable map on the master observable's realm which tracks
134
	 *         the current value of this property for the elements in the given
135
	 *         map's values collection
136
	 */
137
	public IObservableMap observeDetail(IObservableMap master);
138
139
	/**
140
	 * Returns the nested combination of this property and the specified detail
141
	 * value property. Value modifications made through the returned property
142
	 * are delegated to the detail property, using the value of this property as
143
	 * the source.
144
	 * 
145
	 * @param detailValue
146
	 *            the detail property
147
	 * @return the nested combination of the master and detail properties
148
	 */
149
	public IValueProperty value(IValueProperty detailValue);
150
151
	/**
152
	 * Returns the nested combination of this property and the specified detail
153
	 * list property. List modifications made through the returned property are
154
	 * delegated to the detail property, using the value of the master property
155
	 * as the source.
156
	 * 
157
	 * @param detailList
158
	 *            the detail property
159
	 * @return the nested combination of the master value and detail list
160
	 *         properties
161
	 */
162
	public IListProperty list(IListProperty detailList);
163
164
	/**
165
	 * Returns the nested combination of this property and the specified detail
166
	 * set property. Set modifications made through the returned property are
167
	 * delegated to the detail property, using the value of the master property
168
	 * as the source.
169
	 * 
170
	 * @param detailSet
171
	 *            the detail property
172
	 * @return the nested combination of the master value and detail set
173
	 *         properties
174
	 */
175
	public ISetProperty set(ISetProperty detailSet);
176
177
	/**
178
	 * Returns the nested combination of this property and the specified detail
179
	 * map property. Map modifications made through the returned property are
180
	 * delegated to the detail property, using the value of the master property
181
	 * as the source.
182
	 * 
183
	 * @param detailMap
184
	 *            the detail property
185
	 * @return the nested combination of the master value and detial map
186
	 *         properties
187
	 */
188
	public IMapProperty map(IMapProperty detailMap);
189
}
(-)src/org/eclipse/core/internal/databinding/property/value/ObservableSetDelegatingValuePropertyObservableMap.java (+241 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.value;
13
14
import java.util.AbstractSet;
15
import java.util.Collections;
16
import java.util.HashMap;
17
import java.util.Iterator;
18
import java.util.Map;
19
import java.util.Set;
20
21
import org.eclipse.core.databinding.observable.Diffs;
22
import org.eclipse.core.databinding.observable.IStaleListener;
23
import org.eclipse.core.databinding.observable.ObservableTracker;
24
import org.eclipse.core.databinding.observable.StaleEvent;
25
import org.eclipse.core.databinding.observable.map.AbstractObservableMap;
26
import org.eclipse.core.databinding.observable.map.MapDiff;
27
import org.eclipse.core.databinding.observable.set.IObservableSet;
28
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
29
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
30
import org.eclipse.core.databinding.observable.set.SetDiff;
31
import org.eclipse.core.databinding.property.IProperty;
32
import org.eclipse.core.databinding.property.IPropertyObservable;
33
import org.eclipse.core.databinding.property.value.DelegatingValueProperty;
34
import org.eclipse.core.internal.databinding.Util;
35
36
/**
37
 * @since 1.2
38
 */
39
public class ObservableSetDelegatingValuePropertyObservableMap extends
40
		AbstractObservableMap implements IPropertyObservable {
41
	private IObservableSet masterSet;
42
	private DelegatingValueProperty detailProperty;
43
	private DelegatingCache cache;
44
45
	private Set entrySet;
46
47
	class EntrySet extends AbstractSet {
48
		public Iterator iterator() {
49
			return new Iterator() {
50
				final Iterator it = masterSet.iterator();
51
52
				public boolean hasNext() {
53
					return it.hasNext();
54
				}
55
56
				public Object next() {
57
					return new MapEntry(it.next());
58
				}
59
60
				public void remove() {
61
					it.remove();
62
				}
63
			};
64
		}
65
66
		public int size() {
67
			return masterSet.size();
68
		}
69
	}
70
71
	class MapEntry implements Map.Entry {
72
		private final Object key;
73
74
		MapEntry(Object key) {
75
			this.key = key;
76
		}
77
78
		public Object getKey() {
79
			getterCalled();
80
			return key;
81
		}
82
83
		public Object getValue() {
84
			getterCalled();
85
86
			if (!masterSet.contains(key))
87
				return null;
88
89
			return cache.get(key);
90
		}
91
92
		public Object setValue(Object value) {
93
			checkRealm();
94
95
			if (!masterSet.contains(key))
96
				return null;
97
98
			return cache.put(key, value);
99
		}
100
101
		public boolean equals(Object o) {
102
			getterCalled();
103
			if (o == this)
104
				return true;
105
			if (o == null)
106
				return false;
107
			if (!(o instanceof Map.Entry))
108
				return false;
109
			Map.Entry that = (Map.Entry) o;
110
			return Util.equals(this.getKey(), that.getKey())
111
					&& Util.equals(this.getValue(), that.getValue());
112
		}
113
114
		public int hashCode() {
115
			getterCalled();
116
			Object value = getValue();
117
			return (key == null ? 0 : key.hashCode())
118
					^ (value == null ? 0 : value.hashCode());
119
		}
120
	}
121
122
	private ISetChangeListener masterListener = new ISetChangeListener() {
123
		public void handleSetChange(SetChangeEvent event) {
124
			if (isDisposed())
125
				return;
126
127
			cache.addAll(masterSet);
128
129
			// Need both obsolete and new elements to convert diff
130
			MapDiff diff = convertDiff(event.diff);
131
132
			cache.retainAll(masterSet);
133
134
			fireMapChange(diff);
135
		}
136
137
		private MapDiff convertDiff(SetDiff diff) {
138
			// Convert diff to detail value
139
			Map oldValues = new HashMap();
140
			Map newValues = new HashMap();
141
142
			for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) {
143
				Object masterElement = it.next();
144
				oldValues.put(masterElement, cache.get(masterElement));
145
			}
146
			for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) {
147
				Object masterElement = it.next();
148
				newValues.put(masterElement, cache.get(masterElement));
149
			}
150
			return Diffs.createMapDiff(diff.getAdditions(), diff.getRemovals(),
151
					Collections.EMPTY_SET, oldValues, newValues);
152
		}
153
	};
154
155
	private IStaleListener staleListener = new IStaleListener() {
156
		public void handleStale(StaleEvent staleEvent) {
157
			fireStale();
158
		}
159
	};
160
161
	/**
162
	 * @param keySet
163
	 * @param valueProperty
164
	 */
165
	public ObservableSetDelegatingValuePropertyObservableMap(
166
			IObservableSet keySet, DelegatingValueProperty valueProperty) {
167
		super(keySet.getRealm());
168
		this.masterSet = keySet;
169
		this.detailProperty = valueProperty;
170
		this.cache = new DelegatingCache(getRealm(), valueProperty) {
171
			void handleValueChange(Object masterElement, Object oldValue,
172
					Object newValue) {
173
				fireMapChange(Diffs.createMapDiffSingleChange(masterElement,
174
						oldValue, newValue));
175
			}
176
		};
177
		cache.addAll(masterSet);
178
179
		masterSet.addSetChangeListener(masterListener);
180
		masterSet.addStaleListener(staleListener);
181
	}
182
183
	public Set entrySet() {
184
		getterCalled();
185
		if (entrySet == null)
186
			entrySet = new EntrySet();
187
		return entrySet;
188
	}
189
190
	private void getterCalled() {
191
		ObservableTracker.getterCalled(this);
192
	}
193
194
	public Object get(Object key) {
195
		getterCalled();
196
		return cache.get(key);
197
	}
198
199
	public Object put(Object key, Object value) {
200
		checkRealm();
201
		return cache.put(key, value);
202
	}
203
204
	public boolean isStale() {
205
		return masterSet.isStale();
206
	}
207
208
	public Object getObserved() {
209
		return masterSet;
210
	}
211
212
	public IProperty getProperty() {
213
		return detailProperty;
214
	}
215
216
	public Object getKeyType() {
217
		return masterSet.getElementType();
218
	}
219
220
	public Object getValueType() {
221
		return detailProperty.getValueType();
222
	}
223
224
	public synchronized void dispose() {
225
		if (masterSet != null) {
226
			masterSet.removeSetChangeListener(masterListener);
227
			masterSet.removeStaleListener(staleListener);
228
			masterSet = null;
229
		}
230
231
		if (cache != null) {
232
			cache.dispose();
233
			cache = null;
234
		}
235
236
		masterListener = null;
237
		detailProperty = null;
238
239
		super.dispose();
240
	}
241
}
(-)src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java (+195 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 *     Matthew Hall - bug 195222, 247997
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.set;
14
15
import java.util.Collections;
16
import java.util.Set;
17
18
import org.eclipse.core.databinding.observable.Realm;
19
import org.eclipse.core.databinding.observable.set.IObservableSet;
20
import org.eclipse.core.databinding.observable.set.SetDiff;
21
import org.eclipse.core.databinding.property.INativePropertyListener;
22
import org.eclipse.core.databinding.property.ISimplePropertyListener;
23
import org.eclipse.core.internal.databinding.property.set.SimpleSetPropertyObservableSet;
24
25
/**
26
 * Simplified abstract implementation of ISetProperty. This class takes care of
27
 * most of the functional requirements for an ISetProperty implementation,
28
 * leaving only the property-specific details to subclasses.
29
 * <p>
30
 * Subclasses must implement these methods:
31
 * <ul>
32
 * <li> {@link #getElementType()}
33
 * <li> {@link #doGetSet(Object)}
34
 * <li> {@link #doSetSet(Object, Set, SetDiff)}
35
 * <li> {@link #adaptListener(ISimplePropertyListener)}
36
 * <li> {@link #doAddListener(Object, INativePropertyListener)}
37
 * <li> {@link #doRemoveListener(Object, INativePropertyListener)}
38
 * </ul>
39
 * <p>
40
 * In addition, we recommended overriding {@link #toString()} to return a
41
 * description suitable for debugging purposes.
42
 * 
43
 * @since 1.2
44
 */
45
public abstract class SimpleSetProperty extends SetProperty {
46
	public IObservableSet observe(Realm realm, Object source) {
47
		return new SimpleSetPropertyObservableSet(realm, source, this);
48
	}
49
50
	// Accessors
51
52
	/**
53
	 * Returns a Set with the current contents of the source's set property
54
	 * 
55
	 * @param source
56
	 *            the property source
57
	 * @return a Set with the current contents of the source's set property
58
	 * @noreference This method is not intended to be referenced by clients.
59
	 */
60
	public final Set getSet(Object source) {
61
		if (source == null)
62
			return Collections.EMPTY_SET;
63
		return Collections.unmodifiableSet(doGetSet(source));
64
	}
65
66
	/**
67
	 * Returns an unmodifiable Set with the current contents of the source's set
68
	 * property
69
	 * 
70
	 * @param source
71
	 *            the property source
72
	 * @return an unmodifiable Set with the current contents of the source's set
73
	 *         property
74
	 * @noreference This method is not intended to be referenced by clients.
75
	 */
76
	protected abstract Set doGetSet(Object source);
77
78
	// Mutators
79
80
	/**
81
	 * Updates the property on the source with the specified change.
82
	 * 
83
	 * @param source
84
	 *            the property source
85
	 * @param set
86
	 *            the new set
87
	 * @param diff
88
	 *            a diff describing the change
89
	 * @noreference This method is not intended to be referenced by clients.
90
	 */
91
	public final void setSet(Object source, Set set, SetDiff diff) {
92
		if (source != null && !diff.isEmpty())
93
			doSetSet(source, set, diff);
94
	}
95
96
	/**
97
	 * Updates the property on the source with the specified change.
98
	 * 
99
	 * @param source
100
	 *            the property source
101
	 * @param set
102
	 *            the new set
103
	 * @param diff
104
	 *            a diff describing the change
105
	 * @noreference This method is not intended to be referenced by clients.
106
	 */
107
	protected abstract void doSetSet(Object source, Set set, SetDiff diff);
108
109
	// Listeners
110
111
	/**
112
	 * Returns a listener which implements the correct listener interface for
113
	 * the expected source object, and which parlays property change events from
114
	 * the source object to the given listener. If there is no listener API for
115
	 * this property, this method returns null.
116
	 * 
117
	 * @param listener
118
	 *            the property listener to receive events
119
	 * @return a native listener which parlays property change events to the
120
	 *         specified listener.
121
	 * @noreference This method is not intended to be referenced by clients.
122
	 */
123
	public abstract INativePropertyListener adaptListener(
124
			ISimplePropertyListener listener);
125
126
	/**
127
	 * Adds the specified listener as a listener for this property on the
128
	 * specified property source. If the source object has no listener API for
129
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
130
	 * returns null), this method does nothing.
131
	 * 
132
	 * @param source
133
	 *            the property source
134
	 * @param listener
135
	 *            a listener obtained from calling
136
	 *            {@link #adaptListener(ISimplePropertyListener)}.
137
	 * @noreference This method is not intended to be referenced by clients.
138
	 */
139
	public final void addListener(Object source,
140
			INativePropertyListener listener) {
141
		if (source != null)
142
			doAddListener(source, listener);
143
	}
144
145
	/**
146
	 * Adds the specified listener as a listener for this property on the
147
	 * specified property source. If the source object has no listener API for
148
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
149
	 * returns null), this method does nothing.
150
	 * 
151
	 * @param source
152
	 *            the property source
153
	 * @param listener
154
	 *            a listener obtained from calling
155
	 *            {@link #adaptListener(ISimplePropertyListener)}.
156
	 * @noreference This method is not intended to be referenced by clients.
157
	 */
158
	protected abstract void doAddListener(Object source,
159
			INativePropertyListener listener);
160
161
	/**
162
	 * Removes the specified listener as a listener for this property on the
163
	 * specified property source. If the source object has no listener API for
164
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
165
	 * returns null), this method does nothing.
166
	 * 
167
	 * @param source
168
	 *            the property source
169
	 * @param listener
170
	 *            a listener obtained from calling
171
	 *            {@link #adaptListener(ISimplePropertyListener)}.
172
	 * @noreference This method is not intended to be referenced by clients.
173
	 */
174
	public final void removeListener(Object source,
175
			INativePropertyListener listener) {
176
		if (source != null)
177
			doRemoveListener(source, listener);
178
	}
179
180
	/**
181
	 * Removes the specified listener as a listener for this property on the
182
	 * specified property source. If the source object has no listener API for
183
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
184
	 * returns null), this method does nothing.
185
	 * 
186
	 * @param source
187
	 *            the property source
188
	 * @param listener
189
	 *            a listener obtained from calling
190
	 *            {@link #adaptListener(ISimplePropertyListener)} .
191
	 * @noreference This method is not intended to be referenced by clients.
192
	 */
193
	protected abstract void doRemoveListener(Object source,
194
			INativePropertyListener listener);
195
}
(-)src/org/eclipse/core/databinding/property/list/IListProperty.java (+114 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.list;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
17
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.core.databinding.property.IProperty;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
22
/**
23
 * Interface for list-typed properties.
24
 * 
25
 * @since 1.2
26
 * @noimplement This interface is not intended to be implemented by clients.
27
 *              Clients should instead subclass one of the classes that
28
 *              implement this interface. Note that direct implementers of this
29
 *              interface outside of the framework will be broken in future
30
 *              releases when methods are added to this interface.
31
 * @see ListProperty
32
 * @see SimpleListProperty
33
 */
34
public interface IListProperty extends IProperty {
35
	/**
36
	 * Returns the type of the elements in the collection or <code>null</code>
37
	 * if untyped
38
	 * 
39
	 * @return the type of the elements in the collection or <code>null</code>
40
	 *         if untyped
41
	 */
42
	public Object getElementType();
43
44
	/**
45
	 * Returns an observable list observing this list property on the given
46
	 * property source
47
	 * 
48
	 * @param source
49
	 *            the property source
50
	 * @return an observable list observing this list property on the given
51
	 *         property source
52
	 */
53
	public IObservableList observe(Object source);
54
55
	/**
56
	 * Returns an observable list observing this list property on the given
57
	 * property source
58
	 * 
59
	 * @param realm
60
	 *            the observable's realm
61
	 * @param source
62
	 *            the property source
63
	 * @return an observable list observing this list property on the given
64
	 *         property source
65
	 */
66
	public IObservableList observe(Realm realm, Object source);
67
68
	/**
69
	 * Returns a factory for creating observable lists tracking this property of
70
	 * a particular property source.
71
	 * 
72
	 * @return a factory for creating observable lists tracking this property of
73
	 *         a particular property source.
74
	 */
75
	public IObservableFactory listFactory();
76
77
	/**
78
	 * Returns a factory for creating observable lists in the given realm,
79
	 * tracking this property of a particular property source.
80
	 * 
81
	 * @param realm
82
	 *            the realm
83
	 * 
84
	 * @return a factory for creating observable lists in the given realm,
85
	 *         tracking this property of a particular property source.
86
	 */
87
	public IObservableFactory listFactory(Realm realm);
88
89
	/**
90
	 * Returns an observable list on the master observable's realm which tracks
91
	 * this property of the current value of <code>master</code>.
92
	 * 
93
	 * @param master
94
	 *            the master observable
95
	 * @return an observable list on the given realm which tracks this property
96
	 *         of the current value of <code>master</code>.
97
	 */
98
	public IObservableList observeDetail(IObservableValue master);
99
100
	/**
101
	 * Returns the nested combination of this property and the specified detail
102
	 * value property. Note that because this property is a projection of value
103
	 * properties over a list, the only modification supported is through the
104
	 * {@link IObservableList#set(int, Object)} method. Modifications made
105
	 * through the returned property are delegated to the detail property, using
106
	 * the corresponding list element from the master property as the source.
107
	 * 
108
	 * @param detailValue
109
	 *            the detail property
110
	 * @return the nested combination of the master list and detail value
111
	 *         properties
112
	 */
113
	public IListProperty values(IValueProperty detailValue);
114
}
(-)src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailValue.java (+86 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.property;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
17
import org.eclipse.core.databinding.observable.map.IObservableMap;
18
import org.eclipse.core.databinding.observable.set.IObservableSet;
19
import org.eclipse.core.databinding.observable.value.IObservableValue;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
import org.eclipse.core.databinding.property.value.ValueProperty;
22
23
/**
24
 * @since 1.2
25
 * 
26
 */
27
public class ValuePropertyDetailValue extends ValueProperty implements
28
		IValueProperty {
29
	private IValueProperty masterProperty;
30
	private IValueProperty detailProperty;
31
32
	/**
33
	 * @param masterProperty
34
	 * @param detailProperty
35
	 */
36
	public ValuePropertyDetailValue(IValueProperty masterProperty,
37
			IValueProperty detailProperty) {
38
		this.masterProperty = masterProperty;
39
		this.detailProperty = detailProperty;
40
	}
41
42
	public Object getValueType() {
43
		return detailProperty.getValueType();
44
	}
45
46
	public IObservableValue observe(Realm realm, Object source) {
47
		IObservableValue masterValue = masterProperty.observe(realm, source);
48
		IObservableValue detailValue = detailProperty
49
				.observeDetail(masterValue);
50
		PropertyObservableUtil.cascadeDispose(detailValue, masterValue);
51
		return detailValue;
52
	}
53
54
	public IObservableValue observeDetail(IObservableValue master) {
55
		IObservableValue masterValue = masterProperty.observeDetail(master);
56
		IObservableValue detailValue = detailProperty
57
				.observeDetail(masterValue);
58
		PropertyObservableUtil.cascadeDispose(detailValue, masterValue);
59
		return detailValue;
60
	}
61
62
	public IObservableList observeDetail(IObservableList master) {
63
		IObservableList masterList = masterProperty.observeDetail(master);
64
		IObservableList detailList = detailProperty.observeDetail(masterList);
65
		PropertyObservableUtil.cascadeDispose(detailList, masterList);
66
		return detailList;
67
	}
68
69
	public IObservableMap observeDetail(IObservableSet master) {
70
		IObservableMap masterMap = masterProperty.observeDetail(master);
71
		IObservableMap detailMap = detailProperty.observeDetail(masterMap);
72
		PropertyObservableUtil.cascadeDispose(detailMap, masterMap);
73
		return detailMap;
74
	}
75
76
	public IObservableMap observeDetail(IObservableMap master) {
77
		IObservableMap masterMap = masterProperty.observeDetail(master);
78
		IObservableMap detailMap = detailProperty.observeDetail(masterMap);
79
		PropertyObservableUtil.cascadeDispose(detailMap, masterMap);
80
		return detailMap;
81
	}
82
83
	public String toString() {
84
		return masterProperty + " => " + detailProperty; //$NON-NLS-1$
85
	}
86
}
(-)src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailSet.java (+61 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.property;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.set.IObservableSet;
17
import org.eclipse.core.databinding.observable.value.IObservableValue;
18
import org.eclipse.core.databinding.property.set.ISetProperty;
19
import org.eclipse.core.databinding.property.set.SetProperty;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class ValuePropertyDetailSet extends SetProperty {
27
	private IValueProperty masterProperty;
28
	private ISetProperty detailProperty;
29
30
	/**
31
	 * @param masterProperty
32
	 * @param detailProperty
33
	 */
34
	public ValuePropertyDetailSet(IValueProperty masterProperty,
35
			ISetProperty detailProperty) {
36
		this.masterProperty = masterProperty;
37
		this.detailProperty = detailProperty;
38
	}
39
40
	public Object getElementType() {
41
		return detailProperty.getElementType();
42
	}
43
44
	public IObservableSet observe(Realm realm, Object source) {
45
		IObservableValue masterValue = masterProperty.observe(realm, source);
46
		IObservableSet detailSet = detailProperty.observeDetail(masterValue);
47
		PropertyObservableUtil.cascadeDispose(detailSet, masterValue);
48
		return detailSet;
49
	}
50
51
	public IObservableSet observeDetail(IObservableValue master) {
52
		IObservableValue masterValue = masterProperty.observeDetail(master);
53
		IObservableSet detailSet = detailProperty.observeDetail(masterValue);
54
		PropertyObservableUtil.cascadeDispose(detailSet, masterValue);
55
		return detailSet;
56
	}
57
58
	public String toString() {
59
		return masterProperty + " => " + detailProperty; //$NON-NLS-1$
60
	}
61
}
(-)src/org/eclipse/core/databinding/property/value/ValueProperty.java (+74 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.value;
14
15
import org.eclipse.core.databinding.observable.IObservable;
16
import org.eclipse.core.databinding.observable.Realm;
17
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
18
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
19
import org.eclipse.core.databinding.observable.value.IObservableValue;
20
import org.eclipse.core.databinding.property.list.IListProperty;
21
import org.eclipse.core.databinding.property.map.IMapProperty;
22
import org.eclipse.core.databinding.property.set.ISetProperty;
23
import org.eclipse.core.internal.databinding.property.ValuePropertyDetailList;
24
import org.eclipse.core.internal.databinding.property.ValuePropertyDetailMap;
25
import org.eclipse.core.internal.databinding.property.ValuePropertyDetailSet;
26
import org.eclipse.core.internal.databinding.property.ValuePropertyDetailValue;
27
28
/**
29
 * Abstract implementation of IValueProperty
30
 * 
31
 * @since 1.2
32
 */
33
public abstract class ValueProperty implements IValueProperty {
34
	public IObservableValue observe(Object source) {
35
		return observe(Realm.getDefault(), source);
36
	}
37
38
	public IObservableFactory valueFactory() {
39
		return new IObservableFactory() {
40
			public IObservable createObservable(Object target) {
41
				return observe(target);
42
			}
43
		};
44
	}
45
46
	public IObservableFactory valueFactory(final Realm realm) {
47
		return new IObservableFactory() {
48
			public IObservable createObservable(Object target) {
49
				return observe(realm, target);
50
			}
51
		};
52
	}
53
54
	public IObservableValue observeDetail(IObservableValue master) {
55
		return MasterDetailObservables.detailValue(master, valueFactory(master
56
				.getRealm()), getValueType());
57
	}
58
59
	public final IValueProperty value(IValueProperty detailValue) {
60
		return new ValuePropertyDetailValue(this, detailValue);
61
	}
62
63
	public final IListProperty list(IListProperty detailList) {
64
		return new ValuePropertyDetailList(this, detailList);
65
	}
66
67
	public final ISetProperty set(ISetProperty detailSet) {
68
		return new ValuePropertyDetailSet(this, detailSet);
69
	}
70
71
	public final IMapProperty map(IMapProperty detailMap) {
72
		return new ValuePropertyDetailMap(this, detailMap);
73
	}
74
}
(-)src/org/eclipse/core/databinding/property/Properties.java (+71 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property;
14
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.observable.map.IObservableMap;
18
import org.eclipse.core.databinding.observable.set.IObservableSet;
19
import org.eclipse.core.databinding.property.value.IValueProperty;
20
21
/**
22
 * Contains static methods to operate on or return IProperty objects.
23
 * 
24
 * @since 1.2
25
 */
26
public class Properties {
27
	/**
28
	 * Returns an array of observable maps where each map observes the
29
	 * corresponding value property on all elements in the given domain set, for
30
	 * each property in the given array.
31
	 * 
32
	 * @param domainSet
33
	 *            the set of elements whose properties will be observed
34
	 * @param properties
35
	 *            array of value properties to observe on each element in the
36
	 *            domain set.
37
	 * @return an array of observable maps where each map observes the
38
	 *         corresponding value property of the given domain set.
39
	 */
40
	public static IObservableMap[] observeEach(IObservableSet domainSet,
41
			IValueProperty[] properties) {
42
		IObservableMap[] maps = new IObservableMap[properties.length];
43
		for (int i = 0; i < maps.length; i++)
44
			maps[i] = properties[i].observeDetail(domainSet);
45
		return maps;
46
	}
47
48
	/**
49
	 * Returns an array of observable maps where each maps observes the
50
	 * corresponding value property on all elements in the given domain map's
51
	 * {@link Map#values() values} collection, for each property in the given
52
	 * array.
53
	 * 
54
	 * @param domainMap
55
	 *            the map of elements whose properties will be observed
56
	 * @param properties
57
	 *            array of value properties to observe on each element in the
58
	 *            domain map's {@link Map#values() values} collection.
59
	 * @return an array of observable maps where each maps observes the
60
	 *         corresponding value property on all elements in the given domain
61
	 *         map's {@link Map#values() values} collection, for each property
62
	 *         in the given array.
63
	 */
64
	public static IObservableMap[] observeEach(IObservableMap domainMap,
65
			IValueProperty[] properties) {
66
		IObservableMap[] maps = new IObservableMap[properties.length];
67
		for (int i = 0; i < maps.length; i++)
68
			maps[i] = properties[i].observeDetail(domainMap);
69
		return maps;
70
	}
71
}
(-)src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java (+210 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.value;
13
14
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.HashMap;
17
import java.util.HashSet;
18
import java.util.Iterator;
19
import java.util.Map;
20
import java.util.Set;
21
22
import org.eclipse.core.databinding.observable.Realm;
23
import org.eclipse.core.databinding.observable.map.IMapChangeListener;
24
import org.eclipse.core.databinding.observable.map.IObservableMap;
25
import org.eclipse.core.databinding.observable.map.MapChangeEvent;
26
import org.eclipse.core.databinding.observable.set.IObservableSet;
27
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
28
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
29
import org.eclipse.core.databinding.observable.set.WritableSet;
30
import org.eclipse.core.databinding.property.value.DelegatingValueProperty;
31
import org.eclipse.core.databinding.property.value.IValueProperty;
32
import org.eclipse.core.internal.databinding.IdentityWrapper;
33
import org.eclipse.core.internal.databinding.Util;
34
35
/**
36
 * @since 3.3
37
 * 
38
 */
39
abstract class DelegatingCache {
40
	private Realm realm;
41
	private DelegatingValueProperty detailProperty;
42
	private IObservableSet elements;
43
	private Map delegateCaches;
44
45
	private class DelegateCache implements IMapChangeListener {
46
		private final IValueProperty delegate;
47
		private final IObservableSet masterElements;
48
		private final IObservableMap masterElementValues;
49
		private final Map cachedValues;
50
51
		DelegateCache(IValueProperty delegate) {
52
			this.delegate = delegate;
53
			this.masterElements = new WritableSet(realm, Collections.EMPTY_SET,
54
					elements.getElementType());
55
			this.masterElementValues = delegate.observeDetail(masterElements);
56
			this.cachedValues = new HashMap();
57
58
			masterElementValues.addMapChangeListener(this);
59
		}
60
61
		void add(Object masterElement) {
62
			boolean wasEmpty = masterElements.isEmpty();
63
64
			masterElements.add(masterElement);
65
			cachedValues.put(new IdentityWrapper(masterElement),
66
					masterElementValues.get(masterElement));
67
68
			if (wasEmpty)
69
				delegateCaches.put(delegate, this);
70
		}
71
72
		void remove(Object masterElement) {
73
			cachedValues.remove(new IdentityWrapper(masterElement));
74
			masterElements.remove(masterElement);
75
			if (cachedValues.isEmpty())
76
				dispose();
77
		}
78
79
		Object get(Object masterElement) {
80
			return cachedValues.get(new IdentityWrapper(masterElement));
81
		}
82
83
		Object put(Object masterElement, Object detailValue) {
84
			Object oldValue = masterElementValues.put(masterElement,
85
					detailValue);
86
			notifyIfChanged(masterElement);
87
			return oldValue;
88
		}
89
90
		boolean containsValue(Object detailValue) {
91
			return cachedValues.containsValue(detailValue);
92
		}
93
94
		public void handleMapChange(MapChangeEvent event) {
95
			Set changedKeys = event.diff.getChangedKeys();
96
			for (Iterator it = changedKeys.iterator(); it.hasNext();)
97
				notifyIfChanged(it.next());
98
		}
99
100
		private void notifyIfChanged(Object masterElement) {
101
			Object oldValue = cachedValues.get(new IdentityWrapper(
102
					masterElement));
103
			Object newValue = masterElementValues.get(masterElement);
104
			if (!Util.equals(oldValue, newValue)) {
105
				cachedValues.put(new IdentityWrapper(masterElement), newValue);
106
				handleValueChange(masterElement, oldValue, newValue);
107
			}
108
		}
109
110
		void handleValueChange(Object masterElement, Object oldValue,
111
				Object newValue) {
112
			DelegatingCache.this.handleValueChange(masterElement, oldValue,
113
					newValue);
114
		}
115
116
		void dispose() {
117
			delegateCaches.remove(delegate);
118
			masterElementValues.dispose();
119
			masterElements.dispose();
120
			cachedValues.clear();
121
		}
122
	}
123
124
	DelegatingCache(Realm realm, DelegatingValueProperty detailProperty) {
125
		this.realm = realm;
126
		this.detailProperty = detailProperty;
127
128
		this.elements = new WritableSet(realm);
129
		this.delegateCaches = new HashMap();
130
131
		elements.addSetChangeListener(new ISetChangeListener() {
132
			public void handleSetChange(SetChangeEvent event) {
133
				for (Iterator it = event.diff.getRemovals().iterator(); it
134
						.hasNext();) {
135
					IdentityWrapper wrapper = (IdentityWrapper) it.next();
136
					Object element = wrapper.unwrap();
137
					getCache(element).remove(element);
138
139
				}
140
				for (Iterator it = event.diff.getAdditions().iterator(); it
141
						.hasNext();) {
142
					IdentityWrapper wrapper = (IdentityWrapper) it.next();
143
					Object element = wrapper.unwrap();
144
					getCache(element).add(element);
145
				}
146
			}
147
		});
148
	}
149
150
	private DelegateCache getCache(Object masterElement) {
151
		IValueProperty delegate = detailProperty.getDelegate(masterElement);
152
		if (delegateCaches.containsKey(delegate)) {
153
			return (DelegateCache) delegateCaches.get(delegate);
154
		}
155
		return new DelegateCache(delegate);
156
	}
157
158
	Object get(Object element) {
159
		return getCache(element).get(element);
160
	}
161
162
	Object put(Object element, Object value) {
163
		return getCache(element).put(element, value);
164
	}
165
166
	boolean contains(Object value) {
167
		for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) {
168
			DelegateCache cache = (DelegateCache) it.next();
169
			if (cache.containsValue(value))
170
				return true;
171
		}
172
		return false;
173
	}
174
175
	private Set identitySet(Collection elements) {
176
		Set result = new HashSet();
177
		for (Iterator it = elements.iterator(); it.hasNext();) {
178
			result.add(new IdentityWrapper(it.next()));
179
		}
180
		return result;
181
	}
182
183
	void addAll(Collection elements) {
184
		this.elements.addAll(identitySet(elements));
185
	}
186
187
	void retainAll(Collection elements) {
188
		this.elements.retainAll(identitySet(elements));
189
	}
190
191
	abstract void handleValueChange(Object masterElement, Object oldValue,
192
			Object newValue);
193
194
	void dispose() {
195
		if (elements != null) {
196
			elements.clear(); // clears caches
197
			elements.dispose();
198
			elements = null;
199
		}
200
201
		if (delegateCaches != null) {
202
			for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) {
203
				DelegateCache cache = (DelegateCache) it.next();
204
				cache.dispose();
205
			}
206
			delegateCaches.clear();
207
			delegateCaches = null;
208
		}
209
	}
210
}
(-)src/org/eclipse/core/databinding/property/map/IMapProperty.java (+127 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.map;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.map.IObservableMap;
17
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.core.databinding.property.IProperty;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
22
/**
23
 * Interface for map-typed properties
24
 * 
25
 * @since 1.2
26
 * @noimplement This interface is not intended to be implemented by clients.
27
 *              Clients should instead subclass one of the classes that
28
 *              implement this interface. Note that direct implementers of this
29
 *              interface outside of the framework will be broken in future
30
 *              releases when methods are added to this interface.
31
 * @see MapProperty
32
 * @see SimpleMapProperty
33
 */
34
public interface IMapProperty extends IProperty {
35
	/**
36
	 * Returns the element type of the map's key set or <code>null</code> if the
37
	 * key set is untyped.
38
	 * 
39
	 * @return the element type of the map's key set or <code>null</code> if the
40
	 *         key set is untyped.
41
	 */
42
	public Object getKeyType();
43
44
	/**
45
	 * Returns the element type of the map's values collection or
46
	 * <code>null</code> if the collection is untyped.
47
	 * 
48
	 * @return the element type of the map's values collection or
49
	 *         <code>null</code> if the collection is untyped.
50
	 */
51
	public Object getValueType();
52
53
	/**
54
	 * Returns an observable map observing this map property on the given
55
	 * property source
56
	 * 
57
	 * @param source
58
	 *            the property source
59
	 * @return an observable map observing this map-typed property on the given
60
	 *         property source
61
	 */
62
	public IObservableMap observe(Object source);
63
64
	/**
65
	 * Returns an observable map observing this map property on the given
66
	 * property source
67
	 * 
68
	 * @param realm
69
	 *            the observable's realm
70
	 * @param source
71
	 *            the property source
72
	 * @return an observable map observing this map-typed property on the given
73
	 *         property source
74
	 */
75
	public IObservableMap observe(Realm realm, Object source);
76
77
	/**
78
	 * Returns a factory for creating observable maps tracking this property of
79
	 * a particular property source.
80
	 * 
81
	 * @return a factory for creating observable maps tracking this property of
82
	 *         a particular property source.
83
	 */
84
	public IObservableFactory mapFactory();
85
86
	/**
87
	 * Returns a factory for creating observable maps in the given realm,
88
	 * tracking this property of a particular property source.
89
	 * 
90
	 * @param realm
91
	 *            the realm
92
	 * 
93
	 * @return a factory for creating observable maps in the given realm,
94
	 *         tracking this property of a particular property source.
95
	 */
96
	public IObservableFactory mapFactory(Realm realm);
97
98
	/**
99
	 * Returns an observable map on the master observable's realm which tracks
100
	 * this property of the values in the entry set of <code>master</code>.
101
	 * 
102
	 * @param master
103
	 *            the master observable
104
	 * @return an observable map on the master observable's realm which tracks
105
	 *         this property of the values in the entry set of
106
	 *         <code>master</code>.
107
	 */
108
	public IObservableMap observeDetail(IObservableValue master);
109
110
	/**
111
	 * Returns the nested combination of this property and the specified detail
112
	 * value property. Note that because this property is a projection of value
113
	 * properties over a values collection, the only modifications supported are
114
	 * through the {@link IObservableMap#put(Object, Object)} and
115
	 * {@link IObservableMap#putAll(java.util.Map)} methods. In the latter case,
116
	 * this property does not entries for keys not already contained in the
117
	 * master map's key set. Modifications made through the returned property
118
	 * are delegated to the detail property, using the corresponding entry value
119
	 * from the master property as the source.
120
	 * 
121
	 * @param detailValues
122
	 *            the detail property
123
	 * @return the nested combination of the master map and detail value
124
	 *         properties.
125
	 */
126
	public IMapProperty values(IValueProperty detailValues);
127
}
(-)src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailMap.java (+64 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.map.IObservableMap;
16
import org.eclipse.core.databinding.observable.value.IObservableValue;
17
import org.eclipse.core.databinding.property.map.IMapProperty;
18
import org.eclipse.core.databinding.property.map.MapProperty;
19
import org.eclipse.core.databinding.property.value.IValueProperty;
20
21
/**
22
 * @since 3.3
23
 * 
24
 */
25
public class ValuePropertyDetailMap extends MapProperty {
26
	private final IValueProperty masterProperty;
27
	private final IMapProperty detailProperty;
28
29
	/**
30
	 * @param masterProperty
31
	 * @param detailProperty
32
	 */
33
	public ValuePropertyDetailMap(IValueProperty masterProperty,
34
			IMapProperty detailProperty) {
35
		this.masterProperty = masterProperty;
36
		this.detailProperty = detailProperty;
37
	}
38
39
	public Object getKeyType() {
40
		return detailProperty.getKeyType();
41
	}
42
43
	public Object getValueType() {
44
		return detailProperty.getValueType();
45
	}
46
47
	public IObservableMap observe(Realm realm, Object source) {
48
		IObservableValue masterValue = masterProperty.observe(realm, source);
49
		IObservableMap detailMap = detailProperty.observeDetail(masterValue);
50
		PropertyObservableUtil.cascadeDispose(detailMap, masterValue);
51
		return detailMap;
52
	}
53
54
	public IObservableMap observeDetail(IObservableValue master) {
55
		IObservableValue masterValue = masterProperty.observeDetail(master);
56
		IObservableMap detailMap = detailProperty.observeDetail(masterValue);
57
		PropertyObservableUtil.cascadeDispose(detailMap, masterValue);
58
		return detailMap;
59
	}
60
61
	public String toString() {
62
		return masterProperty + " => " + detailProperty; //$NON-NLS-1$
63
	}
64
}
(-)src/org/eclipse/core/internal/databinding/property/PropertyObservableUtil.java (+26 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Matthew Hall 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
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property;
13
14
import org.eclipse.core.databinding.observable.DisposeEvent;
15
import org.eclipse.core.databinding.observable.IDisposeListener;
16
import org.eclipse.core.databinding.observable.IObservable;
17
18
class PropertyObservableUtil {
19
	static void cascadeDispose(IObservable source, final IObservable target) {
20
		source.addDisposeListener(new IDisposeListener() {
21
			public void handleDispose(DisposeEvent staleEvent) {
22
				target.dispose();
23
			}
24
		});
25
	}
26
}
(-)src/org/eclipse/core/internal/databinding/property/value/ObservableMapDelegatingValuePropertyObservableMap.java (+316 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.value;
13
14
import java.util.AbstractSet;
15
import java.util.Collections;
16
import java.util.HashMap;
17
import java.util.HashSet;
18
import java.util.Iterator;
19
import java.util.Map;
20
import java.util.Set;
21
22
import org.eclipse.core.databinding.observable.Diffs;
23
import org.eclipse.core.databinding.observable.IStaleListener;
24
import org.eclipse.core.databinding.observable.ObservableTracker;
25
import org.eclipse.core.databinding.observable.StaleEvent;
26
import org.eclipse.core.databinding.observable.map.AbstractObservableMap;
27
import org.eclipse.core.databinding.observable.map.IMapChangeListener;
28
import org.eclipse.core.databinding.observable.map.IObservableMap;
29
import org.eclipse.core.databinding.observable.map.MapChangeEvent;
30
import org.eclipse.core.databinding.observable.map.MapDiff;
31
import org.eclipse.core.databinding.property.IProperty;
32
import org.eclipse.core.databinding.property.IPropertyObservable;
33
import org.eclipse.core.databinding.property.value.DelegatingValueProperty;
34
import org.eclipse.core.internal.databinding.Util;
35
36
/**
37
 * @since 1.2
38
 */
39
public class ObservableMapDelegatingValuePropertyObservableMap extends
40
		AbstractObservableMap implements IPropertyObservable {
41
	private IObservableMap masterMap;
42
	private DelegatingValueProperty detailProperty;
43
	private DelegatingCache cache;
44
45
	private Set entrySet;
46
47
	class EntrySet extends AbstractSet {
48
		public Iterator iterator() {
49
			return new Iterator() {
50
				Iterator it = masterMap.entrySet().iterator();
51
52
				public boolean hasNext() {
53
					getterCalled();
54
					return it.hasNext();
55
				}
56
57
				public Object next() {
58
					getterCalled();
59
					Map.Entry next = (Map.Entry) it.next();
60
					return new MapEntry(next.getKey());
61
				}
62
63
				public void remove() {
64
					it.remove();
65
				}
66
			};
67
		}
68
69
		public int size() {
70
			return masterMap.size();
71
		}
72
	}
73
74
	class MapEntry implements Map.Entry {
75
		private Object key;
76
77
		MapEntry(Object key) {
78
			this.key = key;
79
		}
80
81
		public Object getKey() {
82
			getterCalled();
83
			return key;
84
		}
85
86
		public Object getValue() {
87
			getterCalled();
88
89
			if (!masterMap.containsKey(key))
90
				return null;
91
92
			Object masterValue = masterMap.get(key);
93
			return cache.get(masterValue);
94
		}
95
96
		public Object setValue(Object value) {
97
			checkRealm();
98
99
			if (!masterMap.containsKey(key))
100
				return null;
101
102
			Object masterValue = masterMap.get(key);
103
			return cache.put(masterValue, value);
104
		}
105
106
		public boolean equals(Object o) {
107
			getterCalled();
108
			if (o == this)
109
				return true;
110
			if (o == null)
111
				return false;
112
			if (!(o instanceof Map.Entry))
113
				return false;
114
			Map.Entry that = (Map.Entry) o;
115
			return Util.equals(this.getKey(), that.getKey())
116
					&& Util.equals(this.getValue(), that.getValue());
117
		}
118
119
		public int hashCode() {
120
			getterCalled();
121
			Object value = getValue();
122
			return (key == null ? 0 : key.hashCode())
123
					^ (value == null ? 0 : value.hashCode());
124
		}
125
	}
126
127
	private IMapChangeListener masterListener = new IMapChangeListener() {
128
		public void handleMapChange(final MapChangeEvent event) {
129
			if (isDisposed())
130
				return;
131
132
			cache.addAll(masterMap.values());
133
134
			// Need both obsolete and new master values to convert diff
135
			MapDiff diff = convertDiff(event.diff);
136
137
			cache.retainAll(masterMap.values());
138
139
			fireMapChange(diff);
140
		}
141
142
		private MapDiff convertDiff(MapDiff diff) {
143
			Map oldValues = new HashMap();
144
			Map newValues = new HashMap();
145
146
			Set addedKeys = diff.getAddedKeys();
147
			for (Iterator it = addedKeys.iterator(); it.hasNext();) {
148
				Object key = it.next();
149
				Object masterValue = diff.getNewValue(key);
150
				Object newValue = cache.get(masterValue);
151
				newValues.put(key, newValue);
152
			}
153
154
			Set removedKeys = diff.getRemovedKeys();
155
			for (Iterator it = removedKeys.iterator(); it.hasNext();) {
156
				Object key = it.next();
157
				Object masterValue = diff.getOldValue(key);
158
				Object oldValue = cache.get(masterValue);
159
				oldValues.put(key, oldValue);
160
			}
161
162
			Set changedKeys = new HashSet(diff.getChangedKeys());
163
			for (Iterator it = changedKeys.iterator(); it.hasNext();) {
164
				Object key = it.next();
165
166
				Object oldMasterValue = diff.getOldValue(key);
167
				Object newMasterValue = diff.getNewValue(key);
168
169
				Object oldValue = cache.get(oldMasterValue);
170
				Object newValue = cache.get(newMasterValue);
171
172
				if (Util.equals(oldValue, newValue)) {
173
					it.remove();
174
				} else {
175
					oldValues.put(key, oldValue);
176
					newValues.put(key, newValue);
177
				}
178
			}
179
180
			return Diffs.createMapDiff(addedKeys, removedKeys, changedKeys,
181
					oldValues, newValues);
182
		}
183
	};
184
185
	private IStaleListener staleListener = new IStaleListener() {
186
		public void handleStale(StaleEvent staleEvent) {
187
			fireStale();
188
		}
189
	};
190
191
	/**
192
	 * @param map
193
	 * @param valueProperty
194
	 */
195
	public ObservableMapDelegatingValuePropertyObservableMap(
196
			IObservableMap map, DelegatingValueProperty valueProperty) {
197
		super(map.getRealm());
198
		this.masterMap = map;
199
		this.detailProperty = valueProperty;
200
		this.cache = new DelegatingCache(getRealm(), valueProperty) {
201
			void handleValueChange(Object masterElement, Object oldValue,
202
					Object newValue) {
203
				fireMapChange(keysFor(masterElement), oldValue, newValue);
204
			}
205
		};
206
		cache.addAll(masterMap.values());
207
208
		masterMap.addMapChangeListener(masterListener);
209
		masterMap.addStaleListener(staleListener);
210
	}
211
212
	public Set entrySet() {
213
		getterCalled();
214
		if (entrySet == null)
215
			entrySet = new EntrySet();
216
		return entrySet;
217
	}
218
219
	private void getterCalled() {
220
		ObservableTracker.getterCalled(this);
221
	}
222
223
	public Object get(Object key) {
224
		getterCalled();
225
		Object masterValue = masterMap.get(key);
226
		return cache.get(masterValue);
227
	}
228
229
	public Object put(Object key, Object value) {
230
		if (!masterMap.containsKey(key))
231
			return null;
232
		Object masterValue = masterMap.get(key);
233
		return cache.put(masterValue, value);
234
	}
235
236
	public boolean isStale() {
237
		getterCalled();
238
		return masterMap.isStale();
239
	}
240
241
	public Object getObserved() {
242
		return masterMap;
243
	}
244
245
	public IProperty getProperty() {
246
		return detailProperty;
247
	}
248
249
	public Object getKeyType() {
250
		return masterMap.getKeyType();
251
	}
252
253
	public Object getValueType() {
254
		return detailProperty.getValueType();
255
	}
256
257
	private Set keysFor(Object masterValue) {
258
		Set keys = new HashSet();
259
260
		for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) {
261
			Map.Entry entry = (Entry) it.next();
262
			if (entry.getValue() == masterValue) {
263
				keys.add(entry.getKey());
264
			}
265
		}
266
267
		return keys;
268
	}
269
270
	private void fireMapChange(final Set changedKeys, final Object oldValue,
271
			final Object newValue) {
272
		fireMapChange(new MapDiff() {
273
			public Set getAddedKeys() {
274
				return Collections.EMPTY_SET;
275
			}
276
277
			public Set getRemovedKeys() {
278
				return Collections.EMPTY_SET;
279
			}
280
281
			public Set getChangedKeys() {
282
				return Collections.unmodifiableSet(changedKeys);
283
			}
284
285
			public Object getOldValue(Object key) {
286
				if (changedKeys.contains(key))
287
					return oldValue;
288
				return null;
289
			}
290
291
			public Object getNewValue(Object key) {
292
				if (changedKeys.contains(key))
293
					return newValue;
294
				return null;
295
			}
296
		});
297
	}
298
299
	public synchronized void dispose() {
300
		if (masterMap != null) {
301
			masterMap.removeMapChangeListener(masterListener);
302
			masterMap.removeStaleListener(staleListener);
303
			masterMap = null;
304
		}
305
306
		if (cache != null) {
307
			cache.dispose();
308
			cache = null;
309
		}
310
311
		masterListener = null;
312
		detailProperty = null;
313
314
		super.dispose();
315
	}
316
}
(-)src/org/eclipse/core/internal/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java (+449 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.value;
13
14
import java.lang.reflect.Array;
15
import java.util.ArrayList;
16
import java.util.Collection;
17
import java.util.HashMap;
18
import java.util.HashSet;
19
import java.util.Iterator;
20
import java.util.List;
21
import java.util.ListIterator;
22
import java.util.Map;
23
import java.util.Set;
24
25
import org.eclipse.core.databinding.observable.Diffs;
26
import org.eclipse.core.databinding.observable.IStaleListener;
27
import org.eclipse.core.databinding.observable.ObservableTracker;
28
import org.eclipse.core.databinding.observable.StaleEvent;
29
import org.eclipse.core.databinding.observable.list.AbstractObservableList;
30
import org.eclipse.core.databinding.observable.list.IListChangeListener;
31
import org.eclipse.core.databinding.observable.list.IObservableList;
32
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
33
import org.eclipse.core.databinding.observable.list.ListDiff;
34
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
35
import org.eclipse.core.databinding.observable.set.IObservableSet;
36
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
37
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
38
import org.eclipse.core.databinding.observable.set.WritableSet;
39
import org.eclipse.core.databinding.property.INativePropertyListener;
40
import org.eclipse.core.databinding.property.IProperty;
41
import org.eclipse.core.databinding.property.IPropertyObservable;
42
import org.eclipse.core.databinding.property.ISimplePropertyListener;
43
import org.eclipse.core.databinding.property.SimplePropertyEvent;
44
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
45
import org.eclipse.core.internal.databinding.IdentityWrapper;
46
import org.eclipse.core.internal.databinding.Util;
47
48
/**
49
 * @since 1.2
50
 */
51
public class ObservableListSimpleValuePropertyObservableList extends
52
		AbstractObservableList implements IPropertyObservable {
53
	private IObservableList masterList;
54
	private SimpleValueProperty detailProperty;
55
56
	private IObservableSet knownMasterElements;
57
	private Map cachedValues;
58
59
	private boolean updating;
60
61
	private IListChangeListener masterListener = new IListChangeListener() {
62
		public void handleListChange(ListChangeEvent event) {
63
			if (!isDisposed()) {
64
				updateKnownElements();
65
				fireListChange(convertDiff(event.diff));
66
			}
67
		}
68
69
		private void updateKnownElements() {
70
			Set identityKnownElements = new HashSet();
71
			for (Iterator it = masterList.iterator(); it.hasNext();) {
72
				identityKnownElements.add(new IdentityWrapper(it.next()));
73
			}
74
75
			knownMasterElements.retainAll(identityKnownElements);
76
			knownMasterElements.addAll(identityKnownElements);
77
		}
78
79
		private ListDiff convertDiff(ListDiff diff) {
80
			// Convert diff to detail value
81
			ListDiffEntry[] masterEntries = diff.getDifferences();
82
			ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length];
83
			for (int i = 0; i < masterEntries.length; i++) {
84
				ListDiffEntry masterDifference = masterEntries[i];
85
				int index = masterDifference.getPosition();
86
				boolean addition = masterDifference.isAddition();
87
				Object masterElement = masterDifference.getElement();
88
				Object elementDetailValue = detailProperty
89
						.getValue(masterElement);
90
				detailEntries[i] = Diffs.createListDiffEntry(index, addition,
91
						elementDetailValue);
92
			}
93
			return Diffs.createListDiff(detailEntries);
94
		}
95
	};
96
97
	private IStaleListener staleListener = new IStaleListener() {
98
		public void handleStale(StaleEvent staleEvent) {
99
			fireStale();
100
		}
101
	};
102
103
	private INativePropertyListener detailListener;
104
105
	/**
106
	 * @param masterList
107
	 * @param valueProperty
108
	 */
109
	public ObservableListSimpleValuePropertyObservableList(
110
			IObservableList masterList, SimpleValueProperty valueProperty) {
111
		super(masterList.getRealm());
112
		this.masterList = masterList;
113
		this.detailProperty = valueProperty;
114
115
		ISimplePropertyListener listener = new ISimplePropertyListener() {
116
			public void handlePropertyChange(SimplePropertyEvent event) {
117
				if (!isDisposed() && !updating) {
118
					notifyIfChanged(event.getSource());
119
				}
120
			}
121
		};
122
		this.detailListener = detailProperty.adaptListener(listener);
123
	}
124
125
	protected void firstListenerAdded() {
126
		knownMasterElements = new WritableSet(getRealm());
127
		cachedValues = new HashMap();
128
		knownMasterElements.addSetChangeListener(new ISetChangeListener() {
129
			public void handleSetChange(SetChangeEvent event) {
130
				for (Iterator it = event.diff.getRemovals().iterator(); it
131
						.hasNext();) {
132
					IdentityWrapper wrapper = (IdentityWrapper) it.next();
133
					Object key = wrapper.unwrap();
134
					detailProperty.removeListener(key, detailListener);
135
					cachedValues.remove(wrapper);
136
				}
137
				for (Iterator it = event.diff.getAdditions().iterator(); it
138
						.hasNext();) {
139
					IdentityWrapper wrapper = (IdentityWrapper) it.next();
140
					Object key = wrapper.unwrap();
141
					cachedValues.put(wrapper, detailProperty.getValue(key));
142
					detailProperty.addListener(key, detailListener);
143
				}
144
			}
145
		});
146
		for (Iterator it = masterList.iterator(); it.hasNext();) {
147
			knownMasterElements.add(new IdentityWrapper(it.next()));
148
		}
149
150
		masterList.addListChangeListener(masterListener);
151
		masterList.addStaleListener(staleListener);
152
	}
153
154
	protected void lastListenerRemoved() {
155
		masterList.removeListChangeListener(masterListener);
156
		masterList.removeStaleListener(staleListener);
157
		if (knownMasterElements != null) {
158
			knownMasterElements.clear(); // clears cachedValues
159
			knownMasterElements.dispose();
160
			knownMasterElements = null;
161
		}
162
		cachedValues.clear();
163
		cachedValues = null;
164
	}
165
166
	protected int doGetSize() {
167
		getterCalled();
168
		return masterList.size();
169
	}
170
171
	private void getterCalled() {
172
		ObservableTracker.getterCalled(this);
173
	}
174
175
	public Object getElementType() {
176
		return detailProperty.getValueType();
177
	}
178
179
	public Object get(int index) {
180
		getterCalled();
181
		Object masterElement = masterList.get(index);
182
		return detailProperty.getValue(masterElement);
183
	}
184
185
	public boolean add(Object o) {
186
		throw new UnsupportedOperationException();
187
	}
188
189
	public boolean addAll(Collection c) {
190
		throw new UnsupportedOperationException();
191
	}
192
193
	public boolean addAll(int index, Collection c) {
194
		throw new UnsupportedOperationException();
195
	}
196
197
	public boolean contains(Object o) {
198
		getterCalled();
199
200
		for (Iterator it = masterList.iterator(); it.hasNext();) {
201
			if (Util.equals(detailProperty.getValue(it.next()), o))
202
				return true;
203
		}
204
		return false;
205
	}
206
207
	public boolean isEmpty() {
208
		getterCalled();
209
		return masterList.isEmpty();
210
	}
211
212
	public boolean isStale() {
213
		getterCalled();
214
		return masterList.isStale();
215
	}
216
217
	public Iterator iterator() {
218
		getterCalled();
219
		return new Iterator() {
220
			Iterator it = masterList.iterator();
221
222
			public boolean hasNext() {
223
				getterCalled();
224
				return it.hasNext();
225
			}
226
227
			public Object next() {
228
				getterCalled();
229
				Object masterElement = it.next();
230
				return detailProperty.getValue(masterElement);
231
			}
232
233
			public void remove() {
234
				throw new UnsupportedOperationException();
235
			}
236
		};
237
	}
238
239
	public Object move(int oldIndex, int newIndex) {
240
		throw new UnsupportedOperationException();
241
	}
242
243
	public boolean remove(Object o) {
244
		throw new UnsupportedOperationException();
245
	}
246
247
	public boolean removeAll(Collection c) {
248
		throw new UnsupportedOperationException();
249
	}
250
251
	public boolean retainAll(Collection c) {
252
		throw new UnsupportedOperationException();
253
	}
254
255
	public Object[] toArray() {
256
		getterCalled();
257
		Object[] masterElements = masterList.toArray();
258
		Object[] result = new Object[masterElements.length];
259
		for (int i = 0; i < result.length; i++) {
260
			result[i] = detailProperty.getValue(masterElements[i]);
261
		}
262
		return result;
263
	}
264
265
	public Object[] toArray(Object[] a) {
266
		getterCalled();
267
		Object[] masterElements = masterList.toArray();
268
		if (a.length < masterElements.length)
269
			a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
270
					masterElements.length);
271
		for (int i = 0; i < masterElements.length; i++) {
272
			a[i] = detailProperty.getValue(masterElements[i]);
273
		}
274
		return a;
275
	}
276
277
	public void add(int index, Object o) {
278
		throw new UnsupportedOperationException();
279
	}
280
281
	public void clear() {
282
		throw new UnsupportedOperationException();
283
	}
284
285
	public ListIterator listIterator() {
286
		return listIterator(0);
287
	}
288
289
	public ListIterator listIterator(final int index) {
290
		getterCalled();
291
		return new ListIterator() {
292
			ListIterator it = masterList.listIterator(index);
293
			Object lastMasterElement;
294
			Object lastElement;
295
			boolean haveIterated = false;
296
297
			public void add(Object arg0) {
298
				throw new UnsupportedOperationException();
299
			}
300
301
			public boolean hasNext() {
302
				getterCalled();
303
				return it.hasNext();
304
			}
305
306
			public boolean hasPrevious() {
307
				getterCalled();
308
				return it.hasPrevious();
309
			}
310
311
			public Object next() {
312
				getterCalled();
313
				lastMasterElement = it.next();
314
				lastElement = detailProperty.getValue(lastMasterElement);
315
				haveIterated = true;
316
				return lastElement;
317
			}
318
319
			public int nextIndex() {
320
				getterCalled();
321
				return it.nextIndex();
322
			}
323
324
			public Object previous() {
325
				getterCalled();
326
				lastMasterElement = it.previous();
327
				lastElement = detailProperty.getValue(lastMasterElement);
328
				haveIterated = true;
329
				return lastElement;
330
			}
331
332
			public int previousIndex() {
333
				getterCalled();
334
				return it.previousIndex();
335
			}
336
337
			public void remove() {
338
				throw new UnsupportedOperationException();
339
			}
340
341
			public void set(Object o) {
342
				checkRealm();
343
				if (!haveIterated)
344
					throw new IllegalStateException();
345
346
				boolean wasUpdating = updating;
347
				updating = true;
348
				try {
349
					detailProperty.setValue(lastElement, o);
350
				} finally {
351
					updating = wasUpdating;
352
				}
353
354
				notifyIfChanged(lastMasterElement);
355
356
				lastElement = o;
357
			}
358
		};
359
	}
360
361
	private void notifyIfChanged(Object masterElement) {
362
		if (cachedValues != null) {
363
			Object oldValue = cachedValues.get(new IdentityWrapper(
364
					masterElement));
365
			Object newValue = detailProperty.getValue(masterElement);
366
			if (!Util.equals(oldValue, newValue)) {
367
				cachedValues.put(new IdentityWrapper(masterElement), newValue);
368
				fireListChange(indicesOf(masterElement), oldValue, newValue);
369
			}
370
		}
371
	}
372
373
	private int[] indicesOf(Object masterElement) {
374
		List indices = new ArrayList();
375
376
		for (ListIterator it = ObservableListSimpleValuePropertyObservableList.this.masterList
377
				.listIterator(); it.hasNext();) {
378
			if (masterElement == it.next())
379
				indices.add(new Integer(it.previousIndex()));
380
		}
381
382
		int[] result = new int[indices.size()];
383
		for (int i = 0; i < result.length; i++) {
384
			result[i] = ((Integer) indices.get(i)).intValue();
385
		}
386
		return result;
387
	}
388
389
	private void fireListChange(int[] indices, Object oldValue, Object newValue) {
390
		ListDiffEntry[] differences = new ListDiffEntry[indices.length * 2];
391
		for (int i = 0; i < indices.length; i++) {
392
			int index = indices[i];
393
			differences[i * 2] = Diffs.createListDiffEntry(index, false,
394
					oldValue);
395
			differences[i * 2 + 1] = Diffs.createListDiffEntry(index, true,
396
					newValue);
397
		}
398
		fireListChange(Diffs.createListDiff(differences));
399
	}
400
401
	public Object remove(int index) {
402
		throw new UnsupportedOperationException();
403
	}
404
405
	public Object set(int index, Object o) {
406
		checkRealm();
407
		Object masterElement = masterList.get(index);
408
		Object oldValue = detailProperty.getValue(masterElement);
409
410
		boolean wasUpdating = updating;
411
		updating = true;
412
		try {
413
			detailProperty.setValue(masterElement, o);
414
		} finally {
415
			updating = wasUpdating;
416
		}
417
418
		notifyIfChanged(masterElement);
419
420
		return oldValue;
421
	}
422
423
	public Object getObserved() {
424
		return masterList;
425
	}
426
427
	public IProperty getProperty() {
428
		return detailProperty;
429
	}
430
431
	public synchronized void dispose() {
432
		if (masterList != null) {
433
			masterList.removeListChangeListener(masterListener);
434
			masterList = null;
435
		}
436
		if (knownMasterElements != null) {
437
			knownMasterElements.clear(); // detaches listeners
438
			knownMasterElements.dispose();
439
			knownMasterElements = null;
440
		}
441
442
		masterListener = null;
443
		detailListener = null;
444
		detailProperty = null;
445
		cachedValues = null;
446
447
		super.dispose();
448
	}
449
}
(-)src/org/eclipse/core/databinding/property/IProperty.java (+21 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.property;
13
14
/**
15
 * Marker interface for all property types in the properties framework.
16
 * 
17
 * @since 1.2
18
 * @noimplement This interface is not intended to be implemented by clients.
19
 */
20
public interface IProperty {
21
}
(-)src/org/eclipse/core/databinding/property/list/SimpleListProperty.java (+193 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222, 247997
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.list;
14
15
import java.util.Collections;
16
import java.util.List;
17
18
import org.eclipse.core.databinding.observable.Realm;
19
import org.eclipse.core.databinding.observable.list.IObservableList;
20
import org.eclipse.core.databinding.observable.list.ListDiff;
21
import org.eclipse.core.databinding.property.INativePropertyListener;
22
import org.eclipse.core.databinding.property.ISimplePropertyListener;
23
import org.eclipse.core.internal.databinding.property.list.SimpleListPropertyObservableList;
24
25
/**
26
 * Simplified abstract implementation of IListProperty. This class takes care of
27
 * most of the functional requirements for an IListProperty implementation,
28
 * leaving only the property-specific details to subclasses.
29
 * <p>
30
 * Subclasses must implement these methods:
31
 * <ul>
32
 * <li> {@link #getElementType()}
33
 * <li> {@link #doGetList(Object)}
34
 * <li> {@link #doSetList(Object, List, ListDiff)}
35
 * <li> {@link #adaptListener(ISimplePropertyListener)}
36
 * <li> {@link #doAddListener(Object, INativePropertyListener)}
37
 * <li> {@link #doRemoveListener(Object, INativePropertyListener)}
38
 * </ul>
39
 * <p>
40
 * In addition, we recommended overriding {@link #toString()} to return a
41
 * description suitable for debugging purposes.
42
 * 
43
 * @since 1.2
44
 */
45
public abstract class SimpleListProperty extends ListProperty {
46
	public IObservableList observe(Realm realm, Object source) {
47
		return new SimpleListPropertyObservableList(realm, source, this);
48
	}
49
50
	// Accessors
51
52
	/**
53
	 * Returns an unmodifiable List with the current contents of the source's
54
	 * list property
55
	 * 
56
	 * @param source
57
	 *            the property source
58
	 * @return an unmodifiable List with the current contents of the source's
59
	 *         list property
60
	 * @noreference This method is not intended to be referenced by clients.
61
	 */
62
	public final List getList(Object source) {
63
		if (source == null)
64
			return Collections.EMPTY_LIST;
65
		return Collections.unmodifiableList(doGetList(source));
66
	}
67
68
	/**
69
	 * Returns a List with the current contents of the source's list property
70
	 * 
71
	 * @param source
72
	 *            the property source
73
	 * @return a List with the current contents of the source's list property
74
	 * @noreference This method is not intended to be referenced by clients.
75
	 */
76
	protected abstract List doGetList(Object source);
77
78
	// Mutators
79
80
	/**
81
	 * Updates the property on the source with the specified change.
82
	 * 
83
	 * @param source
84
	 *            the property source
85
	 * @param list
86
	 *            the new list
87
	 * @param diff
88
	 *            a diff describing the change
89
	 * @noreference This method is not intended to be referenced by clients.
90
	 */
91
	public final void setList(Object source, List list, ListDiff diff) {
92
		if (source != null && !diff.isEmpty())
93
			doSetList(source, list, diff);
94
	}
95
96
	/**
97
	 * Updates the property on the source with the specified change.
98
	 * 
99
	 * @param source
100
	 *            the property source
101
	 * @param list
102
	 *            the new list
103
	 * @param diff
104
	 *            a diff describing the change
105
	 * @noreference This method is not intended to be referenced by clients.
106
	 */
107
	protected abstract void doSetList(Object source, List list, ListDiff diff);
108
109
	/**
110
	 * Returns a listener which implements the correct listener interface for
111
	 * the expected source object, and which parlays property change events from
112
	 * the source object to the given listener. If there is no listener API for
113
	 * this property, this method returns null.
114
	 * 
115
	 * @param listener
116
	 *            the property listener to receive events
117
	 * @return a native listener which parlays property change events to the
118
	 *         specified listener.
119
	 * @noreference This method is not intended to be referenced by clients.
120
	 */
121
	public abstract INativePropertyListener adaptListener(
122
			ISimplePropertyListener listener);
123
124
	/**
125
	 * Adds the specified listener as a listener for this property on the
126
	 * specified property source. If the source object has no listener API for
127
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
128
	 * returns null), this method does nothing.
129
	 * 
130
	 * @param source
131
	 *            the property source
132
	 * @param listener
133
	 *            a listener obtained from calling
134
	 *            {@link #adaptListener(ISimplePropertyListener)}.
135
	 * @noreference This method is not intended to be referenced by clients.
136
	 */
137
	public final void addListener(Object source,
138
			INativePropertyListener listener) {
139
		if (source != null)
140
			doAddListener(source, listener);
141
	}
142
143
	/**
144
	 * Adds the specified listener as a listener for this property on the
145
	 * specified property source. If the source object has no listener API for
146
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
147
	 * returns null), this method does nothing.
148
	 * 
149
	 * @param source
150
	 *            the property source
151
	 * @param listener
152
	 *            a listener obtained from calling
153
	 *            {@link #adaptListener(ISimplePropertyListener)}.
154
	 * @noreference This method is not intended to be referenced by clients.
155
	 */
156
	protected abstract void doAddListener(Object source,
157
			INativePropertyListener listener);
158
159
	/**
160
	 * Removes the specified listener as a listener for this property on the
161
	 * specified property source. If the source object has no listener API for
162
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
163
	 * returns null), this method does nothing.
164
	 * 
165
	 * @param source
166
	 *            the property source
167
	 * @param listener
168
	 *            a listener obtained from calling
169
	 *            {@link #adaptListener(ISimplePropertyListener)}.
170
	 * @noreference This method is not intended to be referenced by clients.
171
	 */
172
	public final void removeListener(Object source,
173
			INativePropertyListener listener) {
174
		if (source != null)
175
			doRemoveListener(source, listener);
176
	}
177
178
	/**
179
	 * Removes the specified listener as a listener for this property on the
180
	 * specified property source. If the source object has no listener API for
181
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
182
	 * returns null), this method does nothing.
183
	 * 
184
	 * @param source
185
	 *            the property source
186
	 * @param listener
187
	 *            a listener obtained from calling
188
	 *            {@link #adaptListener(ISimplePropertyListener)}.
189
	 * @noreference This method is not intended to be referenced by clients.
190
	 */
191
	protected abstract void doRemoveListener(Object source,
192
			INativePropertyListener listener);
193
}
(-)src/org/eclipse/core/databinding/property/SimplePropertyEvent.java (+76 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.property;
13
14
import java.util.EventObject;
15
16
import org.eclipse.core.databinding.observable.IDiff;
17
import org.eclipse.core.internal.databinding.Util;
18
19
/**
20
 * Base class for change events in the properties API
21
 * 
22
 * @since 1.2
23
 */
24
public final class SimplePropertyEvent extends EventObject {
25
	private static final long serialVersionUID = 1L;
26
27
	/**
28
	 * The property that changed
29
	 */
30
	public final IProperty property;
31
32
	/**
33
	 * A diff object describing the change in state, or null for an unknown
34
	 * change.
35
	 */
36
	public final IDiff diff;
37
38
	/**
39
	 * Constructs a PropertyChangeEvent with the given attributes
40
	 * 
41
	 * @param source
42
	 *            the property source
43
	 * @param property
44
	 *            the property that changed on the source
45
	 * @param diff
46
	 *            a diff describing the change in state, or null if the change
47
	 *            is unknown.
48
	 */
49
	public SimplePropertyEvent(Object source, IProperty property, IDiff diff) {
50
		super(source);
51
		this.property = property;
52
		this.diff = diff;
53
	}
54
55
	public boolean equals(Object obj) {
56
		if (obj == this)
57
			return true;
58
		if (obj == null)
59
			return false;
60
		if (getClass() != obj.getClass())
61
			return false;
62
63
		SimplePropertyEvent that = (SimplePropertyEvent) obj;
64
		return Util.equals(getSource(), that.getSource())
65
				&& Util.equals(this.property, that.property)
66
				&& Util.equals(this.diff, that.diff);
67
	}
68
69
	public int hashCode() {
70
		int hash = 17;
71
		hash = hash * 37 + getSource().hashCode();
72
		hash = hash * 37 + property.hashCode();
73
		hash = hash * 37 + (diff == null ? 0 : diff.hashCode());
74
		return hash;
75
	}
76
}
(-)src/org/eclipse/core/databinding/property/set/DelegatingSetProperty.java (+101 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.property.set;
13
14
import java.util.Collections;
15
import java.util.Set;
16
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.set.IObservableSet;
19
import org.eclipse.core.databinding.observable.set.SetDiff;
20
import org.eclipse.core.databinding.property.INativePropertyListener;
21
import org.eclipse.core.databinding.property.ISimplePropertyListener;
22
23
/**
24
 * @since 1.2
25
 * 
26
 */
27
public abstract class DelegatingSetProperty extends SetProperty {
28
	private final Object elementType;
29
	private final ISetProperty nullProperty = new NullSetProperty();
30
31
	protected DelegatingSetProperty() {
32
		this(null);
33
	}
34
35
	protected DelegatingSetProperty(Object elementType) {
36
		this.elementType = elementType;
37
	}
38
39
	/**
40
	 * Returns the property to delegate to for the specified source object.
41
	 * Repeated calls to this method with the same source object returns the
42
	 * same delegate instance.
43
	 * 
44
	 * @param source
45
	 *            the property source (may be null)
46
	 * @return the property to delegate to for the specified source object.
47
	 */
48
	protected final ISetProperty getDelegate(Object source) {
49
		if (source == null)
50
			return null;
51
		ISetProperty delegate = doGetDelegate(source);
52
		if (delegate == null)
53
			delegate = nullProperty;
54
		return delegate;
55
	}
56
57
	/**
58
	 * Returns the property to delegate to for the specified source object.
59
	 * Implementers must ensure that repeated calls to this method with the same
60
	 * source object returns the same delegate instance.
61
	 * 
62
	 * @param source
63
	 *            the property source
64
	 * @return the property to delegate to for the specified source object.
65
	 */
66
	protected abstract ISetProperty doGetDelegate(Object source);
67
68
	public Object getElementType() {
69
		return elementType;
70
	}
71
72
	public IObservableSet observe(Realm realm, Object source) {
73
		return getDelegate(source).observe(realm, source);
74
	}
75
76
	private class NullSetProperty extends SimpleSetProperty {
77
		public Object getElementType() {
78
			return elementType;
79
		}
80
81
		protected Set doGetSet(Object source) {
82
			return Collections.EMPTY_SET;
83
		}
84
85
		protected void doSetSet(Object source, Set set, SetDiff diff) {
86
		}
87
88
		public INativePropertyListener adaptListener(
89
				ISimplePropertyListener listener) {
90
			return null;
91
		}
92
93
		protected void doAddListener(Object source,
94
				INativePropertyListener listener) {
95
		}
96
97
		protected void doRemoveListener(Object source,
98
				INativePropertyListener listener) {
99
		}
100
	}
101
}
(-)src/org/eclipse/core/databinding/property/IPropertyObservable.java (+28 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.property;
13
14
import org.eclipse.core.databinding.observable.IObserving;
15
16
/**
17
 * Provides access to the details of property observables
18
 * 
19
 * @since 1.2
20
 */
21
public interface IPropertyObservable extends IObserving {
22
	/**
23
	 * Returns the property being observed
24
	 * 
25
	 * @return the property being observed
26
	 */
27
	IProperty getProperty();
28
}
(-)src/org/eclipse/core/internal/databinding/property/map/SimpleMapPropertyObservableMap.java (+297 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.map;
13
14
import java.util.AbstractSet;
15
import java.util.Collection;
16
import java.util.Collections;
17
import java.util.ConcurrentModificationException;
18
import java.util.HashMap;
19
import java.util.HashSet;
20
import java.util.Iterator;
21
import java.util.Map;
22
import java.util.Set;
23
24
import org.eclipse.core.databinding.observable.Diffs;
25
import org.eclipse.core.databinding.observable.ObservableTracker;
26
import org.eclipse.core.databinding.observable.Realm;
27
import org.eclipse.core.databinding.observable.map.AbstractObservableMap;
28
import org.eclipse.core.databinding.observable.map.MapDiff;
29
import org.eclipse.core.databinding.property.INativePropertyListener;
30
import org.eclipse.core.databinding.property.IProperty;
31
import org.eclipse.core.databinding.property.IPropertyObservable;
32
import org.eclipse.core.databinding.property.ISimplePropertyListener;
33
import org.eclipse.core.databinding.property.SimplePropertyEvent;
34
import org.eclipse.core.databinding.property.map.SimpleMapProperty;
35
36
/**
37
 * @since 1.2
38
 */
39
public class SimpleMapPropertyObservableMap extends AbstractObservableMap
40
		implements IPropertyObservable {
41
	private Object source;
42
	private SimpleMapProperty property;
43
44
	private volatile boolean updating = false;
45
46
	private volatile int modCount = 0;
47
48
	private INativePropertyListener listener;
49
50
	private Map cachedMap;
51
52
	/**
53
	 * @param realm
54
	 * @param source
55
	 * @param property
56
	 */
57
	public SimpleMapPropertyObservableMap(Realm realm, Object source,
58
			SimpleMapProperty property) {
59
		super(realm);
60
		this.source = source;
61
		this.property = property;
62
	}
63
64
	public Object getKeyType() {
65
		return property.getKeyType();
66
	}
67
68
	public Object getValueType() {
69
		return property.getValueType();
70
	}
71
72
	private void getterCalled() {
73
		ObservableTracker.getterCalled(this);
74
	}
75
76
	protected void firstListenerAdded() {
77
		if (!isDisposed()) {
78
			cachedMap = new HashMap(this);
79
80
			if (listener == null) {
81
				listener = property
82
						.adaptListener(new ISimplePropertyListener() {
83
							public void handlePropertyChange(
84
									final SimplePropertyEvent event) {
85
								modCount++;
86
								if (!isDisposed() && !updating) {
87
									getRealm().exec(new Runnable() {
88
										public void run() {
89
											notifyIfChanged((MapDiff) event.diff);
90
										}
91
									});
92
								}
93
							}
94
						});
95
			}
96
			property.addListener(source, listener);
97
		}
98
	}
99
100
	protected void lastListenerRemoved() {
101
		if (listener != null) {
102
			property.removeListener(source, listener);
103
		}
104
105
		cachedMap.clear();
106
		cachedMap = null;
107
	}
108
109
	// Queries
110
111
	private Map getMap() {
112
		return property.getMap(source);
113
	}
114
115
	// Single change operations
116
117
	private EntrySet es = new EntrySet();
118
119
	public Set entrySet() {
120
		getterCalled();
121
		return es;
122
	}
123
124
	private class EntrySet extends AbstractSet {
125
		public Iterator iterator() {
126
			return new EntrySetIterator();
127
		}
128
129
		public int size() {
130
			return getMap().size();
131
		}
132
	}
133
134
	private class EntrySetIterator implements Iterator {
135
		private volatile int expectedModCount = modCount;
136
		Map map = new HashMap(getMap());
137
		Iterator iterator = map.entrySet().iterator();
138
		Map.Entry last = null;
139
140
		public boolean hasNext() {
141
			getterCalled();
142
			checkForComodification();
143
			return iterator.hasNext();
144
		}
145
146
		public Object next() {
147
			getterCalled();
148
			checkForComodification();
149
			last = (Map.Entry) iterator.next();
150
			return last;
151
		}
152
153
		public void remove() {
154
			getterCalled();
155
			checkForComodification();
156
157
			iterator.remove(); // stay in sync
158
			MapDiff diff = Diffs.createMapDiffSingleRemove(last.getKey(), last
159
					.getValue());
160
161
			boolean wasUpdating = updating;
162
			updating = true;
163
			try {
164
				property.setMap(source, map, diff);
165
			} finally {
166
				updating = wasUpdating;
167
			}
168
169
			notifyIfChanged(null);
170
171
			last = null;
172
			expectedModCount = modCount;
173
		}
174
175
		private void checkForComodification() {
176
			if (expectedModCount != modCount)
177
				throw new ConcurrentModificationException();
178
		}
179
	}
180
181
	public Set keySet() {
182
		getterCalled();
183
		// AbstractMap depends on entrySet() to fulfil keySet() API, so all
184
		// getterCalled() and comodification checks will still be handled
185
		return super.keySet();
186
	}
187
188
	public Object put(Object key, Object value) {
189
		checkRealm();
190
191
		Map map = new HashMap(getMap());
192
193
		boolean add = !map.containsKey(key);
194
195
		Object oldValue = map.put(key, value);
196
197
		MapDiff diff;
198
		if (add)
199
			diff = Diffs.createMapDiffSingleAdd(key, value);
200
		else
201
			diff = Diffs.createMapDiffSingleChange(key, oldValue, value);
202
203
		boolean wasUpdating = updating;
204
		updating = true;
205
		try {
206
			property.setMap(source, map, diff);
207
			modCount++;
208
		} finally {
209
			updating = wasUpdating;
210
		}
211
212
		notifyIfChanged(null);
213
214
		return oldValue;
215
	}
216
217
	public void putAll(Map m) {
218
		checkRealm();
219
220
		Map map = new HashMap(getMap());
221
222
		Map oldValues = new HashMap();
223
		Map newValues = new HashMap();
224
		Set changedKeys = new HashSet();
225
		Set addedKeys = new HashSet();
226
		for (Iterator it = m.entrySet().iterator(); it.hasNext();) {
227
			Map.Entry entry = (Entry) it.next();
228
			Object key = entry.getKey();
229
			Object newValue = entry.getValue();
230
			if (map.containsKey(key)) {
231
				changedKeys.add(key);
232
				oldValues.put(key, map.get(key));
233
			} else {
234
				addedKeys.add(key);
235
			}
236
			map.put(key, newValue);
237
238
			newValues.put(key, newValue);
239
		}
240
241
		MapDiff diff = Diffs.createMapDiff(addedKeys, Collections.EMPTY_SET,
242
				changedKeys, oldValues, newValues);
243
244
		boolean wasUpdating = updating;
245
		updating = true;
246
		try {
247
			property.setMap(source, map, diff);
248
			modCount++;
249
		} finally {
250
			updating = wasUpdating;
251
		}
252
253
		notifyIfChanged(null);
254
	}
255
256
	public Object remove(Object key) {
257
		checkRealm();
258
		return super.remove(key);
259
	}
260
261
	public Collection values() {
262
		getterCalled();
263
		// AbstractMap depends on entrySet() to fulfil values() API, so all
264
		// getterCalled() and comodification checks will still be handled
265
		return super.values();
266
	}
267
268
	private void notifyIfChanged(MapDiff diff) {
269
		if (hasListeners()) {
270
			Map oldMap = cachedMap;
271
			Map newMap = cachedMap = property.getMap(source);
272
			if (diff == null)
273
				diff = Diffs.computeMapDiff(oldMap, newMap);
274
			if (!diff.isEmpty())
275
				fireMapChange(diff);
276
		}
277
	}
278
279
	public Object getObserved() {
280
		return source;
281
	}
282
283
	public IProperty getProperty() {
284
		return property;
285
	}
286
287
	public synchronized void dispose() {
288
		if (!isDisposed()) {
289
			if (listener != null)
290
				property.removeListener(source, listener);
291
			property = null;
292
			source = null;
293
			listener = null;
294
		}
295
		super.dispose();
296
	}
297
}
(-)src/org/eclipse/core/internal/databinding/property/MapPropertyDetailValuesMap.java (+65 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.property;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.map.IObservableMap;
17
import org.eclipse.core.databinding.observable.value.IObservableValue;
18
import org.eclipse.core.databinding.property.map.IMapProperty;
19
import org.eclipse.core.databinding.property.map.MapProperty;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class MapPropertyDetailValuesMap extends MapProperty {
27
	private final IMapProperty masterProperty;
28
	private final IValueProperty detailProperty;
29
30
	/**
31
	 * @param masterProperty
32
	 * @param detailProperty
33
	 */
34
	public MapPropertyDetailValuesMap(IMapProperty masterProperty,
35
			IValueProperty detailProperty) {
36
		this.masterProperty = masterProperty;
37
		this.detailProperty = detailProperty;
38
	}
39
40
	public Object getKeyType() {
41
		return masterProperty.getKeyType();
42
	}
43
44
	public Object getValueType() {
45
		return detailProperty.getValueType();
46
	}
47
48
	public IObservableMap observe(Realm realm, Object source) {
49
		IObservableMap masterMap = masterProperty.observe(realm, source);
50
		IObservableMap detailMap = detailProperty.observeDetail(masterMap);
51
		PropertyObservableUtil.cascadeDispose(detailMap, masterMap);
52
		return detailMap;
53
	}
54
55
	public IObservableMap observeDetail(IObservableValue master) {
56
		IObservableMap masterMap = masterProperty.observeDetail(master);
57
		IObservableMap detailMap = detailProperty.observeDetail(masterMap);
58
		PropertyObservableUtil.cascadeDispose(detailMap, masterMap);
59
		return detailMap;
60
	}
61
62
	public String toString() {
63
		return masterProperty + " => " + detailProperty; //$NON-NLS-1$
64
	}
65
}
(-)src/org/eclipse/core/internal/databinding/property/ListPropertyDetailValuesList.java (+61 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.property;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
17
import org.eclipse.core.databinding.observable.value.IObservableValue;
18
import org.eclipse.core.databinding.property.list.IListProperty;
19
import org.eclipse.core.databinding.property.list.ListProperty;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class ListPropertyDetailValuesList extends ListProperty {
27
	private final IListProperty masterProperty;
28
	private final IValueProperty detailProperty;
29
30
	/**
31
	 * @param masterProperty
32
	 * @param detailProperty
33
	 */
34
	public ListPropertyDetailValuesList(IListProperty masterProperty,
35
			IValueProperty detailProperty) {
36
		this.masterProperty = masterProperty;
37
		this.detailProperty = detailProperty;
38
	}
39
40
	public Object getElementType() {
41
		return detailProperty.getValueType();
42
	}
43
44
	public IObservableList observe(Realm realm, Object source) {
45
		IObservableList masterList = masterProperty.observe(realm, source);
46
		IObservableList detailList = detailProperty.observeDetail(masterList);
47
		PropertyObservableUtil.cascadeDispose(detailList, masterList);
48
		return detailList;
49
	}
50
51
	public IObservableList observeDetail(IObservableValue master) {
52
		IObservableList masterList = masterProperty.observeDetail(master);
53
		IObservableList detailList = detailProperty.observeDetail(masterList);
54
		PropertyObservableUtil.cascadeDispose(detailList, masterList);
55
		return detailList;
56
	}
57
58
	public String toString() {
59
		return masterProperty + " => " + detailProperty; //$NON-NLS-1$
60
	}
61
}
(-)src/org/eclipse/core/internal/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java (+144 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.value;
13
14
import java.util.HashMap;
15
import java.util.Iterator;
16
import java.util.Map;
17
18
import org.eclipse.core.databinding.observable.Diffs;
19
import org.eclipse.core.databinding.observable.map.ComputedObservableMap;
20
import org.eclipse.core.databinding.observable.set.IObservableSet;
21
import org.eclipse.core.databinding.property.INativePropertyListener;
22
import org.eclipse.core.databinding.property.IProperty;
23
import org.eclipse.core.databinding.property.IPropertyObservable;
24
import org.eclipse.core.databinding.property.ISimplePropertyListener;
25
import org.eclipse.core.databinding.property.SimplePropertyEvent;
26
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
27
import org.eclipse.core.internal.databinding.Util;
28
29
/**
30
 * @since 1.2
31
 */
32
public class ObservableSetSimpleValuePropertyObservableMap extends
33
		ComputedObservableMap implements IPropertyObservable {
34
	private SimpleValueProperty detailProperty;
35
36
	private INativePropertyListener listener;
37
38
	private Map cachedValues;
39
40
	private boolean updating;
41
42
	/**
43
	 * @param keySet
44
	 * @param valueProperty
45
	 */
46
	public ObservableSetSimpleValuePropertyObservableMap(IObservableSet keySet,
47
			SimpleValueProperty valueProperty) {
48
		super(keySet);
49
		this.detailProperty = valueProperty;
50
	}
51
52
	protected void firstListenerAdded() {
53
		cachedValues = new HashMap(this);
54
		if (listener == null) {
55
			listener = detailProperty
56
					.adaptListener(new ISimplePropertyListener() {
57
						public void handlePropertyChange(
58
								final SimplePropertyEvent event) {
59
							if (!isDisposed() && !updating) {
60
								getRealm().exec(new Runnable() {
61
									public void run() {
62
										notifyIfChanged(event.getSource());
63
									}
64
								});
65
							}
66
						}
67
					});
68
		}
69
		super.firstListenerAdded();
70
	}
71
72
	protected void lastListenerRemoved() {
73
		super.lastListenerRemoved();
74
		cachedValues.clear();
75
		cachedValues = null;
76
	}
77
78
	protected void hookListener(Object addedKey) {
79
		if (listener != null) {
80
			cachedValues.put(addedKey, detailProperty.getValue(addedKey));
81
			detailProperty.addListener(addedKey, listener);
82
		}
83
	}
84
85
	protected void unhookListener(Object removedKey) {
86
		if (listener != null) {
87
			detailProperty.removeListener(removedKey, listener);
88
			cachedValues.remove(removedKey);
89
		}
90
	}
91
92
	protected Object doGet(Object key) {
93
		return detailProperty.getValue(key);
94
	}
95
96
	protected Object doPut(Object key, Object value) {
97
		Object oldValue = detailProperty.getValue(key);
98
99
		updating = true;
100
		try {
101
			detailProperty.setValue(key, value);
102
		} finally {
103
			updating = false;
104
		}
105
106
		notifyIfChanged(key);
107
108
		return oldValue;
109
	}
110
111
	private void notifyIfChanged(Object key) {
112
		if (cachedValues != null) {
113
			Object oldValue = cachedValues.get(key);
114
			Object newValue = detailProperty.getValue(key);
115
			if (!Util.equals(oldValue, newValue)) {
116
				cachedValues.put(key, newValue);
117
				fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue,
118
						newValue));
119
			}
120
		}
121
	}
122
123
	public Object getObserved() {
124
		return keySet();
125
	}
126
127
	public IProperty getProperty() {
128
		return detailProperty;
129
	}
130
131
	public synchronized void dispose() {
132
		if (!isDisposed()) {
133
			if (listener != null) {
134
				for (Iterator it = values().iterator(); it.hasNext();) {
135
					unhookListener(it.next());
136
				}
137
				listener = null;
138
			}
139
			detailProperty = null;
140
		}
141
142
		super.dispose();
143
	}
144
}
(-)src/org/eclipse/core/internal/databinding/property/SetPropertyDetailValuesMap.java (+66 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.property;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.map.IObservableMap;
17
import org.eclipse.core.databinding.observable.set.IObservableSet;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.core.databinding.property.map.MapProperty;
20
import org.eclipse.core.databinding.property.set.ISetProperty;
21
import org.eclipse.core.databinding.property.value.IValueProperty;
22
23
/**
24
 * @since 3.3
25
 * 
26
 */
27
public class SetPropertyDetailValuesMap extends MapProperty {
28
	private final ISetProperty masterProperty;
29
	private final IValueProperty detailProperty;
30
31
	/**
32
	 * @param masterProperty
33
	 * @param detailProperty
34
	 */
35
	public SetPropertyDetailValuesMap(ISetProperty masterProperty,
36
			IValueProperty detailProperty) {
37
		this.masterProperty = masterProperty;
38
		this.detailProperty = detailProperty;
39
	}
40
41
	public Object getKeyType() {
42
		return masterProperty.getElementType();
43
	}
44
45
	public Object getValueType() {
46
		return detailProperty.getValueType();
47
	}
48
49
	public IObservableMap observe(Realm realm, Object source) {
50
		IObservableSet masterSet = masterProperty.observe(realm, source);
51
		IObservableMap detailMap = detailProperty.observeDetail(masterSet);
52
		PropertyObservableUtil.cascadeDispose(detailMap, masterSet);
53
		return detailMap;
54
	}
55
56
	public IObservableMap observeDetail(IObservableValue master) {
57
		IObservableSet masterSet = masterProperty.observeDetail(master);
58
		IObservableMap detailMap = detailProperty.observeDetail(masterSet);
59
		PropertyObservableUtil.cascadeDispose(detailMap, masterSet);
60
		return detailMap;
61
	}
62
63
	public String toString() {
64
		return masterProperty + " => " + detailProperty; //$NON-NLS-1$
65
	}
66
}
(-)src/org/eclipse/core/databinding/property/package.html (+42 lines)
Added Link Here
1
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
2
<html>
3
<head>
4
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5
   <meta name="Author" content="Matthew Hall">
6
   <title>Package-level Javadoc</title>
7
</head>
8
<body>
9
Interfaces and classes for representing and observing properties of objects.
10
<h2>
11
Package Specification</h2>
12
<p>
13
This package and its subpackages provide the <tt>IProperty</tt>,
14
<tt>IValueProperty</tt>, <tt>IListProperty</tt>, <tt>ISetProperty</tt> and
15
<tt>IMapProperty</tt> interfaces, along with classes
16
which serve as base implementations of each interface.    
17
<p>
18
Properties are intended to serve as a convenient path to creating observables
19
for observing specific attributes of source objects.  The main goals of this
20
API are:
21
<ul>
22
<li>Simplify the process of creating custom observables.  Developing custom
23
observables correctly can be tricky, so the properties API tries to ease this
24
burden by providing all the observable implementations.  Property implementers
25
only need to extend one of the provided base classes
26
(<tt>SimpleValueProperty</tt>, <tt>SimpleListProperty</tt>,
27
<tt>SimpleSetProperty</tt> or <tt>SimpleMapProperty</tt>) and implement a
28
handful of abstract methods which the observables use to function.
29
<li>Simplify observation of nested properties.  Traditionally observing a
30
nested property required creating an observable for the first property, then
31
wrapping that observable in a master-detail observable for each successive
32
property in the chain.  Using property chaining it is trivial to define a
33
nested property and to observe that property on a particular source object.
34
</ul>
35
<p>
36
A set of delegating properties are also provided
37
(<tt>DelegatingValueProperty</tt>, <tt>DelegatingListProperty</tt>,
38
<tt>DelegatingSetProperty</tt> and <tt>DelegatingMapProperty</tt>) which
39
may be used to implement properties where the property behavior depends on the
40
type of source object.
41
</body>
42
</html>
(-)src/org/eclipse/core/databinding/property/list/ListProperty.java (+58 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.list;
14
15
import org.eclipse.core.databinding.observable.IObservable;
16
import org.eclipse.core.databinding.observable.Realm;
17
import org.eclipse.core.databinding.observable.list.IObservableList;
18
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
19
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
20
import org.eclipse.core.databinding.observable.value.IObservableValue;
21
import org.eclipse.core.databinding.property.value.IValueProperty;
22
import org.eclipse.core.internal.databinding.property.ListPropertyDetailValuesList;
23
24
/**
25
 * Abstract implementation of IListProperty.
26
 * 
27
 * @since 1.2
28
 */
29
public abstract class ListProperty implements IListProperty {
30
	public IObservableList observe(Object source) {
31
		return observe(Realm.getDefault(), source);
32
	}
33
34
	public IObservableFactory listFactory() {
35
		return new IObservableFactory() {
36
			public IObservable createObservable(Object target) {
37
				return observe(target);
38
			}
39
		};
40
	}
41
42
	public IObservableFactory listFactory(final Realm realm) {
43
		return new IObservableFactory() {
44
			public IObservable createObservable(Object target) {
45
				return observe(realm, target);
46
			}
47
		};
48
	}
49
50
	public IObservableList observeDetail(IObservableValue master) {
51
		return MasterDetailObservables.detailList(master, listFactory(master
52
				.getRealm()), getElementType());
53
	}
54
55
	public final IListProperty values(IValueProperty detailValue) {
56
		return new ListPropertyDetailValuesList(this, detailValue);
57
	}
58
}
(-)src/org/eclipse/core/databinding/property/ISimplePropertyListener.java (+30 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - but 194734
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property;
14
15
/**
16
 * Listener for changes to properties on a particular source object
17
 * 
18
 * @noextend This interface is not intended to be extended by clients.
19
 * 
20
 * @since 1.2
21
 */
22
public interface ISimplePropertyListener {
23
	/**
24
	 * Handle the property change described in the event.
25
	 * 
26
	 * @param event
27
	 *            an event describing the property change that occured.
28
	 */
29
	public void handlePropertyChange(SimplePropertyEvent event);
30
}
(-)src/org/eclipse/core/internal/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java (+375 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.value;
13
14
import java.util.AbstractSet;
15
import java.util.Collections;
16
import java.util.HashMap;
17
import java.util.HashSet;
18
import java.util.Iterator;
19
import java.util.Map;
20
import java.util.Set;
21
22
import org.eclipse.core.databinding.observable.Diffs;
23
import org.eclipse.core.databinding.observable.IStaleListener;
24
import org.eclipse.core.databinding.observable.ObservableTracker;
25
import org.eclipse.core.databinding.observable.StaleEvent;
26
import org.eclipse.core.databinding.observable.map.AbstractObservableMap;
27
import org.eclipse.core.databinding.observable.map.IMapChangeListener;
28
import org.eclipse.core.databinding.observable.map.IObservableMap;
29
import org.eclipse.core.databinding.observable.map.MapChangeEvent;
30
import org.eclipse.core.databinding.observable.map.MapDiff;
31
import org.eclipse.core.databinding.observable.set.IObservableSet;
32
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
33
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
34
import org.eclipse.core.databinding.observable.set.WritableSet;
35
import org.eclipse.core.databinding.property.INativePropertyListener;
36
import org.eclipse.core.databinding.property.IProperty;
37
import org.eclipse.core.databinding.property.IPropertyObservable;
38
import org.eclipse.core.databinding.property.ISimplePropertyListener;
39
import org.eclipse.core.databinding.property.SimplePropertyEvent;
40
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
41
import org.eclipse.core.internal.databinding.IdentityWrapper;
42
import org.eclipse.core.internal.databinding.Util;
43
44
/**
45
 * @since 1.2
46
 * 
47
 */
48
public class ObservableMapSimpleValuePropertyObservableMap extends
49
		AbstractObservableMap implements IPropertyObservable {
50
	private IObservableMap masterMap;
51
	private SimpleValueProperty detailProperty;
52
53
	private IObservableSet knownMasterValues;
54
	private Map cachedValues;
55
56
	private boolean updating = false;
57
58
	private IMapChangeListener masterListener = new IMapChangeListener() {
59
		public void handleMapChange(final MapChangeEvent event) {
60
			if (!isDisposed()) {
61
				updateKnownValues();
62
				if (!updating)
63
					fireMapChange(convertDiff(event.diff));
64
			}
65
		}
66
67
		private void updateKnownValues() {
68
			Set identityKnownValues = new HashSet();
69
			for (Iterator it = masterMap.values().iterator(); it.hasNext();) {
70
				identityKnownValues.add(new IdentityWrapper(it.next()));
71
			}
72
73
			knownMasterValues.retainAll(identityKnownValues);
74
			knownMasterValues.addAll(identityKnownValues);
75
		}
76
77
		private MapDiff convertDiff(MapDiff diff) {
78
			Map oldValues = new HashMap();
79
			Map newValues = new HashMap();
80
81
			Set addedKeys = diff.getAddedKeys();
82
			for (Iterator it = addedKeys.iterator(); it.hasNext();) {
83
				Object key = it.next();
84
				Object newSource = diff.getNewValue(key);
85
				Object newValue = detailProperty.getValue(newSource);
86
				newValues.put(key, newValue);
87
			}
88
89
			Set removedKeys = diff.getRemovedKeys();
90
			for (Iterator it = removedKeys.iterator(); it.hasNext();) {
91
				Object key = it.next();
92
				Object oldSource = diff.getOldValue(key);
93
				Object oldValue = detailProperty.getValue(oldSource);
94
				oldValues.put(key, oldValue);
95
			}
96
97
			Set changedKeys = new HashSet(diff.getChangedKeys());
98
			for (Iterator it = changedKeys.iterator(); it.hasNext();) {
99
				Object key = it.next();
100
101
				Object oldSource = diff.getOldValue(key);
102
				Object newSource = diff.getNewValue(key);
103
104
				Object oldValue = detailProperty.getValue(oldSource);
105
				Object newValue = detailProperty.getValue(newSource);
106
107
				if (Util.equals(oldValue, newValue)) {
108
					it.remove();
109
				} else {
110
					oldValues.put(key, oldValue);
111
					newValues.put(key, newValue);
112
				}
113
			}
114
115
			return Diffs.createMapDiff(addedKeys, removedKeys, changedKeys,
116
					oldValues, newValues);
117
		}
118
	};
119
120
	private IStaleListener staleListener = new IStaleListener() {
121
		public void handleStale(StaleEvent staleEvent) {
122
			fireStale();
123
		}
124
	};
125
126
	private INativePropertyListener detailListener;
127
128
	/**
129
	 * @param map
130
	 * @param valueProperty
131
	 */
132
	public ObservableMapSimpleValuePropertyObservableMap(IObservableMap map,
133
			SimpleValueProperty valueProperty) {
134
		super(map.getRealm());
135
		this.masterMap = map;
136
		this.detailProperty = valueProperty;
137
138
		ISimplePropertyListener listener = new ISimplePropertyListener() {
139
			public void handlePropertyChange(SimplePropertyEvent event) {
140
				notifyIfChanged(event.getSource());
141
			}
142
		};
143
		this.detailListener = detailProperty.adaptListener(listener);
144
	}
145
146
	protected void firstListenerAdded() {
147
		knownMasterValues = new WritableSet(getRealm());
148
		cachedValues = new HashMap();
149
		knownMasterValues.addSetChangeListener(new ISetChangeListener() {
150
			public void handleSetChange(SetChangeEvent event) {
151
				for (Iterator it = event.diff.getRemovals().iterator(); it
152
						.hasNext();) {
153
					IdentityWrapper wrapper = (IdentityWrapper) it.next();
154
					Object key = wrapper.unwrap();
155
					detailProperty.removeListener(key, detailListener);
156
					cachedValues.remove(wrapper);
157
				}
158
				for (Iterator it = event.diff.getAdditions().iterator(); it
159
						.hasNext();) {
160
					IdentityWrapper wrapper = (IdentityWrapper) it.next();
161
					Object key = wrapper.unwrap();
162
					cachedValues.put(wrapper, detailProperty.getValue(key));
163
					detailProperty.addListener(key, detailListener);
164
				}
165
			}
166
		});
167
		for (Iterator it = masterMap.values().iterator(); it.hasNext();) {
168
			knownMasterValues.add(new IdentityWrapper(it.next()));
169
		}
170
171
		masterMap.addMapChangeListener(masterListener);
172
		masterMap.addStaleListener(staleListener);
173
	}
174
175
	protected void lastListenerRemoved() {
176
		masterMap.removeMapChangeListener(masterListener);
177
		masterMap.removeStaleListener(staleListener);
178
		if (knownMasterValues != null) {
179
			knownMasterValues.clear(); // removes attached listeners
180
			knownMasterValues.dispose();
181
			knownMasterValues = null;
182
		}
183
		cachedValues.clear();
184
		cachedValues = null;
185
	}
186
187
	private Set entrySet;
188
189
	public Set entrySet() {
190
		getterCalled();
191
		if (entrySet == null)
192
			entrySet = new EntrySet();
193
		return entrySet;
194
	}
195
196
	class EntrySet extends AbstractSet {
197
		public Iterator iterator() {
198
			return new Iterator() {
199
				Iterator it = masterMap.entrySet().iterator();
200
201
				public boolean hasNext() {
202
					getterCalled();
203
					return it.hasNext();
204
				}
205
206
				public Object next() {
207
					getterCalled();
208
					Map.Entry next = (Map.Entry) it.next();
209
					return new MapEntry(next.getKey());
210
				}
211
212
				public void remove() {
213
					it.remove();
214
				}
215
			};
216
		}
217
218
		public int size() {
219
			return masterMap.size();
220
		}
221
	}
222
223
	class MapEntry implements Map.Entry {
224
		private Object key;
225
226
		MapEntry(Object key) {
227
			this.key = key;
228
		}
229
230
		public Object getKey() {
231
			getterCalled();
232
			return key;
233
		}
234
235
		public Object getValue() {
236
			getterCalled();
237
			if (!masterMap.containsKey(key))
238
				return null;
239
			return detailProperty.getValue(masterMap.get(key));
240
		}
241
242
		public Object setValue(Object value) {
243
			if (!masterMap.containsKey(key))
244
				return null;
245
			Object source = masterMap.get(key);
246
247
			Object oldValue = detailProperty.getValue(source);
248
249
			updating = true;
250
			try {
251
				detailProperty.setValue(source, value);
252
			} finally {
253
				updating = false;
254
			}
255
256
			notifyIfChanged(source);
257
258
			return oldValue;
259
		}
260
261
		public boolean equals(Object o) {
262
			getterCalled();
263
			if (o == this)
264
				return true;
265
			if (o == null)
266
				return false;
267
			if (!(o instanceof Map.Entry))
268
				return false;
269
			Map.Entry that = (Map.Entry) o;
270
			return Util.equals(this.getKey(), that.getKey())
271
					&& Util.equals(this.getValue(), that.getValue());
272
		}
273
274
		public int hashCode() {
275
			getterCalled();
276
			Object value = getValue();
277
			return (key == null ? 0 : key.hashCode())
278
					^ (value == null ? 0 : value.hashCode());
279
		}
280
	}
281
282
	public Object put(Object key, Object value) {
283
		if (!masterMap.containsKey(key))
284
			return null;
285
		Object masterValue = masterMap.get(key);
286
		Object oldValue = detailProperty.getValue(key);
287
		detailProperty.setValue(masterValue, value);
288
		notifyIfChanged(masterValue);
289
		return oldValue;
290
	}
291
292
	private void notifyIfChanged(Object masterValue) {
293
		if (cachedValues != null) {
294
			final Set keys = keysFor(masterValue);
295
296
			final Object oldValue = cachedValues.get(new IdentityWrapper(
297
					masterValue));
298
			final Object newValue = detailProperty.getValue(masterValue);
299
300
			if (!Util.equals(oldValue, newValue)) {
301
				cachedValues.put(new IdentityWrapper(masterValue), newValue);
302
				fireMapChange(new MapDiff() {
303
					public Set getAddedKeys() {
304
						return Collections.EMPTY_SET;
305
					}
306
307
					public Set getChangedKeys() {
308
						return keys;
309
					}
310
311
					public Set getRemovedKeys() {
312
						return Collections.EMPTY_SET;
313
					}
314
315
					public Object getNewValue(Object key) {
316
						return newValue;
317
					}
318
319
					public Object getOldValue(Object key) {
320
						return oldValue;
321
					}
322
				});
323
			}
324
		}
325
	}
326
327
	private Set keysFor(Object value) {
328
		Set keys = new HashSet();
329
330
		for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) {
331
			Map.Entry entry = (Entry) it.next();
332
			if (entry.getValue() == value) {
333
				keys.add(entry.getKey());
334
			}
335
		}
336
337
		return keys;
338
	}
339
340
	public boolean isStale() {
341
		getterCalled();
342
		return masterMap.isStale();
343
	}
344
345
	private void getterCalled() {
346
		ObservableTracker.getterCalled(this);
347
	}
348
349
	public Object getObserved() {
350
		return masterMap;
351
	}
352
353
	public IProperty getProperty() {
354
		return detailProperty;
355
	}
356
357
	public synchronized void dispose() {
358
		if (masterMap != null) {
359
			masterMap.removeMapChangeListener(masterListener);
360
			masterMap = null;
361
		}
362
		if (knownMasterValues != null) {
363
			knownMasterValues.clear(); // detaches listeners
364
			knownMasterValues.dispose();
365
			knownMasterValues = null;
366
		}
367
368
		masterListener = null;
369
		detailListener = null;
370
		detailProperty = null;
371
		cachedValues = null;
372
373
		super.dispose();
374
	}
375
}
(-)src/org/eclipse/core/databinding/property/map/MapProperty.java (+58 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.map;
14
15
import org.eclipse.core.databinding.observable.IObservable;
16
import org.eclipse.core.databinding.observable.Realm;
17
import org.eclipse.core.databinding.observable.map.IObservableMap;
18
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
19
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
20
import org.eclipse.core.databinding.observable.value.IObservableValue;
21
import org.eclipse.core.databinding.property.value.IValueProperty;
22
import org.eclipse.core.internal.databinding.property.MapPropertyDetailValuesMap;
23
24
/**
25
 * Abstract implementation of IMapProperty
26
 * 
27
 * @since 1.2
28
 */
29
public abstract class MapProperty implements IMapProperty {
30
	public IObservableMap observe(Object source) {
31
		return observe(Realm.getDefault(), source);
32
	}
33
34
	public IObservableFactory mapFactory() {
35
		return new IObservableFactory() {
36
			public IObservable createObservable(Object target) {
37
				return observe(target);
38
			}
39
		};
40
	}
41
42
	public IObservableFactory mapFactory(final Realm realm) {
43
		return new IObservableFactory() {
44
			public IObservable createObservable(Object target) {
45
				return observe(realm, target);
46
			}
47
		};
48
	}
49
50
	public IObservableMap observeDetail(IObservableValue master) {
51
		return MasterDetailObservables.detailMap(master, mapFactory(master
52
				.getRealm()), getKeyType(), getValueType());
53
	}
54
55
	public final IMapProperty values(IValueProperty detailValues) {
56
		return new MapPropertyDetailValuesMap(this, detailValues);
57
	}
58
}
(-)src/org/eclipse/core/databinding/property/set/SetProperty.java (+59 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.set;
14
15
import org.eclipse.core.databinding.observable.IObservable;
16
import org.eclipse.core.databinding.observable.Realm;
17
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
18
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
19
import org.eclipse.core.databinding.observable.set.IObservableSet;
20
import org.eclipse.core.databinding.observable.value.IObservableValue;
21
import org.eclipse.core.databinding.property.map.IMapProperty;
22
import org.eclipse.core.databinding.property.value.IValueProperty;
23
import org.eclipse.core.internal.databinding.property.SetPropertyDetailValuesMap;
24
25
/**
26
 * Abstract implementation of ISetProperty
27
 * 
28
 * @since 1.2
29
 */
30
public abstract class SetProperty implements ISetProperty {
31
	public IObservableSet observe(Object source) {
32
		return observe(Realm.getDefault(), source);
33
	}
34
35
	public IObservableFactory setFactory() {
36
		return new IObservableFactory() {
37
			public IObservable createObservable(Object target) {
38
				return observe(target);
39
			}
40
		};
41
	}
42
43
	public IObservableFactory setFactory(final Realm realm) {
44
		return new IObservableFactory() {
45
			public IObservable createObservable(Object target) {
46
				return observe(realm, target);
47
			}
48
		};
49
	}
50
51
	public IObservableSet observeDetail(IObservableValue master) {
52
		return MasterDetailObservables.detailSet(master, setFactory(master
53
				.getRealm()), getElementType());
54
	}
55
56
	public final IMapProperty values(IValueProperty detailValues) {
57
		return new SetPropertyDetailValuesMap(this, detailValues);
58
	}
59
}
(-)src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java (+186 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222, 247997
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.value;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
17
import org.eclipse.core.databinding.observable.map.IObservableMap;
18
import org.eclipse.core.databinding.observable.set.IObservableSet;
19
import org.eclipse.core.databinding.observable.value.IObservableValue;
20
import org.eclipse.core.databinding.property.INativePropertyListener;
21
import org.eclipse.core.databinding.property.ISimplePropertyListener;
22
import org.eclipse.core.internal.databinding.property.value.ObservableListSimpleValuePropertyObservableList;
23
import org.eclipse.core.internal.databinding.property.value.ObservableMapSimpleValuePropertyObservableMap;
24
import org.eclipse.core.internal.databinding.property.value.ObservableSetSimpleValuePropertyObservableMap;
25
import org.eclipse.core.internal.databinding.property.value.SimpleValuePropertyObservableValue;
26
27
/**
28
 * Simplified abstract implementation of IValueProperty. This class takes care
29
 * of most of the functional requirements for an IValueProperty implementation,
30
 * leaving only the property-specific details to subclasses.
31
 * <p>
32
 * Subclasses must implement these methods:
33
 * <ul>
34
 * <li> {@link #getValueType()}
35
 * <li> {@link #doGetValue(Object)}
36
 * <li> {@link #doSetValue(Object, Object)}
37
 * <li> {@link #adaptListener(ISimplePropertyListener)}
38
 * <li> {@link #doAddListener(Object, INativePropertyListener)}
39
 * <li> {@link #doRemoveListener(Object, INativePropertyListener)}
40
 * </ul>
41
 * <p>
42
 * In addition, we recommended overriding {@link #toString()} to return a
43
 * description suitable for debugging purposes.
44
 * 
45
 * @since 1.2
46
 */
47
public abstract class SimpleValueProperty extends ValueProperty {
48
	/**
49
	 * Returns the value of the property on the specified source object
50
	 * 
51
	 * @param source
52
	 *            the property source (may be null)
53
	 * @return the current value of the source's value property
54
	 * @noreference This method is not intended to be referenced by clients.
55
	 */
56
	public final Object getValue(Object source) {
57
		return source == null ? null : doGetValue(source);
58
	}
59
60
	/**
61
	 * Returns the value of the property on the specified source object
62
	 * 
63
	 * @param source
64
	 *            the property source
65
	 * @return the current value of the source's value property
66
	 * @noreference This method is not intended to be referenced by clients.
67
	 */
68
	protected abstract Object doGetValue(Object source);
69
70
	/**
71
	 * Sets the source's value property to the specified value
72
	 * 
73
	 * @param source
74
	 *            the property source
75
	 * @param value
76
	 *            the new value
77
	 * @noreference This method is not intended to be referenced by clients.
78
	 */
79
	public final void setValue(Object source, Object value) {
80
		if (source != null)
81
			doSetValue(source, value);
82
	}
83
84
	protected abstract void doSetValue(Object source, Object value);
85
86
	/**
87
	 * Returns a listener which implements the correct listener interface for
88
	 * the expected source object, and which parlays property change events from
89
	 * the source object to the given listener. If there is no listener API for
90
	 * this property, this method returns null.
91
	 * 
92
	 * @param listener
93
	 *            the property listener to receive events
94
	 * @return a native listener which parlays property change events to the
95
	 *         specified listener.
96
	 * @noreference This method is not intended to be referenced by clients.
97
	 */
98
	public abstract INativePropertyListener adaptListener(
99
			ISimplePropertyListener listener);
100
101
	/**
102
	 * Adds the specified listener as a listener for this property on the
103
	 * specified property source. If the source object has no listener API for
104
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
105
	 * returns null), this method does nothing.
106
	 * 
107
	 * @param source
108
	 *            the property source
109
	 * @param listener
110
	 *            a listener obtained from calling
111
	 *            {@link #adaptListener(ISimplePropertyListener)}.
112
	 * @noreference This method is not intended to be referenced by clients.
113
	 */
114
	public final void addListener(Object source,
115
			INativePropertyListener listener) {
116
		if (source != null)
117
			doAddListener(source, listener);
118
	}
119
120
	/**
121
	 * Adds the specified listener as a listener for this property on the
122
	 * specified property source. If the source object has no listener API for
123
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
124
	 * returns null), this method does nothing.
125
	 * 
126
	 * @param source
127
	 *            the property source
128
	 * @param listener
129
	 *            a listener obtained from calling
130
	 *            {@link #adaptListener(ISimplePropertyListener)}.
131
	 * @noreference This method is not intended to be referenced by clients.
132
	 */
133
	protected abstract void doAddListener(Object source,
134
			INativePropertyListener listener);
135
136
	/**
137
	 * Removes the specified listener as a listener for this property on the
138
	 * specified property source. If the source object has no listener API for
139
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
140
	 * returns null), this method does nothing.
141
	 * 
142
	 * @param source
143
	 *            the property source
144
	 * @param listener
145
	 *            a listener obtained from calling
146
	 *            {@link #adaptListener(ISimplePropertyListener)}.
147
	 * @noreference This method is not intended to be referenced by clients.
148
	 */
149
	public final void removeListener(Object source,
150
			INativePropertyListener listener) {
151
		if (source != null)
152
			doRemoveListener(source, listener);
153
	}
154
155
	/**
156
	 * Removes the specified listener as a listener for this property on the
157
	 * specified property source. If the source object has no listener API for
158
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
159
	 * returns null), this method does nothing.
160
	 * 
161
	 * @param source
162
	 *            the property source
163
	 * @param listener
164
	 *            a listener obtained from calling
165
	 *            {@link #adaptListener(ISimplePropertyListener)}.
166
	 * @noreference This method is not intended to be referenced by clients.
167
	 */
168
	protected abstract void doRemoveListener(Object source,
169
			INativePropertyListener listener);
170
171
	public IObservableValue observe(Realm realm, Object source) {
172
		return new SimpleValuePropertyObservableValue(realm, source, this);
173
	}
174
175
	public IObservableList observeDetail(IObservableList master) {
176
		return new ObservableListSimpleValuePropertyObservableList(master, this);
177
	}
178
179
	public IObservableMap observeDetail(IObservableSet master) {
180
		return new ObservableSetSimpleValuePropertyObservableMap(master, this);
181
	}
182
183
	public IObservableMap observeDetail(IObservableMap master) {
184
		return new ObservableMapSimpleValuePropertyObservableMap(master, this);
185
	}
186
}
(-)src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailList.java (+61 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.property;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.list.IObservableList;
17
import org.eclipse.core.databinding.observable.value.IObservableValue;
18
import org.eclipse.core.databinding.property.list.IListProperty;
19
import org.eclipse.core.databinding.property.list.ListProperty;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class ValuePropertyDetailList extends ListProperty {
27
	private final IValueProperty masterProperty;
28
	private final IListProperty detailProperty;
29
30
	/**
31
	 * @param masterProperty
32
	 * @param detailProperty
33
	 */
34
	public ValuePropertyDetailList(IValueProperty masterProperty,
35
			IListProperty detailProperty) {
36
		this.masterProperty = masterProperty;
37
		this.detailProperty = detailProperty;
38
	}
39
40
	public Object getElementType() {
41
		return detailProperty.getElementType();
42
	}
43
44
	public IObservableList observe(Realm realm, Object source) {
45
		IObservableValue masterValue = masterProperty.observe(realm, source);
46
		IObservableList detailList = detailProperty.observeDetail(masterValue);
47
		PropertyObservableUtil.cascadeDispose(detailList, masterValue);
48
		return detailList;
49
	}
50
51
	public IObservableList observeDetail(IObservableValue master) {
52
		IObservableValue masterValue = masterProperty.observeDetail(master);
53
		IObservableList detailList = detailProperty.observeDetail(masterValue);
54
		PropertyObservableUtil.cascadeDispose(detailList, masterValue);
55
		return detailList;
56
	}
57
58
	public String toString() {
59
		return masterProperty + " => " + detailProperty; //$NON-NLS-1$
60
	}
61
}
(-)src/org/eclipse/core/internal/databinding/property/value/SimpleValuePropertyObservableValue.java (+131 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.value;
13
14
import org.eclipse.core.databinding.observable.Diffs;
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
17
import org.eclipse.core.databinding.observable.value.ValueDiff;
18
import org.eclipse.core.databinding.property.INativePropertyListener;
19
import org.eclipse.core.databinding.property.IProperty;
20
import org.eclipse.core.databinding.property.IPropertyObservable;
21
import org.eclipse.core.databinding.property.ISimplePropertyListener;
22
import org.eclipse.core.databinding.property.SimplePropertyEvent;
23
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
24
import org.eclipse.core.internal.databinding.Util;
25
26
/**
27
 * @since 1.2
28
 * 
29
 */
30
public class SimpleValuePropertyObservableValue extends AbstractObservableValue
31
		implements IPropertyObservable {
32
	private Object source;
33
	private SimpleValueProperty property;
34
35
	private boolean updating = false;
36
	private Object cachedValue;
37
38
	private INativePropertyListener listener;
39
40
	/**
41
	 * @param realm
42
	 * @param source
43
	 * @param property
44
	 */
45
	public SimpleValuePropertyObservableValue(Realm realm, Object source,
46
			SimpleValueProperty property) {
47
		super(realm);
48
		this.source = source;
49
		this.property = property;
50
	}
51
52
	protected void firstListenerAdded() {
53
		if (!isDisposed()) {
54
			cachedValue = property.getValue(source);
55
			if (listener == null) {
56
				listener = property
57
						.adaptListener(new ISimplePropertyListener() {
58
							public void handlePropertyChange(
59
									final SimplePropertyEvent event) {
60
								if (!isDisposed() && !updating) {
61
									getRealm().exec(new Runnable() {
62
										public void run() {
63
											notifyIfChanged((ValueDiff) event.diff);
64
										}
65
									});
66
								}
67
							}
68
						});
69
			}
70
			property.addListener(source, listener);
71
		}
72
	}
73
74
	protected void lastListenerRemoved() {
75
		if (listener != null) {
76
			property.removeListener(source, listener);
77
		}
78
		cachedValue = null;
79
	}
80
81
	protected Object doGetValue() {
82
		notifyIfChanged(null);
83
		return property.getValue(source);
84
	}
85
86
	protected void doSetValue(Object value) {
87
		updating = true;
88
		try {
89
			property.setValue(source, value);
90
		} finally {
91
			updating = false;
92
		}
93
94
		notifyIfChanged(null);
95
	}
96
97
	private void notifyIfChanged(ValueDiff diff) {
98
		if (hasListeners()) {
99
			Object oldValue = cachedValue;
100
			Object newValue = cachedValue = property.getValue(source);
101
			if (diff == null)
102
				diff = Diffs.createValueDiff(oldValue, newValue);
103
			if (hasListeners() && !Util.equals(oldValue, newValue)) {
104
				fireValueChange(diff);
105
			}
106
		}
107
	}
108
109
	public Object getValueType() {
110
		return property.getValueType();
111
	}
112
113
	public Object getObserved() {
114
		return source;
115
	}
116
117
	public IProperty getProperty() {
118
		return property;
119
	}
120
121
	public synchronized void dispose() {
122
		if (!isDisposed()) {
123
			if (listener != null)
124
				property.removeListener(source, listener);
125
			source = null;
126
			property = null;
127
			listener = null;
128
		}
129
		super.dispose();
130
	}
131
}
(-)src/org/eclipse/core/databinding/property/map/DelegatingMapProperty.java (+111 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.property.map;
13
14
import java.util.Collections;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.map.IObservableMap;
19
import org.eclipse.core.databinding.observable.map.MapDiff;
20
import org.eclipse.core.databinding.property.INativePropertyListener;
21
import org.eclipse.core.databinding.property.ISimplePropertyListener;
22
23
/**
24
 * @since 1.2
25
 * 
26
 */
27
public abstract class DelegatingMapProperty extends MapProperty {
28
	private final Object keyType;
29
	private final Object valueType;
30
	private final IMapProperty nullProperty = new NullMapProperty();
31
32
	protected DelegatingMapProperty() {
33
		this(null, null);
34
	}
35
36
	protected DelegatingMapProperty(Object keyType, Object valueType) {
37
		this.keyType = keyType;
38
		this.valueType = valueType;
39
	}
40
41
	/**
42
	 * Returns the property to delegate to for the specified source object.
43
	 * Repeated calls to this method with the same source object returns the
44
	 * same delegate instance.
45
	 * 
46
	 * @param source
47
	 *            the property source (may be null)
48
	 * @return the property to delegate to for the specified source object.
49
	 */
50
	public final IMapProperty getDelegate(Object source) {
51
		if (source == null)
52
			return null;
53
		IMapProperty delegate = doGetDelegate(source);
54
		if (delegate == null)
55
			delegate = nullProperty;
56
		return delegate;
57
	}
58
59
	/**
60
	 * Returns the property to delegate to for the specified source object.
61
	 * Implementers must ensure that repeated calls to this method with the same
62
	 * source object returns the same delegate instance.
63
	 * 
64
	 * @param source
65
	 *            the property source
66
	 * @return the property to delegate to for the specified source object.
67
	 */
68
	protected abstract IMapProperty doGetDelegate(Object source);
69
70
	public Object getKeyType() {
71
		return keyType;
72
	}
73
74
	public Object getValueType() {
75
		return valueType;
76
	}
77
78
	public IObservableMap observe(Realm realm, Object source) {
79
		return getDelegate(source).observe(realm, source);
80
	}
81
82
	private class NullMapProperty extends SimpleMapProperty {
83
		protected Map doGetMap(Object source) {
84
			return Collections.EMPTY_MAP;
85
		}
86
87
		protected void doSetMap(Object source, Map map, MapDiff diff) {
88
		}
89
90
		public INativePropertyListener adaptListener(
91
				ISimplePropertyListener listener) {
92
			return null;
93
		}
94
95
		protected void doAddListener(Object source,
96
				INativePropertyListener listener) {
97
		}
98
99
		protected void doRemoveListener(Object source,
100
				INativePropertyListener listener) {
101
		}
102
103
		public Object getKeyType() {
104
			return keyType;
105
		}
106
107
		public Object getValueType() {
108
			return valueType;
109
		}
110
	}
111
}
(-)src/org/eclipse/core/internal/databinding/property/list/SimpleListPropertyObservableList.java (+667 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.list;
13
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.Collections;
17
import java.util.ConcurrentModificationException;
18
import java.util.Iterator;
19
import java.util.List;
20
import java.util.ListIterator;
21
22
import org.eclipse.core.databinding.observable.Diffs;
23
import org.eclipse.core.databinding.observable.ObservableTracker;
24
import org.eclipse.core.databinding.observable.Realm;
25
import org.eclipse.core.databinding.observable.list.AbstractObservableList;
26
import org.eclipse.core.databinding.observable.list.ListDiff;
27
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
28
import org.eclipse.core.databinding.property.INativePropertyListener;
29
import org.eclipse.core.databinding.property.IProperty;
30
import org.eclipse.core.databinding.property.IPropertyObservable;
31
import org.eclipse.core.databinding.property.ISimplePropertyListener;
32
import org.eclipse.core.databinding.property.SimplePropertyEvent;
33
import org.eclipse.core.databinding.property.list.SimpleListProperty;
34
35
/**
36
 * @since 1.2
37
 * 
38
 */
39
public class SimpleListPropertyObservableList extends AbstractObservableList
40
		implements IPropertyObservable {
41
	private Object source;
42
	private SimpleListProperty property;
43
44
	private volatile boolean updating = false;
45
46
	private volatile int modCount = 0;
47
48
	private INativePropertyListener listener;
49
50
	private List cachedList;
51
52
	/**
53
	 * @param realm
54
	 * @param source
55
	 * @param property
56
	 */
57
	public SimpleListPropertyObservableList(Realm realm, Object source,
58
			SimpleListProperty property) {
59
		super(realm);
60
		this.source = source;
61
		this.property = property;
62
	}
63
64
	protected void firstListenerAdded() {
65
		if (!isDisposed()) {
66
			cachedList = getList();
67
68
			if (listener == null) {
69
				listener = property
70
						.adaptListener(new ISimplePropertyListener() {
71
							public void handlePropertyChange(
72
									final SimplePropertyEvent event) {
73
								modCount++;
74
								if (!isDisposed() && !updating) {
75
									getRealm().exec(new Runnable() {
76
										public void run() {
77
											notifyIfChanged((ListDiff) event.diff);
78
										}
79
									});
80
								}
81
							}
82
						});
83
			}
84
			property.addListener(source, listener);
85
		}
86
	}
87
88
	protected void lastListenerRemoved() {
89
		if (listener != null) {
90
			property.removeListener(source, listener);
91
		}
92
93
		cachedList = null;
94
	}
95
96
	private void getterCalled() {
97
		ObservableTracker.getterCalled(this);
98
	}
99
100
	public Object getElementType() {
101
		return property.getElementType();
102
	}
103
104
	// Queries
105
106
	private List getList() {
107
		return property.getList(source);
108
	}
109
110
	protected int doGetSize() {
111
		return getList().size();
112
	}
113
114
	public boolean contains(Object o) {
115
		getterCalled();
116
		return getList().contains(o);
117
	}
118
119
	public boolean containsAll(Collection c) {
120
		getterCalled();
121
		return getList().containsAll(c);
122
	}
123
124
	public Object get(int index) {
125
		getterCalled();
126
		return getList().get(index);
127
	}
128
129
	public int indexOf(Object o) {
130
		getterCalled();
131
		return getList().indexOf(o);
132
	}
133
134
	public boolean isEmpty() {
135
		getterCalled();
136
		return getList().isEmpty();
137
	}
138
139
	public int lastIndexOf(Object o) {
140
		getterCalled();
141
		return getList().lastIndexOf(o);
142
	}
143
144
	public Object[] toArray() {
145
		getterCalled();
146
		return getList().toArray();
147
	}
148
149
	public Object[] toArray(Object[] a) {
150
		getterCalled();
151
		return getList().toArray(a);
152
	}
153
154
	// Single change operations
155
156
	public boolean add(Object o) {
157
		checkRealm();
158
		add(getList().size(), o);
159
		return true;
160
	}
161
162
	public void add(int index, Object o) {
163
		checkRealm();
164
		boolean wasUpdating = updating;
165
		updating = true;
166
		List list = new ArrayList(getList());
167
		list.add(index, o);
168
		ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index,
169
				true, o));
170
		try {
171
			property.setList(source, list, diff);
172
			modCount++;
173
		} finally {
174
			updating = wasUpdating;
175
		}
176
177
		notifyIfChanged(null);
178
	}
179
180
	public Iterator iterator() {
181
		getterCalled();
182
		return new Iterator() {
183
			int expectedModCount = modCount;
184
			List list = new ArrayList(getList());
185
			ListIterator iterator = list.listIterator();
186
187
			Object lastElement = null;
188
			int lastIndex = -1;
189
190
			public boolean hasNext() {
191
				getterCalled();
192
				checkForComodification();
193
				return iterator.hasNext();
194
			}
195
196
			public Object next() {
197
				getterCalled();
198
				checkForComodification();
199
				Object next = lastElement = iterator.next();
200
				lastIndex = iterator.previousIndex();
201
				return next;
202
			}
203
204
			public void remove() {
205
				checkRealm();
206
				checkForComodification();
207
				if (lastIndex == -1)
208
					throw new IllegalStateException();
209
210
				iterator.remove(); // stay in sync
211
				ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
212
						lastIndex, false, lastElement));
213
214
				boolean wasUpdating = updating;
215
				updating = true;
216
				try {
217
					property.setList(source, list, diff);
218
					modCount++;
219
				} finally {
220
					updating = wasUpdating;
221
				}
222
223
				notifyIfChanged(null);
224
225
				lastElement = null;
226
				lastIndex = -1;
227
228
				expectedModCount = modCount;
229
			}
230
231
			private void checkForComodification() {
232
				if (expectedModCount != modCount)
233
					throw new ConcurrentModificationException();
234
			}
235
		};
236
	}
237
238
	public Object move(int oldIndex, int newIndex) {
239
		checkRealm();
240
241
		List list = getList();
242
		int size = list.size();
243
		if (oldIndex < 0 || oldIndex >= size || newIndex < 0
244
				|| newIndex >= size)
245
			throw new IndexOutOfBoundsException();
246
247
		if (oldIndex == newIndex)
248
			return list.get(oldIndex);
249
250
		list = new ArrayList(list);
251
		Object element = list.remove(oldIndex);
252
		list.add(newIndex, element);
253
254
		ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
255
				oldIndex, false, element), Diffs.createListDiffEntry(newIndex,
256
				true, element));
257
258
		boolean wasUpdating = updating;
259
		updating = true;
260
		try {
261
			property.setList(source, list, diff);
262
			modCount++;
263
		} finally {
264
			updating = wasUpdating;
265
		}
266
267
		notifyIfChanged(null);
268
269
		return element;
270
	}
271
272
	public boolean remove(Object o) {
273
		checkRealm();
274
275
		int index = getList().indexOf(o);
276
		if (index == -1)
277
			return false;
278
279
		remove(index);
280
281
		return true;
282
	}
283
284
	public ListIterator listIterator() {
285
		return listIterator(0);
286
	}
287
288
	public ListIterator listIterator(final int index) {
289
		getterCalled();
290
		return new ListIterator() {
291
			int expectedModCount = modCount;
292
			List list = new ArrayList(getList());
293
			ListIterator iterator = list.listIterator(index);
294
295
			Object lastElement = null;
296
			int lastIndex = -1;
297
298
			public boolean hasNext() {
299
				getterCalled();
300
				checkForComodification();
301
				return iterator.hasNext();
302
			}
303
304
			public int nextIndex() {
305
				getterCalled();
306
				checkForComodification();
307
				return iterator.nextIndex();
308
			}
309
310
			public Object next() {
311
				getterCalled();
312
				checkForComodification();
313
				lastElement = iterator.next();
314
				lastIndex = iterator.previousIndex();
315
				return lastElement;
316
			}
317
318
			public boolean hasPrevious() {
319
				getterCalled();
320
				checkForComodification();
321
				return iterator.hasPrevious();
322
			}
323
324
			public int previousIndex() {
325
				getterCalled();
326
				checkForComodification();
327
				return iterator.previousIndex();
328
			}
329
330
			public Object previous() {
331
				getterCalled();
332
				checkForComodification();
333
				lastElement = iterator.previous();
334
				lastIndex = iterator.nextIndex();
335
				return lastElement;
336
			}
337
338
			public void add(Object o) {
339
				checkRealm();
340
				checkForComodification();
341
				int index = iterator.nextIndex();
342
343
				iterator.add(o); // keep in sync
344
345
				List list = getList();
346
				list.add(index, o);
347
				ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
348
						index, true, o));
349
				boolean wasUpdating = updating;
350
				updating = true;
351
				try {
352
					property.setList(source, list, diff);
353
					modCount++;
354
				} finally {
355
					updating = wasUpdating;
356
				}
357
358
				notifyIfChanged(null);
359
360
				lastElement = null;
361
				lastIndex = -1;
362
				expectedModCount = modCount;
363
			}
364
365
			public void set(Object o) {
366
				checkRealm();
367
				checkForComodification();
368
369
				iterator.set(o);
370
				ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
371
						lastIndex, false, lastElement), Diffs
372
						.createListDiffEntry(lastIndex, true, o));
373
374
				boolean wasUpdating = updating;
375
				updating = true;
376
				try {
377
					property.setList(source, list, diff);
378
					modCount++;
379
				} finally {
380
					updating = wasUpdating;
381
				}
382
383
				notifyIfChanged(null);
384
385
				lastElement = o;
386
				expectedModCount = modCount;
387
			}
388
389
			public void remove() {
390
				checkRealm();
391
				checkForComodification();
392
				if (lastIndex == -1)
393
					throw new IllegalStateException();
394
395
				iterator.remove(); // keep in sync
396
				ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
397
						lastIndex, false, lastElement));
398
399
				boolean wasUpdating = updating;
400
				updating = true;
401
				try {
402
					property.setList(source, list, diff);
403
					modCount++;
404
				} finally {
405
					updating = wasUpdating;
406
				}
407
408
				notifyIfChanged(null);
409
410
				lastElement = null;
411
				lastIndex = -1;
412
				expectedModCount = modCount;
413
			}
414
415
			private void checkForComodification() {
416
				if (expectedModCount != modCount)
417
					throw new ConcurrentModificationException();
418
			}
419
		};
420
	}
421
422
	public Object remove(int index) {
423
		checkRealm();
424
425
		List list = new ArrayList(getList());
426
		Object element = list.remove(index);
427
		ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index,
428
				false, element));
429
430
		boolean wasUpdating = updating;
431
		updating = true;
432
		try {
433
			property.setList(source, list, diff);
434
			modCount++;
435
		} finally {
436
			updating = wasUpdating;
437
		}
438
439
		notifyIfChanged(null);
440
441
		return element;
442
	}
443
444
	public Object set(int index, Object o) {
445
		checkRealm();
446
447
		List list = new ArrayList(getList());
448
		Object oldElement = list.set(index, o);
449
450
		ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index,
451
				false, oldElement), Diffs.createListDiffEntry(index, true, o));
452
453
		boolean wasUpdating = updating;
454
		updating = true;
455
		try {
456
			property.setList(source, list, diff);
457
			modCount++;
458
		} finally {
459
			updating = wasUpdating;
460
		}
461
462
		notifyIfChanged(null);
463
464
		return oldElement;
465
	}
466
467
	public List subList(int fromIndex, int toIndex) {
468
		getterCalled();
469
		return Collections.unmodifiableList(getList().subList(fromIndex,
470
				toIndex));
471
	}
472
473
	// Bulk change operations
474
475
	public boolean addAll(Collection c) {
476
		checkRealm();
477
478
		return addAll(getList().size(), c);
479
	}
480
481
	public boolean addAll(int index, Collection c) {
482
		checkRealm();
483
484
		if (c.isEmpty())
485
			return false;
486
487
		List list = new ArrayList(getList());
488
		list.addAll(index, c);
489
490
		ListDiffEntry[] entries = new ListDiffEntry[c.size()];
491
		int offsetIndex = 0;
492
		for (Iterator it = c.iterator(); it.hasNext();) {
493
			Object element = it.next();
494
			entries[offsetIndex] = Diffs.createListDiffEntry(index
495
					+ offsetIndex, true, element);
496
			offsetIndex++;
497
		}
498
		ListDiff diff = Diffs.createListDiff(entries);
499
500
		boolean wasUpdating = updating;
501
		updating = true;
502
		try {
503
			property.setList(source, list, diff);
504
			modCount++;
505
		} finally {
506
			updating = wasUpdating;
507
		}
508
509
		notifyIfChanged(null);
510
511
		return true;
512
	}
513
514
	public boolean removeAll(Collection c) {
515
		checkRealm();
516
517
		if (c.isEmpty())
518
			return false;
519
520
		List list = getList();
521
		if (list.isEmpty())
522
			return false;
523
524
		list = new ArrayList(list);
525
		List entries = new ArrayList();
526
		ListDiff diff;
527
528
		boolean wasUpdating = updating;
529
		updating = true;
530
		try {
531
			for (ListIterator it = list.listIterator(); it.hasNext();) {
532
				Object element = it.next();
533
				int index = it.previousIndex();
534
				if (c.contains(element)) {
535
					it.remove();
536
					entries.add(Diffs
537
							.createListDiffEntry(index, false, element));
538
				}
539
			}
540
			if (entries.isEmpty())
541
				return false;
542
543
			diff = Diffs.createListDiff((ListDiffEntry[]) entries
544
					.toArray(new ListDiffEntry[entries.size()]));
545
			property.setList(source, list, diff);
546
			modCount++;
547
		} finally {
548
			updating = wasUpdating;
549
		}
550
551
		notifyIfChanged(null);
552
553
		return !diff.isEmpty();
554
	}
555
556
	public boolean retainAll(Collection c) {
557
		checkRealm();
558
559
		List list = getList();
560
		if (list.isEmpty())
561
			return false;
562
563
		if (c.isEmpty()) {
564
			clear();
565
			return true;
566
		}
567
568
		list = new ArrayList(list);
569
		List entries = new ArrayList();
570
		ListDiff diff;
571
572
		boolean wasUpdating = updating;
573
		updating = true;
574
		try {
575
			for (ListIterator it = list.listIterator(); it.hasNext();) {
576
				Object element = it.next();
577
				int index = it.previousIndex();
578
				if (!c.contains(element)) {
579
					it.remove();
580
					entries.add(Diffs
581
							.createListDiffEntry(index, false, element));
582
				}
583
			}
584
			if (entries.isEmpty())
585
				return false;
586
587
			diff = Diffs.createListDiff((ListDiffEntry[]) entries
588
					.toArray(new ListDiffEntry[entries.size()]));
589
			property.setList(source, list, diff);
590
			modCount++;
591
		} finally {
592
			updating = wasUpdating;
593
		}
594
595
		notifyIfChanged(null);
596
597
		return !diff.isEmpty();
598
	}
599
600
	public void clear() {
601
		checkRealm();
602
603
		List list = getList();
604
		if (list.isEmpty())
605
			return;
606
607
		List entries = new ArrayList();
608
		for (Iterator it = list.iterator(); it.hasNext();) {
609
			// always report 0 as the remove index
610
			entries.add(Diffs.createListDiffEntry(0, false, it.next()));
611
		}
612
613
		ListDiff diff = Diffs.createListDiff((ListDiffEntry[]) entries
614
				.toArray(new ListDiffEntry[entries.size()]));
615
		boolean wasUpdating = updating;
616
		updating = true;
617
		try {
618
			property.setList(source, Collections.EMPTY_LIST, diff);
619
			modCount++;
620
		} finally {
621
			updating = wasUpdating;
622
		}
623
624
		notifyIfChanged(null);
625
	}
626
627
	private void notifyIfChanged(ListDiff diff) {
628
		if (hasListeners()) {
629
			List oldList = cachedList;
630
			List newList = cachedList = property.getList(source);
631
			if (diff == null)
632
				diff = Diffs.computeListDiff(oldList, newList);
633
			if (!diff.isEmpty()) {
634
				fireListChange(diff);
635
			}
636
		}
637
	}
638
639
	public boolean equals(Object o) {
640
		getterCalled();
641
		return getList().equals(o);
642
	}
643
644
	public int hashCode() {
645
		getterCalled();
646
		return getList().hashCode();
647
	}
648
649
	public Object getObserved() {
650
		return source;
651
	}
652
653
	public IProperty getProperty() {
654
		return property;
655
	}
656
657
	public synchronized void dispose() {
658
		if (!isDisposed()) {
659
			if (listener != null)
660
				property.removeListener(source, listener);
661
			property = null;
662
			source = null;
663
			listener = null;
664
		}
665
		super.dispose();
666
	}
667
}
(-)src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java (+199 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 *     Matthew Hall - bug 195222, 247997
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.map;
14
15
import java.util.Collections;
16
import java.util.Map;
17
18
import org.eclipse.core.databinding.observable.Realm;
19
import org.eclipse.core.databinding.observable.map.IObservableMap;
20
import org.eclipse.core.databinding.observable.map.MapDiff;
21
import org.eclipse.core.databinding.property.INativePropertyListener;
22
import org.eclipse.core.databinding.property.ISimplePropertyListener;
23
import org.eclipse.core.internal.databinding.property.map.SimpleMapPropertyObservableMap;
24
25
/**
26
 * Simplified abstract implementation of IMapProperty. This class takes care of
27
 * most of the functional requirements for an IMapProperty implementation,
28
 * leaving only the property-specific details to subclasses.
29
 * <p>
30
 * Subclasses must implement these methods:
31
 * <ul>
32
 * <li> {@link #getKeyType()}
33
 * <li> {@link #getValueType()}
34
 * <li> {@link #doGetMap(Object)}
35
 * <li> {@link #doSetMap(Object, Map, MapDiff)}
36
 * <li> {@link #adaptListener(ISimplePropertyListener)}
37
 * <li> {@link #doAddListener(Object, INativePropertyListener)}
38
 * <li> {@link #doRemoveListener(Object, INativePropertyListener)}
39
 * </ul>
40
 * <p>
41
 * In addition, we recommended overriding {@link #toString()} to return a
42
 * description suitable for debugging purposes.
43
 * 
44
 * @since 1.2
45
 */
46
public abstract class SimpleMapProperty extends MapProperty {
47
	public IObservableMap observe(Realm realm, Object source) {
48
		return new SimpleMapPropertyObservableMap(realm, source, this);
49
	}
50
51
	// Accessors
52
53
	/**
54
	 * Returns an unmodifiable Map with the current contents of the source's map
55
	 * property.
56
	 * 
57
	 * @param source
58
	 *            the property source
59
	 * @return a Map with the current contents of the source's map property
60
	 * @noreference This method is not intended to be referenced by clients.
61
	 */
62
	public final Map getMap(Object source) {
63
		if (source == null)
64
			return Collections.EMPTY_MAP;
65
		return Collections.unmodifiableMap(doGetMap(source));
66
	}
67
68
	/**
69
	 * Returns a Map with the current contents of the source's map property
70
	 * 
71
	 * @param source
72
	 *            the property source
73
	 * @return a Map with the current contents of the source's map property
74
	 * @noreference This method is not intended to be referenced by clients.
75
	 */
76
	protected abstract Map doGetMap(Object source);
77
78
	// Mutators
79
80
	/**
81
	 * Updates the property on the source with the specified change.
82
	 * 
83
	 * @param source
84
	 *            the property source
85
	 * @param map
86
	 *            the new map
87
	 * @param diff
88
	 *            a diff describing the change
89
	 * @noreference This method is not intended to be referenced by clients.
90
	 */
91
	public final void setMap(Object source, Map map, MapDiff diff) {
92
		if (source != null && !diff.isEmpty())
93
			doSetMap(source, map, diff);
94
	}
95
96
	/**
97
	 * Updates the property on the source with the specified change.
98
	 * 
99
	 * @param source
100
	 *            the property source
101
	 * @param map
102
	 *            the new map
103
	 * @param diff
104
	 *            a diff describing the change
105
	 * @noreference This method is not intended to be referenced by clients.
106
	 */
107
	protected abstract void doSetMap(Object source, Map map, MapDiff diff);
108
109
	// Listeners
110
111
	/**
112
	 * Returns a listener which implements the correct listener interface for
113
	 * the expected source object, and which parlays property change events from
114
	 * the source object to the given listener. If there is no listener API for
115
	 * this property, this method returns null.
116
	 * 
117
	 * @param listener
118
	 *            the property listener to receive events
119
	 * @return a native listener which parlays property change events to the
120
	 *         specified listener.
121
	 * @throws ClassCastException
122
	 *             if the provided listener does not implement the correct
123
	 *             listener interface (IValueProperty, IListProperty,
124
	 *             ISetProperty or IMapProperty) depending on the property.
125
	 * @noreference This method is not intended to be referenced by clients.
126
	 */
127
	public abstract INativePropertyListener adaptListener(
128
			ISimplePropertyListener listener);
129
130
	/**
131
	 * Adds the specified listener as a listener for this property on the
132
	 * specified property source. If the source object has no listener API for
133
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
134
	 * returns null), this method does nothing.
135
	 * 
136
	 * @param source
137
	 *            the property source
138
	 * @param listener
139
	 *            a listener obtained from calling
140
	 *            {@link #adaptListener(ISimplePropertyListener)} .
141
	 * @noreference This method is not intended to be referenced by clients.
142
	 */
143
	public final void addListener(Object source,
144
			INativePropertyListener listener) {
145
		if (source != null)
146
			doAddListener(source, listener);
147
	}
148
149
	/**
150
	 * Adds the specified listener as a listener for this property on the
151
	 * specified property source. If the source object has no listener API for
152
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
153
	 * returns null), this method does nothing.
154
	 * 
155
	 * @param source
156
	 *            the property source
157
	 * @param listener
158
	 *            a listener obtained from calling
159
	 *            {@link #adaptListener(ISimplePropertyListener)} .
160
	 * @noreference This method is not intended to be referenced by clients.
161
	 */
162
	protected abstract void doAddListener(Object source,
163
			INativePropertyListener listener);
164
165
	/**
166
	 * Removes the specified listener as a listener for this property on the
167
	 * specified property source. If the source object has no listener API for
168
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
169
	 * returns null), this method does nothing.
170
	 * 
171
	 * @param source
172
	 *            the property source
173
	 * @param listener
174
	 *            a listener obtained from calling
175
	 *            {@link #adaptListener(ISimplePropertyListener)} .
176
	 * @noreference This method is not intended to be referenced by clients.
177
	 */
178
	public final void removeListener(Object source,
179
			INativePropertyListener listener) {
180
		if (source != null)
181
			doRemoveListener(source, listener);
182
	}
183
184
	/**
185
	 * Removes the specified listener as a listener for this property on the
186
	 * specified property source. If the source object has no listener API for
187
	 * this property (i.e. {@link #adaptListener(ISimplePropertyListener)}
188
	 * returns null), this method does nothing.
189
	 * 
190
	 * @param source
191
	 *            the property source
192
	 * @param listener
193
	 *            a listener obtained from calling
194
	 *            {@link #adaptListener(ISimplePropertyListener)} .
195
	 * @noreference This method is not intended to be referenced by clients.
196
	 */
197
	protected abstract void doRemoveListener(Object source,
198
			INativePropertyListener listener);
199
}
(-)src/org/eclipse/core/internal/databinding/property/value/ObservableListDelegatingValuePropertyObservableList.java (+348 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.property.value;
13
14
import java.lang.reflect.Array;
15
import java.util.ArrayList;
16
import java.util.Collection;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.ListIterator;
20
21
import org.eclipse.core.databinding.observable.Diffs;
22
import org.eclipse.core.databinding.observable.IStaleListener;
23
import org.eclipse.core.databinding.observable.ObservableTracker;
24
import org.eclipse.core.databinding.observable.StaleEvent;
25
import org.eclipse.core.databinding.observable.list.AbstractObservableList;
26
import org.eclipse.core.databinding.observable.list.IListChangeListener;
27
import org.eclipse.core.databinding.observable.list.IObservableList;
28
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
29
import org.eclipse.core.databinding.observable.list.ListDiff;
30
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
31
import org.eclipse.core.databinding.property.IProperty;
32
import org.eclipse.core.databinding.property.IPropertyObservable;
33
import org.eclipse.core.databinding.property.value.DelegatingValueProperty;
34
35
/**
36
 * @since 1.2
37
 */
38
public class ObservableListDelegatingValuePropertyObservableList extends
39
		AbstractObservableList implements IPropertyObservable {
40
	private IObservableList masterList;
41
	private DelegatingValueProperty detailProperty;
42
	private DelegatingCache cache;
43
44
	private IListChangeListener masterListener = new IListChangeListener() {
45
		public void handleListChange(ListChangeEvent event) {
46
			if (isDisposed())
47
				return;
48
49
			cache.addAll(masterList);
50
51
			// Need both obsolete and new elements to convert diff
52
			ListDiff diff = convertDiff(event.diff);
53
54
			cache.retainAll(masterList);
55
56
			fireListChange(diff);
57
		}
58
59
		private ListDiff convertDiff(ListDiff diff) {
60
			// Convert diff to detail value
61
			ListDiffEntry[] masterEntries = diff.getDifferences();
62
			ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length];
63
			for (int i = 0; i < masterEntries.length; i++) {
64
				ListDiffEntry masterDifference = masterEntries[i];
65
				int index = masterDifference.getPosition();
66
				boolean addition = masterDifference.isAddition();
67
				Object masterElement = masterDifference.getElement();
68
				Object detailValue = cache.get(masterElement);
69
70
				detailEntries[i] = Diffs.createListDiffEntry(index, addition,
71
						detailValue);
72
			}
73
			return Diffs.createListDiff(detailEntries);
74
		}
75
	};
76
77
	private IStaleListener staleListener = new IStaleListener() {
78
		public void handleStale(StaleEvent staleEvent) {
79
			fireStale();
80
		}
81
	};
82
83
	/**
84
	 * @param masterList
85
	 * @param valueProperty
86
	 */
87
	public ObservableListDelegatingValuePropertyObservableList(
88
			IObservableList masterList, DelegatingValueProperty valueProperty) {
89
		super(masterList.getRealm());
90
		this.masterList = masterList;
91
		this.detailProperty = valueProperty;
92
		this.cache = new DelegatingCache(getRealm(), valueProperty) {
93
			void handleValueChange(Object masterElement, Object oldValue,
94
					Object newValue) {
95
				fireListChange(indicesOf(masterElement), oldValue, newValue);
96
			}
97
		};
98
		cache.addAll(masterList);
99
100
		masterList.addListChangeListener(masterListener);
101
		masterList.addStaleListener(staleListener);
102
	}
103
104
	protected int doGetSize() {
105
		getterCalled();
106
		return masterList.size();
107
	}
108
109
	private void getterCalled() {
110
		ObservableTracker.getterCalled(this);
111
	}
112
113
	public Object get(int index) {
114
		getterCalled();
115
		Object masterElement = masterList.get(index);
116
		return cache.get(masterElement);
117
	}
118
119
	public boolean add(Object o) {
120
		throw new UnsupportedOperationException();
121
	}
122
123
	public boolean addAll(Collection c) {
124
		throw new UnsupportedOperationException();
125
	}
126
127
	public boolean addAll(int index, Collection c) {
128
		throw new UnsupportedOperationException();
129
	}
130
131
	public boolean contains(Object o) {
132
		getterCalled();
133
		return cache.contains(o);
134
	}
135
136
	public boolean isEmpty() {
137
		getterCalled();
138
		return masterList.isEmpty();
139
	}
140
141
	public boolean isStale() {
142
		getterCalled();
143
		return masterList.isStale();
144
	}
145
146
	public Iterator iterator() {
147
		getterCalled();
148
		return new Iterator() {
149
			Iterator it = masterList.iterator();
150
151
			public boolean hasNext() {
152
				getterCalled();
153
				return it.hasNext();
154
			}
155
156
			public Object next() {
157
				getterCalled();
158
				Object masterElement = it.next();
159
				return cache.get(masterElement);
160
			}
161
162
			public void remove() {
163
				throw new UnsupportedOperationException();
164
			}
165
		};
166
	}
167
168
	public Object move(int oldIndex, int newIndex) {
169
		throw new UnsupportedOperationException();
170
	}
171
172
	public boolean remove(Object o) {
173
		throw new UnsupportedOperationException();
174
	}
175
176
	public boolean removeAll(Collection c) {
177
		throw new UnsupportedOperationException();
178
	}
179
180
	public boolean retainAll(Collection c) {
181
		throw new UnsupportedOperationException();
182
	}
183
184
	public Object[] toArray() {
185
		getterCalled();
186
		Object[] masterElements = masterList.toArray();
187
		Object[] result = new Object[masterElements.length];
188
		for (int i = 0; i < result.length; i++) {
189
			result[i] = cache.get(masterElements[i]);
190
		}
191
		return result;
192
	}
193
194
	public Object[] toArray(Object[] a) {
195
		getterCalled();
196
		Object[] masterElements = masterList.toArray();
197
		if (a.length < masterElements.length)
198
			a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
199
					masterElements.length);
200
		for (int i = 0; i < masterElements.length; i++) {
201
			a[i] = cache.get(masterElements[i]);
202
		}
203
		return a;
204
	}
205
206
	public void add(int index, Object o) {
207
		throw new UnsupportedOperationException();
208
	}
209
210
	public void clear() {
211
		throw new UnsupportedOperationException();
212
	}
213
214
	public ListIterator listIterator() {
215
		return listIterator(0);
216
	}
217
218
	public ListIterator listIterator(final int index) {
219
		getterCalled();
220
		return new ListIterator() {
221
			ListIterator it = masterList.listIterator(index);
222
			Object lastMasterElement;
223
			Object lastElement;
224
			boolean haveIterated = false;
225
226
			public void add(Object arg0) {
227
				throw new UnsupportedOperationException();
228
			}
229
230
			public boolean hasNext() {
231
				getterCalled();
232
				return it.hasNext();
233
			}
234
235
			public boolean hasPrevious() {
236
				getterCalled();
237
				return it.hasPrevious();
238
			}
239
240
			public Object next() {
241
				getterCalled();
242
				lastMasterElement = it.next();
243
				lastElement = cache.get(lastMasterElement);
244
				haveIterated = true;
245
				return lastElement;
246
			}
247
248
			public int nextIndex() {
249
				getterCalled();
250
				return it.nextIndex();
251
			}
252
253
			public Object previous() {
254
				getterCalled();
255
				lastMasterElement = it.previous();
256
				lastElement = cache.get(lastMasterElement);
257
				haveIterated = true;
258
				return lastElement;
259
			}
260
261
			public int previousIndex() {
262
				getterCalled();
263
				return it.previousIndex();
264
			}
265
266
			public void remove() {
267
				throw new UnsupportedOperationException();
268
			}
269
270
			public void set(Object o) {
271
				checkRealm();
272
				if (!haveIterated)
273
					throw new IllegalStateException();
274
275
				cache.put(lastMasterElement, o);
276
277
				lastElement = o;
278
			}
279
		};
280
	}
281
282
	private int[] indicesOf(Object masterElement) {
283
		List indices = new ArrayList();
284
285
		for (ListIterator it = masterList.listIterator(); it.hasNext();) {
286
			if (masterElement == it.next())
287
				indices.add(new Integer(it.previousIndex()));
288
		}
289
290
		int[] result = new int[indices.size()];
291
		for (int i = 0; i < result.length; i++) {
292
			result[i] = ((Integer) indices.get(i)).intValue();
293
		}
294
		return result;
295
	}
296
297
	private void fireListChange(int[] indices, Object oldValue, Object newValue) {
298
		ListDiffEntry[] differences = new ListDiffEntry[indices.length * 2];
299
		for (int i = 0; i < indices.length; i++) {
300
			int index = indices[i];
301
			differences[i * 2] = Diffs.createListDiffEntry(index, false,
302
					oldValue);
303
			differences[i * 2 + 1] = Diffs.createListDiffEntry(index, true,
304
					newValue);
305
		}
306
		fireListChange(Diffs.createListDiff(differences));
307
	}
308
309
	public Object remove(int index) {
310
		throw new UnsupportedOperationException();
311
	}
312
313
	public Object set(int index, Object o) {
314
		checkRealm();
315
		Object masterElement = masterList.get(index);
316
		return cache.put(masterElement, o);
317
	}
318
319
	public Object getObserved() {
320
		return masterList;
321
	}
322
323
	public IProperty getProperty() {
324
		return detailProperty;
325
	}
326
327
	public Object getElementType() {
328
		return detailProperty.getValueType();
329
	}
330
331
	public synchronized void dispose() {
332
		if (masterList != null) {
333
			masterList.removeListChangeListener(masterListener);
334
			masterList.removeStaleListener(staleListener);
335
			masterList = null;
336
		}
337
338
		if (cache != null) {
339
			cache.dispose();
340
			cache = null;
341
		}
342
343
		masterListener = null;
344
		detailProperty = null;
345
346
		super.dispose();
347
	}
348
}
(-)src/org/eclipse/core/databinding/property/INativePropertyListener.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.property;
13
14
import org.eclipse.core.databinding.property.list.SimpleListProperty;
15
import org.eclipse.core.databinding.property.map.SimpleMapProperty;
16
import org.eclipse.core.databinding.property.set.SimpleSetProperty;
17
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
18
19
/**
20
 * Marker interface for "native" property listeners. A native listener
21
 * implements the listener interface supported by the source object, and parlays
22
 * events received from the source object to the property change listener
23
 * provided when the native listener was constructed.
24
 * 
25
 * @since 1.2
26
 * @see SimpleValueProperty#adaptListener(ISimplePropertyListener)
27
 * @see SimpleListProperty#adaptListener(ISimplePropertyListener)
28
 * @see SimpleSetProperty#adaptListener(ISimplePropertyListener)
29
 * @see SimpleMapProperty#adaptListener(ISimplePropertyListener)
30
 */
31
public interface INativePropertyListener {
32
}
(-)src/org/eclipse/core/databinding/property/set/ISetProperty.java (+119 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.property.set;
14
15
import org.eclipse.core.databinding.observable.Realm;
16
import org.eclipse.core.databinding.observable.map.IObservableMap;
17
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
18
import org.eclipse.core.databinding.observable.set.IObservableSet;
19
import org.eclipse.core.databinding.observable.value.IObservableValue;
20
import org.eclipse.core.databinding.property.IProperty;
21
import org.eclipse.core.databinding.property.map.IMapProperty;
22
import org.eclipse.core.databinding.property.value.IValueProperty;
23
24
/**
25
 * Interface for set-typed properties
26
 * 
27
 * @since 1.2
28
 * @noimplement This interface is not intended to be implemented by clients.
29
 *              Clients should instead subclass one of the classes that
30
 *              implement this interface. Note that direct implementers of this
31
 *              interface outside of the framework will be broken in future
32
 *              releases when methods are added to this interface.
33
 * @see SetProperty
34
 * @see SimpleSetProperty
35
 */
36
public interface ISetProperty extends IProperty {
37
	/**
38
	 * Returns the type of the elements in the collection or <code>null</code>
39
	 * if untyped
40
	 * 
41
	 * @return the type of the elements in the collection or <code>null</code>
42
	 *         if untyped
43
	 */
44
	public Object getElementType();
45
46
	/**
47
	 * Returns an observable set observing this set property on the given
48
	 * property source
49
	 * 
50
	 * @param source
51
	 *            the property source
52
	 * @return an observable set observing this set property on the given
53
	 *         property source
54
	 */
55
	public IObservableSet observe(Object source);
56
57
	/**
58
	 * Returns an observable set observing this set property on the given
59
	 * property source
60
	 * 
61
	 * @param realm
62
	 *            the observable's realm
63
	 * @param source
64
	 *            the property source
65
	 * @return an observable set observing this set property on the given
66
	 *         property source
67
	 */
68
	public IObservableSet observe(Realm realm, Object source);
69
70
	/**
71
	 * Returns a factory for creating observable sets tracking this property of
72
	 * a particular property source.
73
	 * 
74
	 * @return a factory for creating observable sets tracking this property of
75
	 *         a particular property source.
76
	 */
77
	public IObservableFactory setFactory();
78
79
	/**
80
	 * Returns a factory for creating observable sets in the given realm,
81
	 * tracking this property of a particular property source.
82
	 * 
83
	 * @param realm
84
	 *            the realm
85
	 * 
86
	 * @return a factory for creating observable sets in the given realm,
87
	 *         tracking this property of a particular property source.
88
	 */
89
	public IObservableFactory setFactory(Realm realm);
90
91
	/**
92
	 * Returns an observable set on the master observable's realm which tracks
93
	 * this property of the current value of <code>master</code>.
94
	 * 
95
	 * @param master
96
	 *            the master observable
97
	 * @return an observable set on the given realm which tracks this property
98
	 *         of the current value of <code>master</code>.
99
	 */
100
	public IObservableSet observeDetail(IObservableValue master);
101
102
	/**
103
	 * Returns the nested combination of this property and the specified detail
104
	 * value property. Note that because this property is a projection of value
105
	 * properties over a set, the only modifications supported are through the
106
	 * {@link IObservableMap#put(Object, Object)} and
107
	 * {@link IObservableMap#putAll(java.util.Map)} methods. In the latter case,
108
	 * this property does not put entries for keys not already in the master key
109
	 * set. Modifications made through the returned property are delegated to
110
	 * the detail property, using the corresponding set element from the master
111
	 * property as the source.
112
	 * 
113
	 * @param detailValues
114
	 *            the detail property
115
	 * @return the nested combination of the master set and detail value
116
	 *         properties
117
	 */
118
	public IMapProperty values(IValueProperty detailValues);
119
}
(-)src/org/eclipse/core/databinding/property/list/DelegatingListProperty.java (+102 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.property.list;
13
14
import java.util.Collections;
15
import java.util.List;
16
17
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.list.IObservableList;
19
import org.eclipse.core.databinding.observable.list.ListDiff;
20
import org.eclipse.core.databinding.property.INativePropertyListener;
21
import org.eclipse.core.databinding.property.ISimplePropertyListener;
22
23
/**
24
 * @since 1.2
25
 * 
26
 */
27
public abstract class DelegatingListProperty extends ListProperty {
28
	private final IListProperty nullProperty;
29
	private final Object elementType;
30
31
	protected DelegatingListProperty() {
32
		this(null);
33
	}
34
35
	protected DelegatingListProperty(Object elementType) {
36
		this.elementType = elementType;
37
		this.nullProperty = new NullListProperty();
38
	}
39
40
	/**
41
	 * Returns the property to delegate to for the specified source object.
42
	 * Repeated calls to this method with the same source object returns the
43
	 * same delegate instance.
44
	 * 
45
	 * @param source
46
	 *            the property source (may be null)
47
	 * @return the property to delegate to for the specified source object.
48
	 */
49
	public final IListProperty getDelegate(Object source) {
50
		if (source == null)
51
			return null;
52
		IListProperty delegate = doGetDelegate(source);
53
		if (delegate == null)
54
			delegate = nullProperty;
55
		return delegate;
56
	}
57
58
	/**
59
	 * Returns the property to delegate to for the specified source object.
60
	 * Implementers must ensure that repeated calls to this method with the same
61
	 * source object returns the same delegate instance.
62
	 * 
63
	 * @param source
64
	 *            the property source
65
	 * @return the property to delegate to for the specified source object.
66
	 */
67
	protected abstract IListProperty doGetDelegate(Object source);
68
69
	public Object getElementType() {
70
		return elementType;
71
	}
72
73
	public IObservableList observe(Realm realm, Object source) {
74
		return getDelegate(source).observe(realm, source);
75
	}
76
77
	private class NullListProperty extends SimpleListProperty {
78
		public Object getElementType() {
79
			return elementType;
80
		}
81
82
		protected List doGetList(Object source) {
83
			return Collections.EMPTY_LIST;
84
		}
85
86
		protected void doSetList(Object source, List list, ListDiff diff) {
87
		}
88
89
		public INativePropertyListener adaptListener(
90
				ISimplePropertyListener listener) {
91
			return null;
92
		}
93
94
		protected void doAddListener(Object source,
95
				INativePropertyListener listener) {
96
		}
97
98
		protected void doRemoveListener(Object source,
99
				INativePropertyListener listener) {
100
		}
101
	}
102
}
(-)src/org/eclipse/core/databinding/property/value/DelegatingValueProperty.java (+118 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.property.value;
13
14
import org.eclipse.core.databinding.observable.Realm;
15
import org.eclipse.core.databinding.observable.list.IObservableList;
16
import org.eclipse.core.databinding.observable.map.IObservableMap;
17
import org.eclipse.core.databinding.observable.set.IObservableSet;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.core.databinding.property.INativePropertyListener;
20
import org.eclipse.core.databinding.property.ISimplePropertyListener;
21
import org.eclipse.core.internal.databinding.property.value.ObservableListDelegatingValuePropertyObservableList;
22
import org.eclipse.core.internal.databinding.property.value.ObservableMapDelegatingValuePropertyObservableMap;
23
import org.eclipse.core.internal.databinding.property.value.ObservableSetDelegatingValuePropertyObservableMap;
24
25
/**
26
 * @since 1.2
27
 * 
28
 */
29
public abstract class DelegatingValueProperty extends ValueProperty {
30
	private final Object valueType;
31
	private final IValueProperty nullProperty = new NullValueProperty();
32
33
	protected DelegatingValueProperty() {
34
		this(null);
35
	}
36
37
	protected DelegatingValueProperty(Object valueType) {
38
		this.valueType = valueType;
39
	}
40
41
	/**
42
	 * Returns the property to delegate to for the specified source object.
43
	 * Repeated calls to this method with the same source object returns the
44
	 * same delegate instance.
45
	 * 
46
	 * @param source
47
	 *            the property source (may be null)
48
	 * @return the property to delegate to for the specified source object.
49
	 */
50
	public final IValueProperty getDelegate(Object source) {
51
		if (source == null)
52
			return null;
53
		IValueProperty delegate = doGetDelegate(source);
54
		if (delegate == null)
55
			delegate = nullProperty;
56
		return delegate;
57
	}
58
59
	/**
60
	 * Returns the property to delegate to for the specified source object.
61
	 * Implementers must ensure that repeated calls to this method with the same
62
	 * source object returns the same delegate instance.
63
	 * 
64
	 * @param source
65
	 *            the property source
66
	 * @return the property to delegate to for the specified source object.
67
	 */
68
	protected abstract IValueProperty doGetDelegate(Object source);
69
70
	public Object getValueType() {
71
		return valueType;
72
	}
73
74
	public IObservableValue observe(Realm realm, Object source) {
75
		return getDelegate(source).observe(realm, source);
76
	}
77
78
	public IObservableList observeDetail(IObservableList master) {
79
		return new ObservableListDelegatingValuePropertyObservableList(master,
80
				this);
81
	}
82
83
	public IObservableMap observeDetail(IObservableSet master) {
84
		return new ObservableSetDelegatingValuePropertyObservableMap(master,
85
				this);
86
	}
87
88
	public IObservableMap observeDetail(IObservableMap master) {
89
		return new ObservableMapDelegatingValuePropertyObservableMap(master,
90
				this);
91
	}
92
93
	private class NullValueProperty extends SimpleValueProperty {
94
		public Object getValueType() {
95
			return valueType;
96
		}
97
98
		protected Object doGetValue(Object source) {
99
			return null;
100
		}
101
102
		protected void doSetValue(Object source, Object value) {
103
		}
104
105
		public INativePropertyListener adaptListener(
106
				ISimplePropertyListener listener) {
107
			return null;
108
		}
109
110
		protected void doAddListener(Object source,
111
				INativePropertyListener listener) {
112
		}
113
114
		protected void doRemoveListener(Object source,
115
				INativePropertyListener listener) {
116
		}
117
	}
118
}
(-)src/org/eclipse/core/databinding/observable/IDiff.java (+29 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.observable;
13
14
import org.eclipse.core.databinding.observable.list.ListDiff;
15
import org.eclipse.core.databinding.observable.map.MapDiff;
16
import org.eclipse.core.databinding.observable.set.SetDiff;
17
import org.eclipse.core.databinding.observable.value.ValueDiff;
18
19
/**
20
 * Marker interface for objects which describe a difference in state.
21
 * 
22
 * @since 1.2
23
 * @see ValueDiff
24
 * @see ListDiff
25
 * @see SetDiff
26
 * @see MapDiff
27
 */
28
public interface IDiff {
29
}
(-)src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableMap.java (-193 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 171616
11
 *     Matthew hall - bugs 223164, 241585, 226289, 246103
12
 *******************************************************************************/
13
14
package org.eclipse.core.internal.databinding.beans;
15
16
import java.beans.PropertyChangeListener;
17
import java.beans.PropertyDescriptor;
18
import java.lang.reflect.Method;
19
import java.util.HashMap;
20
import java.util.Map;
21
22
import org.eclipse.core.databinding.beans.IBeanObservable;
23
import org.eclipse.core.databinding.observable.Diffs;
24
import org.eclipse.core.databinding.observable.map.ComputedObservableMap;
25
import org.eclipse.core.databinding.observable.set.IObservableSet;
26
import org.eclipse.core.databinding.util.Policy;
27
import org.eclipse.core.internal.databinding.Util;
28
import org.eclipse.core.runtime.IStatus;
29
import org.eclipse.core.runtime.Status;
30
31
/**
32
 * @since 1.0
33
 * 
34
 */
35
public class JavaBeanObservableMap extends ComputedObservableMap implements
36
		IBeanObservable {
37
38
	private PropertyDescriptor propertyDescriptor;
39
	
40
	private PropertyChangeListener elementListener = new PropertyChangeListener() {
41
		public void propertyChange(final java.beans.PropertyChangeEvent event) {
42
			if (!updating) {
43
				getRealm().exec(new Runnable() {
44
					public void run() {
45
						Object source = event.getSource();
46
						Object oldValue = event.getOldValue();
47
						Object newValue = event.getNewValue();
48
						if (oldValue == null && newValue == null) {
49
							oldValue = cachedValues.get(new IdentityWrapper(
50
									source));
51
							newValue = doGet(source);
52
						}
53
						cachedValues.put(new IdentityWrapper(source), newValue);
54
						if (!Util.equals(oldValue, newValue)) {
55
							fireMapChange(Diffs.createMapDiffSingleChange(
56
									source, oldValue, newValue));
57
						}
58
					}
59
				});
60
			}
61
		}
62
	};
63
64
	private ListenerSupport listenerSupport;
65
66
	private boolean updating = false;
67
68
	private boolean attachListeners;
69
70
	// Applicable only while hasListeners() == true
71
	private Map cachedValues;
72
73
	/**
74
	 * @param domain
75
	 * @param propertyDescriptor
76
	 */
77
	public JavaBeanObservableMap(IObservableSet domain,
78
			PropertyDescriptor propertyDescriptor) {
79
		this(domain, propertyDescriptor, true);
80
	}
81
82
	/**
83
	 * @param domain
84
	 * @param propertyDescriptor
85
	 * @param attachListeners
86
	 */
87
	public JavaBeanObservableMap(IObservableSet domain,
88
			PropertyDescriptor propertyDescriptor, boolean attachListeners) {
89
		super(domain, propertyDescriptor.getPropertyType());
90
91
		this.propertyDescriptor = propertyDescriptor;
92
		this.attachListeners = attachListeners;
93
		if (attachListeners) {
94
			this.listenerSupport = new ListenerSupport(elementListener,
95
					propertyDescriptor.getName());
96
		}
97
	}
98
99
	protected void firstListenerAdded() {
100
		if (attachListeners) {
101
			cachedValues = new HashMap();
102
		}
103
		super.firstListenerAdded();
104
	}
105
106
	protected void lastListenerRemoved() {
107
		super.lastListenerRemoved();
108
		if (attachListeners) {
109
			cachedValues = null;
110
		}
111
	}
112
113
	protected void hookListener(Object domainElement) {
114
		if (attachListeners && domainElement != null) {
115
			listenerSupport.hookListener(domainElement);
116
			cachedValues.put(new IdentityWrapper(domainElement),
117
					doGet(domainElement));
118
		}
119
	}
120
121
	protected void unhookListener(Object domainElement) {
122
		if (attachListeners && domainElement != null) {
123
			cachedValues.remove(new IdentityWrapper(domainElement));
124
			listenerSupport.unhookListener(domainElement);
125
		}
126
	}
127
128
	protected Object doGet(Object key) {
129
		if (key == null) {
130
			return null;
131
		}
132
		try {
133
			Method readMethod = propertyDescriptor.getReadMethod();
134
			if (!readMethod.isAccessible()) {
135
				readMethod.setAccessible(true);
136
			}
137
			return readMethod.invoke(key, new Object[0]);
138
		} catch (Exception e) {
139
			Policy.getLog().log(
140
					new Status(IStatus.ERROR, Policy.JFACE_DATABINDING,
141
							IStatus.ERROR, "cannot get value", e)); //$NON-NLS-1$
142
			throw new RuntimeException(e);
143
		}
144
	}
145
146
	protected Object doPut(Object key, Object value) {
147
		try {
148
			Object oldValue = get(key);
149
			if (!Util.equals(oldValue, value)) {
150
				Method writeMethod = propertyDescriptor.getWriteMethod();
151
				if (!writeMethod.isAccessible()) {
152
					writeMethod.setAccessible(true);
153
				}
154
				writeMethod.invoke(key, new Object[] { value });
155
			}
156
157
			if (hasListeners()) {
158
				// oldValue contains the live value which may be different from
159
				// the cached value if the bean does not have listener API or
160
				// does not fire events properly. For consistency we want to
161
				// provide the cached value as the old value, rather than the
162
				// live value so that consumers that hook/unhook listeners can
163
				// do so without maintaining caches of their own.
164
				Object newValue = doGet(key);
165
				oldValue = cachedValues.put(new IdentityWrapper(key), newValue);
166
167
				if (!Util.equals(oldValue, newValue)) {
168
					fireSingleChange(key, oldValue, newValue);
169
				}
170
			}
171
			return oldValue;
172
		} catch (Exception e) {
173
			Policy.getLog().log(
174
					new Status(IStatus.ERROR, Policy.JFACE_DATABINDING,
175
							IStatus.ERROR, "cannot set value", e)); //$NON-NLS-1$
176
			throw new RuntimeException(e);
177
		}
178
	}
179
180
	/* (non-Javadoc)
181
	 * @see org.eclipse.core.databinding.beans.IBeanObservable#getObserved()
182
	 */
183
	public Object getObserved() {
184
		return keySet();
185
	}
186
187
	/* (non-Javadoc)
188
	 * @see org.eclipse.core.databinding.beans.IBeanObservable#getPropertyDescriptor()
189
	 */
190
	public PropertyDescriptor getPropertyDescriptor() {
191
		return propertyDescriptor;
192
	}
193
}
(-)src/org/eclipse/core/internal/databinding/beans/IdentityWrapper.java (-1 / +1 lines)
Lines 29-35 Link Here
29
	public IdentityWrapper(Object o) {
29
	public IdentityWrapper(Object o) {
30
		this.o = o;
30
		this.o = o;
31
	}
31
	}
32
	
32
33
	/**
33
	/**
34
	 * @return the unwrapped object
34
	 * @return the unwrapped object
35
	 */
35
	 */
(-)src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableList.java (-399 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006-2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 171616
11
 *     Matthew Hall - bugs 208858, 221351, 213145, 223164, 244098
12
 *     Mike Evans - bug 217558
13
 *******************************************************************************/
14
15
package org.eclipse.core.internal.databinding.beans;
16
17
import java.beans.PropertyChangeListener;
18
import java.beans.PropertyDescriptor;
19
import java.lang.reflect.Array;
20
import java.lang.reflect.InvocationTargetException;
21
import java.lang.reflect.Method;
22
import java.util.ArrayList;
23
import java.util.Arrays;
24
import java.util.Collection;
25
import java.util.Iterator;
26
import java.util.List;
27
28
import org.eclipse.core.databinding.BindingException;
29
import org.eclipse.core.databinding.beans.IBeanObservable;
30
import org.eclipse.core.databinding.observable.Diffs;
31
import org.eclipse.core.databinding.observable.Realm;
32
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
33
import org.eclipse.core.databinding.observable.list.ObservableList;
34
35
/**
36
 * @since 1.0
37
 * 
38
 */
39
public class JavaBeanObservableList extends ObservableList implements
40
		IBeanObservable {
41
42
	private final Object object;
43
44
	private boolean updating = false;
45
46
	private PropertyDescriptor descriptor;
47
48
	private ListenerSupport listenerSupport;
49
50
	/**
51
	 * @param realm
52
	 * @param object
53
	 * @param descriptor
54
	 * @param elementType
55
	 */
56
	public JavaBeanObservableList(Realm realm, Object object,
57
			PropertyDescriptor descriptor, Class elementType) {
58
		this(realm, object, descriptor, elementType, true);
59
	}
60
61
	/**
62
	 * @param realm
63
	 * @param object
64
	 * @param descriptor
65
	 * @param elementType
66
	 * @param attachListeners
67
	 */
68
	public JavaBeanObservableList(Realm realm, Object object,
69
			PropertyDescriptor descriptor, Class elementType,
70
			boolean attachListeners) {
71
72
		super(realm, new ArrayList(), elementType);
73
		this.object = object;
74
		this.descriptor = descriptor;
75
76
		if (attachListeners) {
77
			PropertyChangeListener listener = new PropertyChangeListener() {
78
				public void propertyChange(java.beans.PropertyChangeEvent event) {
79
					if (!updating) {
80
						getRealm().exec(new Runnable() {
81
							public void run() {
82
								updateWrappedList(new ArrayList(Arrays
83
										.asList(getValues())));
84
							}
85
						});
86
					}
87
				}
88
			};
89
			this.listenerSupport = new ListenerSupport(listener,
90
					descriptor.getName());
91
			listenerSupport.hookListener(this.object);
92
		}
93
94
		// initialize list without firing events
95
		wrappedList.addAll(Arrays.asList(getValues()));
96
	}
97
98
	public void dispose() {
99
		if (listenerSupport != null) {
100
			listenerSupport.dispose();
101
			listenerSupport = null;
102
		}
103
		super.dispose();
104
	}
105
106
	private Object primGetValues() {
107
		Exception ex = null;
108
		try {
109
			Method readMethod = descriptor.getReadMethod();
110
			if (!readMethod.isAccessible()) {
111
				readMethod.setAccessible(true);
112
			}
113
			return readMethod.invoke(object, new Object[0]);
114
		} catch (IllegalArgumentException e) {
115
			ex = e;
116
		} catch (IllegalAccessException e) {
117
			ex = e;
118
		} catch (InvocationTargetException e) {
119
			ex = e;
120
		}
121
		throw new BindingException("Could not read collection values", ex); //$NON-NLS-1$
122
	}
123
124
	private Object[] getValues() {
125
		Object[] values = null;
126
127
		Object result = primGetValues();
128
		if (descriptor.getPropertyType().isArray())
129
			values = (Object[]) result;
130
		else {
131
			// TODO add jUnit for POJO (var. SettableValue) collections
132
			Collection list = (Collection) result;
133
			if (list != null) {
134
				values = list.toArray();
135
			}
136
		}
137
		if (values == null)
138
			values = new Object[0];
139
		return values;
140
	}
141
142
	public Object getObserved() {
143
		return object;
144
	}
145
146
	public PropertyDescriptor getPropertyDescriptor() {
147
		return descriptor;
148
	}
149
150
	private void setValues() {
151
		if (descriptor.getPropertyType().isArray()) {
152
			Class componentType = descriptor.getPropertyType()
153
					.getComponentType();
154
			Object[] newArray = (Object[]) Array.newInstance(componentType,
155
					wrappedList.size());
156
			wrappedList.toArray(newArray);
157
			primSetValues(newArray);
158
		} else {
159
			// assume that it is a java.util.List
160
			primSetValues(new ArrayList(wrappedList));
161
		}
162
	}
163
164
	private void primSetValues(Object newValue) {
165
		Exception ex = null;
166
		try {
167
			Method writeMethod = descriptor.getWriteMethod();
168
			if (!writeMethod.isAccessible()) {
169
				writeMethod.setAccessible(true);
170
			}
171
			writeMethod.invoke(object, new Object[] { newValue });
172
			return;
173
		} catch (IllegalArgumentException e) {
174
			ex = e;
175
		} catch (IllegalAccessException e) {
176
			ex = e;
177
		} catch (InvocationTargetException e) {
178
			ex = e;
179
		}
180
		throw new BindingException("Could not write collection values", ex); //$NON-NLS-1$
181
	}
182
183
	public Object set(int index, Object element) {
184
		getterCalled();
185
		updating = true;
186
		try {
187
			Object oldElement = wrappedList.set(index, element);
188
			setValues();
189
			fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
190
					index, false, oldElement), Diffs.createListDiffEntry(index,
191
					true, element)));
192
			return oldElement;
193
		} finally {
194
			updating = false;
195
		}
196
	}
197
198
	public Object move(int oldIndex, int newIndex) {
199
		getterCalled();
200
		updating = true;
201
		try {
202
			int size = wrappedList.size();
203
			if (oldIndex < 0 || oldIndex >= size)
204
				throw new IndexOutOfBoundsException(
205
						"oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$
206
			if (newIndex < 0 || newIndex >= size)
207
				throw new IndexOutOfBoundsException(
208
						"newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$
209
			if (oldIndex == newIndex)
210
				return wrappedList.get(oldIndex);
211
			Object element = wrappedList.remove(oldIndex);
212
			wrappedList.add(newIndex, element);
213
			setValues();
214
			fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
215
					oldIndex, false, element), Diffs.createListDiffEntry(
216
					newIndex, true, element)));
217
			return element;
218
		} finally {
219
			updating = false;
220
		}
221
	}
222
223
	public Object remove(int index) {
224
		getterCalled();
225
		updating = true;
226
		try {
227
			Object oldElement = wrappedList.remove(index);
228
			setValues();
229
			fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
230
					index, false, oldElement)));
231
			return oldElement;
232
		} finally {
233
			updating = false;
234
		}
235
	}
236
237
	public boolean add(Object element) {
238
		updating = true;
239
		try {
240
			int index = wrappedList.size();
241
			boolean result = wrappedList.add(element);
242
			setValues();
243
			fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
244
					index, true, element)));
245
			return result;
246
		} finally {
247
			updating = false;
248
		}
249
	}
250
251
	public void add(int index, Object element) {
252
		updating = true;
253
		try {
254
			wrappedList.add(index, element);
255
			setValues();
256
			fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
257
					index, true, element)));
258
		} finally {
259
			updating = false;
260
		}
261
	}
262
263
	public boolean addAll(Collection c) {
264
		if (c.isEmpty()) {
265
			return false;
266
		}
267
		updating = true;
268
		try {
269
			int index = wrappedList.size();
270
			boolean result = wrappedList.addAll(c);
271
			setValues();
272
			ListDiffEntry[] entries = new ListDiffEntry[c.size()];
273
			int i = 0;
274
			for (Iterator it = c.iterator(); it.hasNext();) {
275
				Object o = it.next();
276
				entries[i++] = Diffs.createListDiffEntry(index++, true, o);
277
			}
278
			fireListChange(Diffs.createListDiff(entries));
279
			return result;
280
		} finally {
281
			updating = false;
282
		}
283
	}
284
285
	public boolean addAll(int index, Collection c) {
286
		if (c.isEmpty()) {
287
			return false;
288
		}
289
		updating = true;
290
		try {
291
			boolean result = wrappedList.addAll(index, c);
292
			setValues();
293
			ListDiffEntry[] entries = new ListDiffEntry[c.size()];
294
			int i = 0;
295
			for (Iterator it = c.iterator(); it.hasNext();) {
296
				Object o = it.next();
297
				entries[i++] = Diffs.createListDiffEntry(index++, true, o);
298
			}
299
			fireListChange(Diffs.createListDiff(entries));
300
			return result;
301
		} finally {
302
			updating = false;
303
		}
304
	}
305
306
	public boolean remove(Object o) {
307
		getterCalled();
308
		int index = wrappedList.indexOf(o);
309
		if (index == -1) {
310
			return false;
311
		}
312
		updating = true;
313
		try {
314
			Object oldElement = wrappedList.remove(index);
315
			setValues();
316
			fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
317
					index, false, oldElement)));
318
			return true;
319
		} finally {
320
			updating = false;
321
		}
322
	}
323
324
	public boolean removeAll(Collection c) {
325
		getterCalled();
326
		boolean changed = false;
327
		updating = true;
328
		try {
329
			List diffEntries = new ArrayList();
330
			for (Iterator it = c.iterator(); it.hasNext();) {
331
				Object o = it.next();
332
				int index = wrappedList.indexOf(o);
333
				if (index != -1) {
334
					changed = true;
335
					Object oldElement = wrappedList.remove(index);
336
					diffEntries.add(Diffs.createListDiffEntry(index, false,
337
							oldElement));
338
				}
339
			}
340
			if (changed) {
341
				setValues();
342
				fireListChange(Diffs
343
						.createListDiff((ListDiffEntry[]) diffEntries
344
								.toArray(new ListDiffEntry[diffEntries.size()])));
345
			}
346
			return changed;
347
		} finally {
348
			updating = false;
349
		}
350
	}
351
352
	public boolean retainAll(Collection c) {
353
		getterCalled();
354
		boolean changed = false;
355
		updating = true;
356
		try {
357
			List diffEntries = new ArrayList();
358
			int index = 0;
359
			for (Iterator it = wrappedList.iterator(); it.hasNext();) {
360
				Object o = it.next();
361
				boolean retain = c.contains(o);
362
				if (retain) {
363
					index++;
364
				} else {
365
					changed = true;
366
					it.remove();
367
					diffEntries.add(Diffs.createListDiffEntry(index, false, o));
368
				}
369
			}
370
			if (changed) {
371
				setValues();
372
				fireListChange(Diffs
373
						.createListDiff((ListDiffEntry[]) diffEntries
374
								.toArray(new ListDiffEntry[diffEntries.size()])));
375
			}
376
			return changed;
377
		} finally {
378
			updating = false;
379
		}
380
	}
381
382
	public void clear() {
383
		updating = true;
384
		try {
385
			List diffEntries = new ArrayList();
386
			for (Iterator it = wrappedList.iterator(); it.hasNext();) {
387
				Object o = it.next();
388
				diffEntries.add(Diffs.createListDiffEntry(0, false, o));
389
			}
390
			wrappedList.clear();
391
			setValues();
392
			fireListChange(Diffs.createListDiff((ListDiffEntry[]) diffEntries
393
					.toArray(new ListDiffEntry[diffEntries.size()])));
394
		} finally {
395
			updating = false;
396
		}
397
	}
398
399
}
(-)src/org/eclipse/core/internal/databinding/beans/ListenerSupport.java (-216 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 118516
11
 *******************************************************************************/
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyChangeEvent;
15
import java.beans.PropertyChangeListener;
16
import java.lang.reflect.InvocationTargetException;
17
import java.lang.reflect.Method;
18
import java.util.HashSet;
19
import java.util.Iterator;
20
import java.util.Set;
21
22
import org.eclipse.core.databinding.beans.BeansObservables;
23
import org.eclipse.core.databinding.util.Policy;
24
import org.eclipse.core.runtime.Assert;
25
import org.eclipse.core.runtime.IStatus;
26
import org.eclipse.core.runtime.Status;
27
28
/**
29
 * This is a helper that will hook up and listen for <code>PropertyChangeEvent</code> events
30
 * for a set of target JavaBeans
31
 * 
32
 * @since 1.0
33
 */
34
public class ListenerSupport {
35
36
	private Set elementsListenedTo = new HashSet();
37
	
38
	private PropertyChangeListener listener;
39
40
	private String propertyName;
41
42
	/**
43
	 * Constructs a new instance.
44
	 * 
45
	 * @param listener is the callback that will be called
46
	 * 		when a <code>PropertyChangeEvent</code> is fired on any
47
	 * 		of the target objects.  Will only receive change events 
48
	 * 		when the provided <code>propertyName</code> changes.
49
	 * @param propertyName
50
	 */
51
	public ListenerSupport(final PropertyChangeListener listener,
52
			final String propertyName) {
53
		Assert.isNotNull(listener, "Listener cannot be null"); //$NON-NLS-1$
54
		Assert.isNotNull(propertyName, "Property name cannot be null"); //$NON-NLS-1$
55
56
		this.propertyName = propertyName;
57
		this.listener = new PropertyChangeListener() {
58
			public void propertyChange(PropertyChangeEvent evt) {
59
				if (propertyName.equals(evt.getPropertyName())) {
60
					listener.propertyChange(evt);
61
				}
62
			}
63
		};
64
	}
65
66
	/**
67
	 * Start listen to target (if it supports the JavaBean property change listener pattern)
68
	 * 
69
	 * @param target
70
	 */
71
	public void hookListener(Object target) {
72
		if (processListener(
73
				"addPropertyChangeListener", "Could not attach listener to ", target)) { //$NON-NLS-1$ //$NON-NLS-2$
74
			elementsListenedTo.add(new IdentityWrapper(target));
75
		}
76
	}
77
		
78
	/**
79
	 * Add listeners for new targets (those this instance of<code>ListenerSupport</code> does not 
80
	 * already listen to),
81
	 * Stop to listen to those object that this instance listen to and is one of the object in targets 
82
	 * 
83
	 * @param targets 
84
	 */
85
	public void setHookTargets(Object[] targets) {		
86
		Set elementsToUnhook = new HashSet(elementsListenedTo);
87
		if (targets!=null) {
88
			for (int i = 0; i < targets.length; i++) {
89
				Object newValue = targets[i];
90
				IdentityWrapper identityWrapper = new IdentityWrapper(newValue);
91
				if(!elementsToUnhook.remove(identityWrapper)) 				
92
					hookListener(newValue);
93
			}
94
		}
95
			
96
		for (Iterator it = elementsToUnhook.iterator(); it.hasNext();) {
97
			Object o = it.next();
98
			if (o.getClass()!=IdentityWrapper.class)
99
				o = new IdentityWrapper(o);
100
			elementsListenedTo.remove(o);
101
			unhookListener(o);
102
		}							
103
	}
104
	
105
	/**
106
	 * Stop listen to target
107
	 * 
108
	 * @param target
109
	 */
110
	public void unhookListener(Object target) {
111
		if (target.getClass() == IdentityWrapper.class)
112
			target = ((IdentityWrapper) target).unwrap();
113
114
		if (processListener(
115
				"removePropertyChangeListener", "Cound not remove listener from ", target)) { //$NON-NLS-1$//$NON-NLS-2$
116
			elementsListenedTo.remove(new IdentityWrapper(target));
117
		}
118
	}
119
	
120
	
121
	/**
122
	 * 
123
	 */
124
	public void dispose() {
125
		if (elementsListenedTo!=null) {
126
			Object[] targets = elementsListenedTo.toArray();		
127
			for (int i = 0; i < targets.length; i++) {		
128
				unhookListener(targets[i]);
129
			}			
130
			elementsListenedTo=null;
131
			listener=null;
132
		}
133
	}
134
	
135
	/**
136
	 * @return elements that were registred to
137
	 */
138
	public Object[] getHookedTargets() {
139
		Object[] targets = null;
140
		if (elementsListenedTo!=null && elementsListenedTo.size()>0) {
141
			Object[] identityList = elementsListenedTo.toArray();
142
			targets = new Object[identityList.length];
143
			for (int i = 0; i < identityList.length; i++) 
144
				targets[i]=((IdentityWrapper)identityList[i]).unwrap();							
145
		}
146
		return targets;
147
	}
148
149
	/**
150
	 * Invokes the method for the provided <code>methodName</code> attempting
151
	 * to first use the method with the property name and then the unnamed
152
	 * version.
153
	 * 
154
	 * @param methodName
155
	 *            either addPropertyChangeListener or
156
	 *            removePropertyChangeListener
157
	 * @param message
158
	 *            string that will be prefixed to the target in an error message
159
	 * @param target
160
	 *            object to invoke the method on
161
	 * @return <code>true</code> if the method was invoked successfully
162
	 */
163
	private boolean processListener(String methodName, String message,
164
			Object target) {
165
		Method method = null;
166
		Object[] parameters = null;
167
168
		try {
169
			try {
170
				method = target.getClass().getMethod(
171
						methodName,
172
						new Class[] { String.class,
173
								PropertyChangeListener.class });
174
175
				parameters = new Object[] { propertyName, listener };
176
			} catch (NoSuchMethodException e) {
177
				method = target.getClass().getMethod(methodName,
178
						new Class[] { PropertyChangeListener.class });
179
180
				parameters = new Object[] { listener };
181
			}
182
		} catch (SecurityException e) {
183
			// ignore
184
		} catch (NoSuchMethodException e) {
185
			log(IStatus.WARNING, message + target, e);
186
		}
187
188
		if (method != null) {
189
			if (!method.isAccessible()) {
190
				method.setAccessible(true);
191
			}
192
			try {
193
				method.invoke(target, parameters);
194
				return true;
195
			} catch (IllegalArgumentException e) {
196
				log(IStatus.WARNING, message + target, e);
197
			} catch (IllegalAccessException e) {
198
				log(IStatus.WARNING, message + target, e);
199
			} catch (InvocationTargetException e) {
200
				log(IStatus.WARNING, message + target, e);
201
			}
202
		}
203
		return false;
204
	}
205
206
	/**
207
	 * Logs a message to the Data Binding logger.
208
	 */
209
	private void log(int severity, String message, Throwable throwable) {
210
		if (BeansObservables.DEBUG) {
211
			Policy.getLog().log(
212
					new Status(severity, Policy.JFACE_DATABINDING, IStatus.OK,
213
							message, throwable));
214
		}
215
	}
216
}
(-)src/org/eclipse/core/internal/databinding/beans/JavaBeanPropertyObservableMap.java (-263 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 221704)
10
 *     Matthew Hall - bug 223164, 226289, 244098, 246103
11
 *******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyChangeEvent;
16
import java.beans.PropertyChangeListener;
17
import java.beans.PropertyDescriptor;
18
import java.lang.reflect.InvocationTargetException;
19
import java.lang.reflect.Method;
20
import java.util.Collections;
21
import java.util.HashMap;
22
import java.util.HashSet;
23
import java.util.Iterator;
24
import java.util.Map;
25
import java.util.Set;
26
27
import org.eclipse.core.databinding.BindingException;
28
import org.eclipse.core.databinding.beans.IBeanObservable;
29
import org.eclipse.core.databinding.observable.Diffs;
30
import org.eclipse.core.databinding.observable.Realm;
31
import org.eclipse.core.databinding.observable.map.ObservableMap;
32
import org.eclipse.core.internal.databinding.Util;
33
import org.eclipse.core.runtime.Assert;
34
35
/**
36
 * @since 1.0
37
 * 
38
 */
39
public class JavaBeanPropertyObservableMap extends ObservableMap implements
40
		IBeanObservable {
41
42
	private final Object object;
43
44
	private Object keyType;
45
	private Object valueType;
46
47
	private boolean updating = false;
48
49
	private PropertyDescriptor descriptor;
50
51
	private ListenerSupport listenerSupport;
52
53
	/**
54
	 * @param realm
55
	 * @param object
56
	 * @param descriptor
57
	 * @param keyType
58
	 * @param valueType
59
	 */
60
	public JavaBeanPropertyObservableMap(Realm realm, Object object,
61
			PropertyDescriptor descriptor, Object keyType, Object valueType) {
62
		this(realm, object, descriptor, keyType, valueType, true);
63
	}
64
65
	/**
66
	 * @param realm
67
	 * @param object
68
	 * @param descriptor
69
	 * @param keyType
70
	 * @param valueType
71
	 * @param attachListeners
72
	 */
73
	public JavaBeanPropertyObservableMap(Realm realm, Object object,
74
			PropertyDescriptor descriptor, Object keyType, Object valueType,
75
			boolean attachListeners) {
76
		super(realm, new HashMap());
77
		this.object = object;
78
		this.descriptor = descriptor;
79
		this.keyType = keyType;
80
		this.valueType = valueType;
81
		if (attachListeners) {
82
			PropertyChangeListener listener = new PropertyChangeListener() {
83
				public void propertyChange(final PropertyChangeEvent event) {
84
					if (!updating) {
85
						getRealm().exec(new Runnable() {
86
							public void run() {
87
								Map oldMap = (Map) event.getOldValue();
88
								Map newMap = (Map) event.getNewValue();
89
								if (oldMap == null && newMap == null) {
90
									oldMap = wrappedMap;
91
									newMap = getMap();
92
								}
93
94
								if (!Util.equals(oldMap, newMap)) {
95
									wrappedMap = new HashMap(newMap);
96
									fireMapChange(Diffs.computeMapDiff(oldMap,
97
											newMap));
98
								}
99
							}
100
						});
101
					}
102
				}
103
			};
104
105
			listenerSupport = new ListenerSupport(listener,
106
					descriptor.getName());
107
			listenerSupport.hookListener(this.object);
108
		}
109
110
		wrappedMap.putAll(getMap());
111
	}
112
113
	public Object getKeyType() {
114
		return keyType;
115
	}
116
117
	public Object getValueType() {
118
		return valueType;
119
	}
120
121
	private Object primGetMap() {
122
		try {
123
			Method readMethod = descriptor.getReadMethod();
124
			if (!readMethod.isAccessible()) {
125
				readMethod.setAccessible(true);
126
			}
127
			return readMethod.invoke(object, new Object[0]);
128
		} catch (IllegalArgumentException e) {
129
		} catch (IllegalAccessException e) {
130
		} catch (InvocationTargetException e) {
131
		}
132
		Assert.isTrue(false, "Could not read collection values"); //$NON-NLS-1$
133
		return null;
134
	}
135
136
	private void primSetMap(Object newValue) {
137
		Exception ex = null;
138
		try {
139
			Method writeMethod = descriptor.getWriteMethod();
140
			if (!writeMethod.isAccessible()) {
141
				writeMethod.setAccessible(true);
142
			}
143
			writeMethod.invoke(object, new Object[] { newValue });
144
			return;
145
		} catch (IllegalArgumentException e) {
146
			ex = e;
147
		} catch (IllegalAccessException e) {
148
			ex = e;
149
		} catch (InvocationTargetException e) {
150
			ex = e;
151
		}
152
		throw new BindingException("Could not write collection values", ex); //$NON-NLS-1$
153
	}
154
155
	private Map getMap() {
156
		Map result = (Map) primGetMap();
157
158
		if (result == null)
159
			result = new HashMap();
160
		return result;
161
	}
162
163
	private void setMap() {
164
		primSetMap(new HashMap(wrappedMap));
165
	}
166
167
	public Object put(Object key, Object value) {
168
		checkRealm();
169
		updating = true;
170
		try {
171
			boolean add = !wrappedMap.containsKey(key);
172
			Object result = wrappedMap.put(key, value);
173
			if (!Util.equals(result, value)) {
174
				setMap();
175
				if (add) {
176
					fireMapChange(Diffs.createMapDiffSingleAdd(key, value));
177
				} else {
178
					fireMapChange(Diffs.createMapDiffSingleChange(key, result,
179
							value));
180
				}
181
			}
182
			return result;
183
		} finally {
184
			updating = false;
185
		}
186
	}
187
188
	public void putAll(Map map) {
189
		checkRealm();
190
		updating = true;
191
		try {
192
			Set addedKeys = new HashSet(map.size());
193
			Map changes = new HashMap(map.size());
194
			for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
195
				Map.Entry entry = (Entry) it.next();
196
				Object key = entry.getKey();
197
				Object newValue = entry.getValue();
198
				boolean add = !wrappedMap.containsKey(key);
199
				Object oldValue = wrappedMap.put(key, newValue);
200
				if (add) {
201
					addedKeys.add(key);
202
				} else if (!Util.equals(oldValue, newValue)) {
203
					changes.put(key, oldValue);
204
				}
205
			}
206
			if (!addedKeys.isEmpty() || !changes.isEmpty()) {
207
				setMap();
208
				fireMapChange(Diffs.createMapDiff(addedKeys,
209
						Collections.EMPTY_SET, changes.keySet(), changes,
210
						wrappedMap));
211
			}
212
		} finally {
213
			updating = false;
214
		}
215
	}
216
217
	public Object remove(Object key) {
218
		checkRealm();
219
		if (!wrappedMap.containsKey(key)) {
220
			return null;
221
		}
222
		updating = true;
223
		try {
224
			Object result = wrappedMap.remove(key);
225
			setMap();
226
			fireMapChange(Diffs.createMapDiffSingleRemove(key, result));
227
			return result;
228
		} finally {
229
			updating = false;
230
		}
231
	}
232
233
	public void clear() {
234
		checkRealm();
235
		if (wrappedMap.isEmpty())
236
			return;
237
		updating = true;
238
		try {
239
			Map oldMap = wrappedMap;
240
			wrappedMap = new HashMap();
241
			setMap();
242
			fireMapChange(Diffs.computeMapDiff(oldMap, Collections.EMPTY_MAP));
243
		} finally {
244
			updating = false;
245
		}
246
	}
247
248
	public Object getObserved() {
249
		return object;
250
	}
251
252
	public PropertyDescriptor getPropertyDescriptor() {
253
		return descriptor;
254
	}
255
256
	public synchronized void dispose() {
257
		if (listenerSupport != null) {
258
			listenerSupport.dispose();
259
			listenerSupport = null;
260
		}
261
		super.dispose();
262
	}
263
}
(-)src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableSet.java (-301 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006-2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 171616
11
 *     Matthew Hall - bugs 221351, 223164, 244098
12
 *******************************************************************************/
13
14
package org.eclipse.core.internal.databinding.beans;
15
16
import java.beans.PropertyChangeListener;
17
import java.beans.PropertyDescriptor;
18
import java.lang.reflect.Array;
19
import java.lang.reflect.InvocationTargetException;
20
import java.lang.reflect.Method;
21
import java.util.Arrays;
22
import java.util.Collection;
23
import java.util.Collections;
24
import java.util.HashSet;
25
import java.util.Iterator;
26
import java.util.Set;
27
28
import org.eclipse.core.databinding.BindingException;
29
import org.eclipse.core.databinding.beans.IBeanObservable;
30
import org.eclipse.core.databinding.observable.Diffs;
31
import org.eclipse.core.databinding.observable.Realm;
32
import org.eclipse.core.databinding.observable.set.ObservableSet;
33
import org.eclipse.core.runtime.Assert;
34
35
/**
36
 * @since 1.0
37
 * 
38
 */
39
public class JavaBeanObservableSet extends ObservableSet implements IBeanObservable {
40
41
	private final Object object;
42
43
	private boolean updating = false;
44
45
	private PropertyDescriptor descriptor;
46
47
	private ListenerSupport listenerSupport;
48
49
	/**
50
	 * @param realm
51
	 * @param object
52
	 * @param descriptor
53
	 * @param elementType
54
	 */
55
	public JavaBeanObservableSet(Realm realm, Object object,
56
			PropertyDescriptor descriptor, Class elementType) {
57
		this(realm, object, descriptor, elementType, true);
58
	}
59
60
	/**
61
	 * @param realm
62
	 * @param object
63
	 * @param descriptor
64
	 * @param elementType
65
	 * @param attachListeners
66
	 */
67
	public JavaBeanObservableSet(Realm realm, Object object,
68
			PropertyDescriptor descriptor, Class elementType,
69
			boolean attachListeners) {
70
		super(realm, new HashSet(), elementType);
71
		this.object = object;
72
		this.descriptor = descriptor;
73
		if (attachListeners) {
74
			PropertyChangeListener listener = new PropertyChangeListener() {
75
				public void propertyChange(java.beans.PropertyChangeEvent event) {
76
					if (!updating) {
77
						getRealm().exec(new Runnable() {
78
							public void run() {
79
								Set newElements = new HashSet(Arrays
80
										.asList(getValues()));
81
								Set addedElements = new HashSet(newElements);
82
								Set removedElements = new HashSet(wrappedSet);
83
								// remove all new elements from old elements to
84
								// compute
85
								// the removed elements
86
								removedElements.removeAll(newElements);
87
								addedElements.removeAll(wrappedSet);
88
								wrappedSet = newElements;
89
								fireSetChange(Diffs.createSetDiff(
90
										addedElements, removedElements));
91
							}
92
						});
93
					}
94
				}
95
			};
96
			this.listenerSupport = new ListenerSupport(listener, descriptor
97
					.getName());
98
			listenerSupport.hookListener(this.object);
99
		}
100
101
		wrappedSet.addAll(Arrays.asList(getValues()));
102
	}
103
104
	private Object primGetValues() {
105
		try {
106
			Method readMethod = descriptor.getReadMethod();
107
			if (!readMethod.isAccessible()) {
108
				readMethod.setAccessible(true);
109
			}
110
			return readMethod.invoke(object, new Object[0]);
111
		} catch (IllegalArgumentException e) {
112
		} catch (IllegalAccessException e) {
113
		} catch (InvocationTargetException e) {
114
		}
115
		Assert.isTrue(false, "Could not read collection values"); //$NON-NLS-1$
116
		return null;
117
	}
118
119
	private Object[] getValues() {
120
		Object[] values = null;
121
122
		Object result = primGetValues();
123
		if (descriptor.getPropertyType().isArray())
124
			values = (Object[]) result;
125
		else {
126
			// TODO add jUnit for POJO (var. SettableValue) collections
127
			Collection list = (Collection) result;
128
			if (list != null)
129
				values = list.toArray();
130
		}
131
		if (values == null)
132
			values = new Object[0];
133
		return values;
134
	}
135
136
	private void setValues() {
137
		if (descriptor.getPropertyType().isArray()) {
138
			Class componentType = descriptor.getPropertyType()
139
					.getComponentType();
140
			Object[] newArray = (Object[]) Array.newInstance(componentType,
141
					wrappedSet.size());
142
			wrappedSet.toArray(newArray);
143
			primSetValues(newArray);
144
		} else {
145
			// assume that it is a java.util.Set
146
			primSetValues(new HashSet(wrappedSet));
147
		}
148
	}
149
150
	public boolean add(Object o) {
151
		getterCalled();
152
		updating = true;
153
		try {
154
			boolean added = wrappedSet.add(o);
155
			if (added) {
156
				setValues();
157
				fireSetChange(Diffs.createSetDiff(Collections.singleton(o),
158
						Collections.EMPTY_SET));
159
			}
160
			return added;
161
		} finally {
162
			updating = false;
163
		}
164
	}
165
166
	public boolean remove(Object o) {
167
		getterCalled();
168
		updating = true;
169
		try {
170
			boolean removed = wrappedSet.remove(o);
171
			if (removed) {
172
				setValues();
173
				fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
174
						Collections.singleton(o)));
175
			}
176
			return removed;
177
		} finally {
178
			updating = false;
179
		}
180
	}
181
182
	public boolean addAll(Collection c) {
183
		getterCalled();
184
		updating = true;
185
		try {
186
			Set additions = new HashSet();
187
			for (Iterator iterator = c.iterator(); iterator.hasNext();) {
188
				Object element = iterator.next();
189
				if (wrappedSet.add(element))
190
					additions.add(element);
191
			}
192
			boolean changed = !additions.isEmpty();
193
			if (changed) {
194
				setValues();
195
				fireSetChange(Diffs.createSetDiff(additions,
196
						Collections.EMPTY_SET));
197
			}
198
			return changed;
199
		} finally {
200
			updating = false;
201
		}
202
	}
203
204
	public boolean removeAll(Collection c) {
205
		getterCalled();
206
		updating = true;
207
		try {
208
			Set removals = new HashSet();
209
			for (Iterator iterator = c.iterator(); iterator.hasNext();) {
210
				Object element = iterator.next();
211
				if (wrappedSet.remove(element))
212
					removals.add(element);
213
			}
214
			boolean changed = !removals.isEmpty();
215
			if (changed) {
216
				setValues();
217
				fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
218
						removals));
219
			}
220
			return changed;
221
		} finally {
222
			updating = false;
223
		}
224
	}
225
226
	public boolean retainAll(Collection c) {
227
		getterCalled();
228
		updating = true;
229
		try {
230
			Set removals = new HashSet();
231
			for (Iterator iterator = wrappedSet.iterator(); iterator.hasNext();) {
232
				Object element = iterator.next();
233
				if (!c.contains(element)) {
234
					iterator.remove();
235
					removals.add(element);
236
				}
237
			}
238
			boolean changed = !removals.isEmpty();
239
			if (changed) {
240
				setValues();
241
				fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
242
						removals));
243
			}
244
			return changed;
245
		} finally {
246
			updating = false;
247
		}
248
	}
249
250
	public void clear() {
251
		getterCalled();
252
		if (wrappedSet.isEmpty())
253
			return;
254
255
		updating = true;
256
		try {
257
			Set removals = new HashSet(wrappedSet);
258
			wrappedSet.clear();
259
			setValues();
260
			fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
261
		} finally {
262
			updating = false;
263
		}
264
	}
265
266
	private void primSetValues(Object newValue) {
267
		Exception ex = null;
268
		try {
269
			Method writeMethod = descriptor.getWriteMethod();
270
			if (!writeMethod.isAccessible()) {
271
				writeMethod.setAccessible(true);
272
			}
273
			writeMethod.invoke(object, new Object[] { newValue });
274
			return;
275
		} catch (IllegalArgumentException e) {
276
			ex = e;
277
		} catch (IllegalAccessException e) {
278
			ex = e;
279
		} catch (InvocationTargetException e) {
280
			ex = e;
281
		}
282
		throw new BindingException("Could not write collection values", ex); //$NON-NLS-1$
283
	}
284
285
	public Object getObserved() {
286
		return object;
287
	}
288
289
	public PropertyDescriptor getPropertyDescriptor() {
290
		return descriptor;
291
	}
292
293
	public synchronized void dispose() {
294
		if (listenerSupport != null) {
295
			listenerSupport.dispose();
296
			listenerSupport = null;
297
		}
298
299
		super.dispose();
300
	}
301
}
(-)src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableValue.java (-221 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 164653
11
 *     Brad Reynolds - bug 164134, 171616
12
 *     Matthew Hall - bug 246103
13
 *******************************************************************************/
14
package org.eclipse.core.internal.databinding.beans;
15
16
import java.beans.PropertyChangeListener;
17
import java.beans.PropertyDescriptor;
18
import java.lang.reflect.InvocationTargetException;
19
import java.lang.reflect.Method;
20
21
import org.eclipse.core.databinding.BindingException;
22
import org.eclipse.core.databinding.beans.BeansObservables;
23
import org.eclipse.core.databinding.beans.IBeanObservable;
24
import org.eclipse.core.databinding.observable.Diffs;
25
import org.eclipse.core.databinding.observable.Realm;
26
import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
27
import org.eclipse.core.databinding.util.Policy;
28
import org.eclipse.core.internal.databinding.Util;
29
import org.eclipse.core.runtime.IStatus;
30
import org.eclipse.core.runtime.Status;
31
32
/**
33
 * @since 1.0
34
 * 
35
 */
36
public class JavaBeanObservableValue extends AbstractObservableValue implements IBeanObservable {
37
	private final Object object;
38
	private boolean updating = false;
39
40
	private final PropertyDescriptor propertyDescriptor;
41
	private ListenerSupport listenerSupport;
42
43
	private boolean attachListeners;
44
45
	// Applicable only while hasListeners() == true
46
	private Object cachedValue;
47
48
	/**
49
	 * @param realm
50
	 * @param object
51
	 * @param descriptor
52
	 */
53
	public JavaBeanObservableValue(Realm realm, Object object,
54
			PropertyDescriptor descriptor) {
55
		this(realm, object, descriptor, true);
56
	}
57
58
	/**
59
	 * @param realm
60
	 * @param object
61
	 * @param descriptor
62
	 * @param attachListeners
63
	 */
64
	public JavaBeanObservableValue(Realm realm, Object object,
65
			PropertyDescriptor descriptor, boolean attachListeners) {
66
		super(realm);
67
		this.object = object;
68
		this.propertyDescriptor = descriptor;
69
		this.attachListeners = attachListeners;
70
	}
71
72
	protected void firstListenerAdded() {
73
		if (!attachListeners) {
74
			return;
75
		}
76
77
		if (listenerSupport == null) {
78
			PropertyChangeListener listener = new PropertyChangeListener() {
79
				public void propertyChange(
80
						final java.beans.PropertyChangeEvent event) {
81
					if (!updating) {
82
						getRealm().exec(new Runnable() {
83
							public void run() {
84
								Object oldValue = event.getOldValue();
85
								Object newValue = event.getNewValue();
86
								if (oldValue == null && newValue == null) {
87
									// this condition is provided for in the
88
									// bean spec, and indicates that an 
89
									// unknown change occured.
90
91
									oldValue = cachedValue;
92
									newValue = doGetValue();
93
								}
94
								cachedValue = newValue;
95
								if (!Util.equals(oldValue, newValue)) {
96
									fireValueChange(Diffs.createValueDiff(
97
											oldValue, newValue));
98
								}
99
							}
100
						});
101
					}
102
				}
103
			};
104
			listenerSupport = new ListenerSupport(listener, propertyDescriptor
105
					.getName());
106
		}
107
		
108
		listenerSupport.hookListener(object);
109
		cachedValue = doGetValue();
110
	}
111
112
	public void doSetValue(Object value) {
113
		updating = true;
114
		try {
115
			Object oldValue = doGetValue();
116
			
117
			if (!Util.equals(oldValue, value)) {
118
				Method writeMethod = propertyDescriptor.getWriteMethod();
119
				if (!writeMethod.isAccessible()) {
120
					writeMethod.setAccessible(true);
121
				}
122
				writeMethod.invoke(object, new Object[] { value });
123
			}
124
			
125
			if (hasListeners()) {
126
				// oldValue contains the live value which may be different from
127
				// the cached value if the bean does not have listener API or
128
				// does not fire events properly. For consistency we want to
129
				// provide the cached value as the old value, rather than the
130
				// live value so that consumers that hook/unhook listeners can
131
				// do so without maintaining caches of their own.
132
				oldValue = cachedValue;
133
				cachedValue = doGetValue();
134
				if (!Util.equals(oldValue, cachedValue)) {
135
					fireValueChange(Diffs
136
							.createValueDiff(oldValue, cachedValue));
137
				}
138
			}
139
		} catch (InvocationTargetException e) {
140
			/*
141
			 * InvocationTargetException wraps any exception thrown by the
142
			 * invoked method.
143
			 */
144
			throw new RuntimeException(e.getCause());
145
		} catch (Exception e) {
146
			if (BeansObservables.DEBUG) {
147
				Policy
148
						.getLog()
149
						.log(
150
								new Status(
151
										IStatus.WARNING,
152
										Policy.JFACE_DATABINDING,
153
										IStatus.OK,
154
										"Could not change value of " + object + "." + propertyDescriptor.getName(), e)); //$NON-NLS-1$ //$NON-NLS-2$
155
			}
156
		} finally {
157
			updating = false;
158
		}
159
	}
160
161
	public Object doGetValue() {
162
		try {
163
			Method readMethod = propertyDescriptor.getReadMethod();
164
			if (readMethod == null) {
165
				throw new BindingException(propertyDescriptor.getName()
166
						+ " property does not have a read method."); //$NON-NLS-1$
167
			}
168
			if (!readMethod.isAccessible()) {
169
				readMethod.setAccessible(true);
170
			}
171
			return readMethod.invoke(object, null);
172
		} catch (InvocationTargetException e) {
173
			/*
174
			 * InvocationTargetException wraps any exception thrown by the
175
			 * invoked method.
176
			 */
177
			throw new RuntimeException(e.getCause());
178
		} catch (Exception e) {
179
			if (BeansObservables.DEBUG) {
180
				Policy
181
						.getLog()
182
						.log(
183
								new Status(
184
										IStatus.WARNING,
185
										Policy.JFACE_DATABINDING,
186
										IStatus.OK,
187
										"Could not read value of " + object + "." + propertyDescriptor.getName(), e)); //$NON-NLS-1$ //$NON-NLS-2$
188
			}
189
			return null;
190
		}
191
	}
192
193
	protected void lastListenerRemoved() {
194
		unhookListener();
195
	}
196
197
	private void unhookListener() {
198
		cachedValue = null;
199
		if (listenerSupport != null) {
200
			listenerSupport.dispose();
201
			listenerSupport = null;
202
		}
203
	}
204
205
	public Object getValueType() {
206
		return propertyDescriptor.getPropertyType();
207
	}
208
209
	public Object getObserved() {
210
		return object;
211
	}
212
213
	public PropertyDescriptor getPropertyDescriptor() {
214
		return propertyDescriptor;
215
	}
216
217
	public synchronized void dispose() {
218
		unhookListener();
219
		super.dispose();
220
	}
221
}
(-)src/org/eclipse/core/databinding/beans/BeansObservables.java (-172 / +140 lines)
Lines 8-24 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bugs 164268, 171616, 147515
10
 *     Brad Reynolds - bugs 164268, 171616, 147515
11
 *     Matthew Hall - bug 221704, 234686, 246625, 226289, 246782
11
 *     Matthew Hall - bug 221704, 234686, 246625, 226289, 246782, 194734,
12
 *                    195222, 247997
12
 *     Thomas Kratz - bug 213787
13
 *     Thomas Kratz - bug 213787
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.core.databinding.beans;
15
package org.eclipse.core.databinding.beans;
15
16
16
import java.beans.BeanInfo;
17
import java.beans.IntrospectionException;
18
import java.beans.Introspector;
19
import java.beans.PropertyDescriptor;
17
import java.beans.PropertyDescriptor;
20
18
21
import org.eclipse.core.databinding.BindingException;
22
import org.eclipse.core.databinding.observable.IObservable;
19
import org.eclipse.core.databinding.observable.IObservable;
23
import org.eclipse.core.databinding.observable.Realm;
20
import org.eclipse.core.databinding.observable.Realm;
24
import org.eclipse.core.databinding.observable.list.IObservableList;
21
import org.eclipse.core.databinding.observable.list.IObservableList;
Lines 33-43 Link Here
33
import org.eclipse.core.internal.databinding.beans.BeanObservableMapDecorator;
30
import org.eclipse.core.internal.databinding.beans.BeanObservableMapDecorator;
34
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator;
31
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator;
35
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator;
32
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator;
36
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList;
33
import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper;
37
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableMap;
38
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet;
39
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableValue;
40
import org.eclipse.core.internal.databinding.beans.JavaBeanPropertyObservableMap;
41
import org.eclipse.core.runtime.Assert;
34
import org.eclipse.core.runtime.Assert;
42
import org.eclipse.core.runtime.IStatus;
35
import org.eclipse.core.runtime.IStatus;
43
import org.eclipse.core.runtime.Status;
36
import org.eclipse.core.runtime.Status;
Lines 64-70 Link Here
64
	 * @param bean
57
	 * @param bean
65
	 *            the object
58
	 *            the object
66
	 * @param propertyName
59
	 * @param propertyName
67
	 *            the name of the property
60
	 *            the name of the property. May be nested e.g. "parent.name"
68
	 * @return an observable value tracking the current value of the named
61
	 * @return an observable value tracking the current value of the named
69
	 *         property of the given bean
62
	 *         property of the given bean
70
	 */
63
	 */
Lines 81-115 Link Here
81
	 * @param bean
74
	 * @param bean
82
	 *            the object
75
	 *            the object
83
	 * @param propertyName
76
	 * @param propertyName
84
	 *            the name of the property
77
	 *            the name of the property. May be nested e.g. "parent.name"
85
	 * @return an observable value tracking the current value of the named
78
	 * @return an observable value tracking the current value of the named
86
	 *         property of the given bean
79
	 *         property of the given bean
87
	 */
80
	 */
88
	public static IObservableValue observeValue(Realm realm, Object bean,
81
	public static IObservableValue observeValue(Realm realm, Object bean,
89
			String propertyName) {
82
			String propertyName) {
90
		PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(),
83
		return BeanProperties.value(bean.getClass(), propertyName).observe(
91
				propertyName);
84
				realm, bean);
92
		return new JavaBeanObservableValue(realm, bean, descriptor);
93
	}
85
	}
94
86
95
	/**
87
	/**
96
	 * Returns an observable map in the default realm tracking the current
88
	 * Returns an observable map in the given observable set's realm tracking
97
	 * values of the named property for the beans in the given set.
89
	 * the current values of the named property for the beans in the given set.
90
	 * Elements in the set which do not have the named property will have null
91
	 * values, and attempts to {@link IObservableMap#put(Object, Object) put}
92
	 * values to these elements will be ignored.
93
	 * 
94
	 * @param domain
95
	 *            the set of bean objects
96
	 * @param propertyName
97
	 *            the name of the property. May be nested e.g. "parent.name"
98
	 * @return an observable map tracking the current values of the named
99
	 *         property for the beans in the given domain set
100
	 * @since 1.2
101
	 */
102
	public static IObservableMap observeMap(IObservableSet domain,
103
			String propertyName) {
104
		return BeanProperties.value(propertyName).observeDetail(domain);
105
	}
106
107
	/**
108
	 * Returns an observable map in the given observable set's realm tracking
109
	 * the current values of the named property for the beans in the given set.
98
	 * 
110
	 * 
99
	 * @param domain
111
	 * @param domain
100
	 *            the set of bean objects
112
	 *            the set of bean objects
101
	 * @param beanClass
113
	 * @param beanClass
102
	 *            the common base type of bean objects that may be in the set
114
	 *            the common base type of bean objects that may be in the set
103
	 * @param propertyName
115
	 * @param propertyName
104
	 *            the name of the property
116
	 *            the name of the property. May be nested e.g. "parent.name"
105
	 * @return an observable map tracking the current values of the named
117
	 * @return an observable map tracking the current values of the named
106
	 *         property for the beans in the given domain set
118
	 *         property for the beans in the given domain set
107
	 */
119
	 */
108
	public static IObservableMap observeMap(IObservableSet domain,
120
	public static IObservableMap observeMap(IObservableSet domain,
109
			Class beanClass, String propertyName) {
121
			Class beanClass, String propertyName) {
110
		PropertyDescriptor descriptor = getPropertyDescriptor(beanClass,
122
		return BeanProperties.value(beanClass, propertyName).observeDetail(
111
				propertyName);
123
				domain);
112
		return new JavaBeanObservableMap(domain, descriptor);
113
	}
124
	}
114
125
115
	/**
126
	/**
Lines 121-127 Link Here
121
	 * @param bean
132
	 * @param bean
122
	 *            the bean object
133
	 *            the bean object
123
	 * @param propertyName
134
	 * @param propertyName
124
	 *            the name of the property
135
	 *            the name of the property. May be nested e.g. "parent.name"
125
	 * @return an observable map tracking the map-typed named property of the
136
	 * @return an observable map tracking the map-typed named property of the
126
	 *         given bean object
137
	 *         given bean object
127
	 * @since 1.1
138
	 * @since 1.1
Lines 140-146 Link Here
140
	 * @param bean
151
	 * @param bean
141
	 *            the bean object
152
	 *            the bean object
142
	 * @param propertyName
153
	 * @param propertyName
143
	 *            the name of the property
154
	 *            the name of the property. May be nested e.g. "parent.name"
144
	 * @param keyType
155
	 * @param keyType
145
	 *            the element type of the observable map's key set, or
156
	 *            the element type of the observable map's key set, or
146
	 *            <code>null</code> if untyped
157
	 *            <code>null</code> if untyped
Lines 153-162 Link Here
153
	 */
164
	 */
154
	public static IObservableMap observeMap(Realm realm, Object bean,
165
	public static IObservableMap observeMap(Realm realm, Object bean,
155
			String propertyName, Class keyType, Class valueType) {
166
			String propertyName, Class keyType, Class valueType) {
156
		PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(),
167
		return BeanProperties.map(bean.getClass(), propertyName, keyType,
157
				propertyName);
168
				valueType).observe(realm, bean);
158
		return new JavaBeanPropertyObservableMap(realm, bean, descriptor,
159
				keyType, valueType);
160
	}
169
	}
161
170
162
	/**
171
	/**
Lines 166-172 Link Here
166
	 * @param bean
175
	 * @param bean
167
	 *            the bean object
176
	 *            the bean object
168
	 * @param propertyName
177
	 * @param propertyName
169
	 *            the name of the property
178
	 *            the name of the property. May be nested e.g. "parent.name"
170
	 * @return an observable map tracking the map-typed named property of the
179
	 * @return an observable map tracking the map-typed named property of the
171
	 *         given bean object
180
	 *         given bean object
172
	 * @since 1.2
181
	 * @since 1.2
Lines 193-233 Link Here
193
	 *         given bean object
202
	 *         given bean object
194
	 * @since 1.2
203
	 * @since 1.2
195
	 */
204
	 */
196
	public static IObservableMap observeMap(Object bean, String propertyName, Class keyType, Class valueType) {
205
	public static IObservableMap observeMap(Object bean, String propertyName,
197
		return observeMap(Realm.getDefault(), bean, propertyName, keyType, valueType);
206
			Class keyType, Class valueType) {
207
		return observeMap(Realm.getDefault(), bean, propertyName, keyType,
208
				valueType);
198
	}
209
	}
199
210
200
	/*package*/ static PropertyDescriptor getPropertyDescriptor(Class beanClass,
211
	/**
201
			String propertyName) {
212
	 * Returns an array of observable maps in the given observable set's realm
202
		BeanInfo beanInfo;
213
	 * tracking the current values of the named properties for the beans in the
203
		try {
214
	 * given set. Elements in the set which do not have the named property will
204
			beanInfo = Introspector.getBeanInfo(beanClass);
215
	 * have null values, and attempts to
205
		} catch (IntrospectionException e) {
216
	 * {@link IObservableMap#put(Object, Object) put} values to these elements
206
			// cannot introspect, give up
217
	 * will be ignored.
207
			return null;
218
	 * 
208
		}
219
	 * @param domain
209
		PropertyDescriptor[] propertyDescriptors = beanInfo
220
	 *            the set of objects
210
				.getPropertyDescriptors();
221
	 * @param propertyNames
211
		for (int i = 0; i < propertyDescriptors.length; i++) {
222
	 *            the array of property names. May be nested e.g. "parent.name"
212
			PropertyDescriptor descriptor = propertyDescriptors[i];
223
	 * @return an array of observable maps tracking the current values of the
213
			if (descriptor.getName().equals(propertyName)) {
224
	 *         named propertys for the beans in the given domain set
214
				return descriptor;
225
	 * @since 1.2
215
			}
226
	 */
227
	public static IObservableMap[] observeMaps(IObservableSet domain,
228
			String[] propertyNames) {
229
		IObservableMap[] result = new IObservableMap[propertyNames.length];
230
		for (int i = 0; i < propertyNames.length; i++) {
231
			result[i] = observeMap(domain, propertyNames[i]);
216
		}
232
		}
217
		throw new BindingException(
233
		return result;
218
				"Could not find property with name " + propertyName + " in class " + beanClass); //$NON-NLS-1$ //$NON-NLS-2$
219
	}
234
	}
220
235
221
	/**
236
	/**
222
	 * Returns an array of observable maps in the default realm tracking the
237
	 * Returns an array of observable maps in the given observable set's realm
223
	 * current values of the named propertys for the beans in the given set.
238
	 * tracking the current values of the named properties for the beans in the
239
	 * given set.
224
	 * 
240
	 * 
225
	 * @param domain
241
	 * @param domain
226
	 *            the set of objects
242
	 *            the set of objects
227
	 * @param beanClass
243
	 * @param beanClass
228
	 *            the common base type of objects that may be in the set
244
	 *            the common base type of objects that may be in the set
229
	 * @param propertyNames
245
	 * @param propertyNames
230
	 *            the array of property names
246
	 *            the array of property names. May be nested e.g. "parent.name"
231
	 * @return an array of observable maps tracking the current values of the
247
	 * @return an array of observable maps tracking the current values of the
232
	 *         named propertys for the beans in the given domain set
248
	 *         named propertys for the beans in the given domain set
233
	 */
249
	 */
Lines 283-291 Link Here
283
	 * collection-typed named property of the given bean object. The returned
299
	 * collection-typed named property of the given bean object. The returned
284
	 * list is mutable. When an item is added or removed the setter is invoked
300
	 * list is mutable. When an item is added or removed the setter is invoked
285
	 * for the list on the parent bean to provide notification to other
301
	 * for the list on the parent bean to provide notification to other
286
	 * listeners via <code>PropertyChangeEvents</code>. This is done to
302
	 * listeners via <code>PropertyChangeEvents</code>. This is done to provide
287
	 * provide the same behavior as is expected from arrays as specified in the
303
	 * the same behavior as is expected from arrays as specified in the bean
288
	 * bean spec in section 7.2.
304
	 * spec in section 7.2.
289
	 * 
305
	 * 
290
	 * @param realm
306
	 * @param realm
291
	 *            the realm
307
	 *            the realm
Lines 294-301 Link Here
294
	 * @param propertyName
310
	 * @param propertyName
295
	 *            the name of the property
311
	 *            the name of the property
296
	 * @param elementType
312
	 * @param elementType
297
	 *            type of the elements in the list. If <code>null</code> and
313
	 *            type of the elements in the list. If <code>null</code> and the
298
	 *            the property is an array the type will be inferred. If
314
	 *            property is an array the type will be inferred. If
299
	 *            <code>null</code> and the property type cannot be inferred
315
	 *            <code>null</code> and the property type cannot be inferred
300
	 *            element type will be <code>null</code>.
316
	 *            element type will be <code>null</code>.
301
	 * @return an observable list tracking the collection-typed named property
317
	 * @return an observable list tracking the collection-typed named property
Lines 303-314 Link Here
303
	 */
319
	 */
304
	public static IObservableList observeList(Realm realm, Object bean,
320
	public static IObservableList observeList(Realm realm, Object bean,
305
			String propertyName, Class elementType) {
321
			String propertyName, Class elementType) {
306
		PropertyDescriptor propertyDescriptor = getPropertyDescriptor(bean
322
		return BeanProperties.list(bean.getClass(), propertyName, elementType)
307
				.getClass(), propertyName);
323
				.observe(realm, bean);
308
		elementType = getCollectionElementType(elementType, propertyDescriptor);
309
310
		return new JavaBeanObservableList(realm, bean, propertyDescriptor,
311
				elementType);
312
	}
324
	}
313
325
314
	/**
326
	/**
Lines 379-394 Link Here
379
	 * @param realm
391
	 * @param realm
380
	 *            the realm to use
392
	 *            the realm to use
381
	 * @param propertyName
393
	 * @param propertyName
382
	 *            the name of the property
394
	 *            the name of the property. May be nested e.g. "parent.name"
383
	 * @return an observable value factory
395
	 * @return an observable value factory
384
	 */
396
	 */
385
	public static IObservableFactory valueFactory(final Realm realm,
397
	public static IObservableFactory valueFactory(final Realm realm,
386
			final String propertyName) {
398
			final String propertyName) {
387
		return new IObservableFactory() {
399
		return BeanProperties.value(propertyName).valueFactory(realm);
388
			public IObservable createObservable(Object target) {
389
				return observeValue(realm, target, propertyName);
390
			}
391
		};
392
	}
400
	}
393
401
394
	/**
402
	/**
Lines 396-402 Link Here
396
	 * realm, tracking the given property of a particular bean object
404
	 * realm, tracking the given property of a particular bean object
397
	 * 
405
	 * 
398
	 * @param propertyName
406
	 * @param propertyName
399
	 *            the name of the property
407
	 *            the name of the property. May be nested e.g. "parent.name"
400
	 * @return an observable value factory
408
	 * @return an observable value factory
401
	 * @since 1.2
409
	 * @since 1.2
402
	 */
410
	 */
Lines 417-427 Link Here
417
	 */
425
	 */
418
	public static IObservableFactory listFactory(final Realm realm,
426
	public static IObservableFactory listFactory(final Realm realm,
419
			final String propertyName, final Class elementType) {
427
			final String propertyName, final Class elementType) {
420
		return new IObservableFactory() {
428
		return BeanProperties.list(propertyName, elementType)
421
			public IObservable createObservable(Object target) {
429
				.listFactory(realm);
422
				return observeList(realm, target, propertyName, elementType);
423
			}
424
		};
425
	}
430
	}
426
431
427
	/**
432
	/**
Lines 451-461 Link Here
451
	 */
456
	 */
452
	public static IObservableFactory setFactory(final Realm realm,
457
	public static IObservableFactory setFactory(final Realm realm,
453
			final String propertyName) {
458
			final String propertyName) {
454
		return new IObservableFactory() {
459
		return BeanProperties.set(propertyName).setFactory(realm);
455
			public IObservable createObservable(Object target) {
456
				return observeSet(realm, target, propertyName);
457
			}
458
		};
459
	}
460
	}
460
461
461
	/**
462
	/**
Lines 479-484 Link Here
479
	 * @param realm
480
	 * @param realm
480
	 * @param master
481
	 * @param master
481
	 * @param propertyName
482
	 * @param propertyName
483
	 *            the name of the property. May be nested e.g. "parent.name"
482
	 * @param propertyType
484
	 * @param propertyType
483
	 *            can be <code>null</code>
485
	 *            can be <code>null</code>
484
	 * @return an observable value that tracks the current value of the named
486
	 * @return an observable value that tracks the current value of the named
Lines 494-504 Link Here
494
		warnIfDifferentRealms(realm, master.getRealm());
496
		warnIfDifferentRealms(realm, master.getRealm());
495
497
496
		IObservableValue value = MasterDetailObservables.detailValue(master,
498
		IObservableValue value = MasterDetailObservables.detailValue(master,
497
				valueFactory(realm, propertyName), propertyType);
499
				BeanProperties.value(propertyName, propertyType).valueFactory(
498
		BeanObservableValueDecorator decorator = new BeanObservableValueDecorator(
500
						realm), propertyType);
499
				value, getValueTypePropertyDescriptor(master, propertyName));
501
		return new BeanObservableValueDecorator(value, BeanPropertyHelper
500
502
				.getValueTypePropertyDescriptor(master, propertyName));
501
		return decorator;
502
	}
503
	}
503
504
504
	/* package */static void warnIfDifferentRealms(Realm detailRealm,
505
	/* package */static void warnIfDifferentRealms(Realm detailRealm,
Lines 521-526 Link Here
521
	 * 
522
	 * 
522
	 * @param master
523
	 * @param master
523
	 * @param propertyName
524
	 * @param propertyName
525
	 *            the name of the property. May be nested e.g. "parent.name"
524
	 * @param propertyType
526
	 * @param propertyType
525
	 *            can be <code>null</code>
527
	 *            can be <code>null</code>
526
	 * @return an observable value that tracks the current value of the named
528
	 * @return an observable value that tracks the current value of the named
Lines 531-547 Link Here
531
	 */
533
	 */
532
	public static IObservableValue observeDetailValue(IObservableValue master,
534
	public static IObservableValue observeDetailValue(IObservableValue master,
533
			String propertyName, Class propertyType) {
535
			String propertyName, Class propertyType) {
534
		return observeDetailValue(master.getRealm(), master, propertyName,
536
		Class beanClass = null;
535
				propertyType);
537
		if (master.getValueType() instanceof Class)
538
			beanClass = (Class) master.getValueType();
539
		return observeDetailValue(master, beanClass, propertyName, propertyType);
536
	}
540
	}
537
541
538
	/**
542
	/**
539
	 * Helper method for
543
	 * Helper method for
540
	 * <code>MasterDetailObservables.detailValue(master, valueFactory(realm,
544
	 * <code>MasterDetailObservables.detailValue(master, valueFactory(realm,
541
	 * propertyName), propertyType)</code>.
545
	 * propertyName), propertyType)</code>. This method returns an
542
	 * This method returns an {@link IBeanObservable} with a
546
	 * {@link IBeanObservable} with a {@link PropertyDescriptor} based on the
543
	 * {@link PropertyDescriptor} based on the given master type and property
547
	 * given master type and property name.
544
	 * name.
545
	 * 
548
	 * 
546
	 * @param realm
549
	 * @param realm
547
	 *            the realm
550
	 *            the realm
Lines 551-557 Link Here
551
	 * @param masterType
554
	 * @param masterType
552
	 *            the type of the master observable value
555
	 *            the type of the master observable value
553
	 * @param propertyName
556
	 * @param propertyName
554
	 *            the property name
557
	 *            the property name. May be nested e.g. "parent.name"
555
	 * @param propertyType
558
	 * @param propertyType
556
	 *            can be <code>null</code>
559
	 *            can be <code>null</code>
557
	 * @return an observable value that tracks the current value of the named
560
	 * @return an observable value that tracks the current value of the named
Lines 564-578 Link Here
564
	 *             instead.
567
	 *             instead.
565
	 */
568
	 */
566
	public static IObservableValue observeDetailValue(Realm realm,
569
	public static IObservableValue observeDetailValue(Realm realm,
567
			IObservableValue master, Class masterType, String propertyName, Class propertyType) {
570
			IObservableValue master, Class masterType, String propertyName,
571
			Class propertyType) {
568
		warnIfDifferentRealms(realm, master.getRealm());
572
		warnIfDifferentRealms(realm, master.getRealm());
569
		Assert.isNotNull(masterType, "masterType cannot be null"); //$NON-NLS-1$
573
		Assert.isNotNull(masterType, "masterType cannot be null"); //$NON-NLS-1$
570
		IObservableValue value = MasterDetailObservables.detailValue(master,
574
		IObservableValue value = MasterDetailObservables.detailValue(master,
571
				valueFactory(realm, propertyName), propertyType);
575
				BeanProperties.value(masterType, propertyName, propertyType)
572
		BeanObservableValueDecorator decorator = new BeanObservableValueDecorator(
576
						.valueFactory(realm), propertyType);
573
				value, getPropertyDescriptor(masterType, propertyName));
577
		return new BeanObservableValueDecorator(value, BeanPropertyHelper
574
578
				.getPropertyDescriptor(masterType, propertyName));
575
		return decorator;
576
	}
579
	}
577
580
578
	/**
581
	/**
Lines 588-594 Link Here
588
	 * @param masterType
591
	 * @param masterType
589
	 *            the type of the master observable value
592
	 *            the type of the master observable value
590
	 * @param propertyName
593
	 * @param propertyName
591
	 *            the property name
594
	 *            the property name. May be nested e.g. "parent.name"
592
	 * @param propertyType
595
	 * @param propertyType
593
	 *            can be <code>null</code>
596
	 *            can be <code>null</code>
594
	 * @return an observable value that tracks the current value of the named
597
	 * @return an observable value that tracks the current value of the named
Lines 599-606 Link Here
599
	 */
602
	 */
600
	public static IObservableValue observeDetailValue(IObservableValue master,
603
	public static IObservableValue observeDetailValue(IObservableValue master,
601
			Class masterType, String propertyName, Class propertyType) {
604
			Class masterType, String propertyName, Class propertyType) {
602
		return observeDetailValue(master.getRealm(), master, masterType,
605
		return BeanProperties.value(masterType, propertyName, propertyType)
603
				propertyName, propertyType);
606
				.observeDetail(master);
604
	}
607
	}
605
608
606
	/**
609
	/**
Lines 625-637 Link Here
625
			IObservableValue master, String propertyName, Class propertyType) {
628
			IObservableValue master, String propertyName, Class propertyType) {
626
		warnIfDifferentRealms(realm, master.getRealm());
629
		warnIfDifferentRealms(realm, master.getRealm());
627
		IObservableList observableList = MasterDetailObservables.detailList(
630
		IObservableList observableList = MasterDetailObservables.detailList(
628
				master, listFactory(realm, propertyName, propertyType),
631
				master, BeanProperties.list(propertyName, propertyType)
629
				propertyType);
632
						.listFactory(realm), propertyType);
630
		BeanObservableListDecorator decorator = new BeanObservableListDecorator(
633
		return new BeanObservableListDecorator(observableList,
631
				observableList, getValueTypePropertyDescriptor(master,
634
				BeanPropertyHelper.getValueTypePropertyDescriptor(master,
632
						propertyName));
635
						propertyName));
633
634
		return decorator;
635
	}
636
	}
636
637
637
	/**
638
	/**
Lines 650-657 Link Here
650
	 */
651
	 */
651
	public static IObservableList observeDetailList(IObservableValue master,
652
	public static IObservableList observeDetailList(IObservableValue master,
652
			String propertyName, Class propertyType) {
653
			String propertyName, Class propertyType) {
653
		return observeDetailList(master.getRealm(), master, propertyName,
654
		Class beanClass = null;
654
				propertyType);
655
		if (master.getValueType() instanceof Class)
656
			beanClass = (Class) master.getValueType();
657
		return BeanProperties.list(beanClass, propertyName, propertyType)
658
				.observeDetail(master);
655
	}
659
	}
656
660
657
	/**
661
	/**
Lines 677-689 Link Here
677
		warnIfDifferentRealms(realm, master.getRealm());
681
		warnIfDifferentRealms(realm, master.getRealm());
678
682
679
		IObservableSet observableSet = MasterDetailObservables.detailSet(
683
		IObservableSet observableSet = MasterDetailObservables.detailSet(
680
				master, setFactory(realm, propertyName, propertyType),
684
				master, BeanProperties.set(propertyName, propertyType)
681
				propertyType);
685
						.setFactory(realm), propertyType);
682
		BeanObservableSetDecorator decorator = new BeanObservableSetDecorator(
686
		return new BeanObservableSetDecorator(observableSet, BeanPropertyHelper
683
				observableSet, getValueTypePropertyDescriptor(master,
687
				.getValueTypePropertyDescriptor(master, propertyName));
684
						propertyName));
685
686
		return decorator;
687
	}
688
	}
688
689
689
	/**
690
	/**
Lines 702-709 Link Here
702
	 */
703
	 */
703
	public static IObservableSet observeDetailSet(IObservableValue master,
704
	public static IObservableSet observeDetailSet(IObservableValue master,
704
			String propertyName, Class propertyType) {
705
			String propertyName, Class propertyType) {
705
		return observeDetailSet(master.getRealm(), master, propertyName,
706
		Class beanClass = null;
706
				propertyType);
707
		if (master.getValueType() instanceof Class)
708
			beanClass = (Class) master.getValueType();
709
		return BeanProperties.set(beanClass, propertyName, propertyType)
710
				.observeDetail(master);
707
	}
711
	}
708
712
709
	/**
713
	/**
Lines 724-734 Link Here
724
			IObservableValue master, String propertyName) {
728
			IObservableValue master, String propertyName) {
725
		warnIfDifferentRealms(realm, master.getRealm());
729
		warnIfDifferentRealms(realm, master.getRealm());
726
		IObservableMap observableMap = MasterDetailObservables.detailMap(
730
		IObservableMap observableMap = MasterDetailObservables.detailMap(
727
				master, mapPropertyFactory(realm, propertyName));
731
				master, BeanProperties.map(propertyName).mapFactory(realm));
728
		BeanObservableMapDecorator decorator = new BeanObservableMapDecorator(
732
		return new BeanObservableMapDecorator(observableMap, BeanPropertyHelper
729
				observableMap, getValueTypePropertyDescriptor(master,
733
				.getValueTypePropertyDescriptor(master, propertyName));
730
						propertyName));
731
		return decorator;
732
	}
734
	}
733
735
734
	/**
736
	/**
Lines 743-749 Link Here
743
	 */
745
	 */
744
	public static IObservableMap observeDetailMap(IObservableValue master,
746
	public static IObservableMap observeDetailMap(IObservableValue master,
745
			String propertyName) {
747
			String propertyName) {
746
		return observeDetailMap(master.getRealm(), master, propertyName);
748
		Class beanClass = null;
749
		if (master.getValueType() instanceof Class)
750
			beanClass = (Class) master.getValueType();
751
		return BeanProperties.map(beanClass, propertyName)
752
				.observeDetail(master);
747
	}
753
	}
748
754
749
	/**
755
	/**
Lines 771-782 Link Here
771
	 */
777
	 */
772
	public static IObservableSet observeSet(Realm realm, Object bean,
778
	public static IObservableSet observeSet(Realm realm, Object bean,
773
			String propertyName, Class elementType) {
779
			String propertyName, Class elementType) {
774
		PropertyDescriptor propertyDescriptor = getPropertyDescriptor(bean
780
		return BeanProperties.set(bean.getClass(), propertyName, elementType)
775
				.getClass(), propertyName);
781
				.observe(realm, bean);
776
		elementType = getCollectionElementType(elementType, propertyDescriptor);
777
778
		return new JavaBeanObservableSet(realm, bean, propertyDescriptor,
779
				elementType);
780
	}
782
	}
781
783
782
	/**
784
	/**
Lines 824-834 Link Here
824
	 */
826
	 */
825
	public static IObservableFactory setFactory(final Realm realm,
827
	public static IObservableFactory setFactory(final Realm realm,
826
			final String propertyName, final Class elementType) {
828
			final String propertyName, final Class elementType) {
827
		return new IObservableFactory() {
829
		return BeanProperties.set(propertyName, elementType).setFactory(realm);
828
			public IObservable createObservable(Object target) {
829
				return observeSet(realm, target, propertyName, elementType);
830
			}
831
		};
832
	}
830
	}
833
831
834
	/**
832
	/**
Lines 861-879 Link Here
861
	 * @param beanClass
859
	 * @param beanClass
862
	 *            the common base type of bean objects that may be in the set
860
	 *            the common base type of bean objects that may be in the set
863
	 * @param propertyName
861
	 * @param propertyName
864
	 *            the name of the property
862
	 *            the name of the property. May be nested e.g. "parent.name"
865
	 * @return a factory for creating {@link IObservableMap} objects
863
	 * @return a factory for creating {@link IObservableMap} objects
866
	 *
864
	 * 
867
	 * @since 1.1
865
	 * @since 1.1
868
	 */
866
	 */
869
	public static IObservableFactory setToMapFactory(final Class beanClass, final String propertyName) {
867
	public static IObservableFactory setToMapFactory(final Class beanClass,
868
			final String propertyName) {
870
		return new IObservableFactory() {
869
		return new IObservableFactory() {
871
			public IObservable createObservable(Object target) {
870
			public IObservable createObservable(Object target) {
872
				return observeMap((IObservableSet) target, beanClass, propertyName);
871
				return observeMap((IObservableSet) target, beanClass,
872
						propertyName);
873
			}
873
			}
874
		};
874
		};
875
	}
875
	}
876
	
876
877
	/**
877
	/**
878
	 * Returns a factory for creating an observable map. The factory, when
878
	 * Returns a factory for creating an observable map. The factory, when
879
	 * provided with a bean object, will create an {@link IObservableMap} in the
879
	 * provided with a bean object, will create an {@link IObservableMap} in the
Lines 890-900 Link Here
890
	 */
890
	 */
891
	public static IObservableFactory mapPropertyFactory(final Realm realm,
891
	public static IObservableFactory mapPropertyFactory(final Realm realm,
892
			final String propertyName) {
892
			final String propertyName) {
893
		return new IObservableFactory() {
893
		return BeanProperties.map(propertyName).mapFactory(realm);
894
			public IObservable createObservable(Object target) {
895
				return observeMap(realm, target, propertyName);
896
			}
897
		};
898
	}
894
	}
899
895
900
	/**
896
	/**
Lines 911-942 Link Here
911
	public static IObservableFactory mapPropertyFactory(String propertyName) {
907
	public static IObservableFactory mapPropertyFactory(String propertyName) {
912
		return mapPropertyFactory(Realm.getDefault(), propertyName);
908
		return mapPropertyFactory(Realm.getDefault(), propertyName);
913
	}
909
	}
914
915
	/**
916
	 * @param elementType
917
	 *            can be <code>null</code>
918
	 * @param propertyDescriptor
919
	 * @return type of the items in a collection/array property
920
	 */
921
	/*package*/ static Class getCollectionElementType(Class elementType,
922
			PropertyDescriptor propertyDescriptor) {
923
		if (elementType == null) {
924
			Class propertyType = propertyDescriptor.getPropertyType();
925
			elementType = propertyType.isArray() ? propertyType
926
					.getComponentType() : Object.class;
927
		}
928
929
		return elementType;
930
	}
931
932
	/**
933
	 * @param observable
934
	 * @param propertyName
935
	 * @return property descriptor or <code>null</code>
936
	 */
937
	/* package*/ static PropertyDescriptor getValueTypePropertyDescriptor(
938
			IObservableValue observable, String propertyName) {
939
		return (observable.getValueType() != null) ? getPropertyDescriptor(
940
				(Class) observable.getValueType(), propertyName) : null;
941
	}
942
}
910
}
(-)src/org/eclipse/core/databinding/beans/PojoObservables.java (-105 / +119 lines)
Lines 7-21 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bugs 221704, 234686, 246625, 226289, 246782
10
 *     Matthew Hall - bugs 221704, 234686, 246625, 226289, 246782, 194734,
11
 *                    195222, 247997
11
 *******************************************************************************/
12
 *******************************************************************************/
12
13
13
package org.eclipse.core.databinding.beans;
14
package org.eclipse.core.databinding.beans;
14
15
15
import java.beans.PropertyChangeEvent;
16
import java.beans.PropertyChangeEvent;
16
import java.beans.PropertyDescriptor;
17
17
18
import org.eclipse.core.databinding.observable.IObservable;
19
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.Realm;
20
import org.eclipse.core.databinding.observable.list.IObservableList;
19
import org.eclipse.core.databinding.observable.list.IObservableList;
21
import org.eclipse.core.databinding.observable.map.IObservableMap;
20
import org.eclipse.core.databinding.observable.map.IObservableMap;
Lines 27-37 Link Here
27
import org.eclipse.core.internal.databinding.beans.BeanObservableMapDecorator;
26
import org.eclipse.core.internal.databinding.beans.BeanObservableMapDecorator;
28
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator;
27
import org.eclipse.core.internal.databinding.beans.BeanObservableSetDecorator;
29
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator;
28
import org.eclipse.core.internal.databinding.beans.BeanObservableValueDecorator;
30
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList;
29
import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper;
31
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableMap;
32
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet;
33
import org.eclipse.core.internal.databinding.beans.JavaBeanObservableValue;
34
import org.eclipse.core.internal.databinding.beans.JavaBeanPropertyObservableMap;
35
30
36
/**
31
/**
37
 * A factory for creating observable objects for POJOs (plain old java objects)
32
 * A factory for creating observable objects for POJOs (plain old java objects)
Lines 50-56 Link Here
50
	 * @param pojo
45
	 * @param pojo
51
	 *            the object
46
	 *            the object
52
	 * @param propertyName
47
	 * @param propertyName
53
	 *            the name of the property
48
	 *            the name of the property. May be nested e.g. "parent.name"
54
	 * @return an observable value tracking the current value of the named
49
	 * @return an observable value tracking the current value of the named
55
	 *         property of the given pojo
50
	 *         property of the given pojo
56
	 */
51
	 */
Lines 67-114 Link Here
67
	 * @param pojo
62
	 * @param pojo
68
	 *            the object
63
	 *            the object
69
	 * @param propertyName
64
	 * @param propertyName
70
	 *            the name of the property
65
	 *            the name of the property. May be nested e.g. "parent.name"
71
	 * @return an observable value tracking the current value of the named
66
	 * @return an observable value tracking the current value of the named
72
	 *         property of the given pojo
67
	 *         property of the given pojo
73
	 */
68
	 */
74
	public static IObservableValue observeValue(Realm realm, Object pojo,
69
	public static IObservableValue observeValue(Realm realm, Object pojo,
75
			String propertyName) {
70
			String propertyName) {
71
		return PojoProperties.value(pojo.getClass(), propertyName).observe(
72
				realm, pojo);
73
	}
76
74
77
		PropertyDescriptor descriptor = BeansObservables.getPropertyDescriptor(
75
	/**
78
				pojo.getClass(), propertyName);
76
	 * Returns an observable map in the given observable set's realm tracking
79
		return new JavaBeanObservableValue(realm, pojo, descriptor, false);
77
	 * the current values of the named property for the beans in the given set.
78
	 * Elements in the set which do not have the named property will have null
79
	 * values, and attempts to {@link IObservableMap#put(Object, Object) put}
80
	 * values to these elements will be ignored.
81
	 * 
82
	 * @param domain
83
	 *            the set of bean objects
84
	 * @param propertyName
85
	 *            the name of the property. May be nested e.g. "parent.name"
86
	 * @return an observable map tracking the current values of the named
87
	 *         property for the beans in the given domain set
88
	 * @since 1.2
89
	 */
90
	public static IObservableMap observeMap(IObservableSet domain,
91
			String propertyName) {
92
		return PojoProperties.value(propertyName).observeDetail(domain);
80
	}
93
	}
81
94
82
	/**
95
	/**
83
	 * Returns an observable map in the default realm tracking the current
96
	 * Returns an observable map in the given observable set's realm tracking
84
	 * values of the named property for the pojos in the given set.
97
	 * the current values of the named property for the pojos in the given set.
85
	 * 
98
	 * 
86
	 * @param domain
99
	 * @param domain
87
	 *            the set of pojo objects
100
	 *            the set of pojo objects
88
	 * @param pojoClass
101
	 * @param pojoClass
89
	 *            the common base type of pojo objects that may be in the set
102
	 *            the common base type of pojo objects that may be in the set
90
	 * @param propertyName
103
	 * @param propertyName
91
	 *            the name of the property
104
	 *            the name of the property. May be nested e.g. "parent.name"
92
	 * @return an observable map tracking the current values of the named
105
	 * @return an observable map tracking the current values of the named
93
	 *         property for the pojos in the given domain set
106
	 *         property for the pojos in the given domain set
94
	 */
107
	 */
95
	public static IObservableMap observeMap(IObservableSet domain,
108
	public static IObservableMap observeMap(IObservableSet domain,
96
			Class pojoClass, String propertyName) {
109
			Class pojoClass, String propertyName) {
97
		PropertyDescriptor descriptor = BeansObservables.getPropertyDescriptor(
110
		return PojoProperties.value(pojoClass, propertyName).observeDetail(
98
				pojoClass, propertyName);
111
				domain);
99
		return new JavaBeanObservableMap(domain, descriptor, false);
100
	}
112
	}
101
113
102
	/**
114
	/**
103
	 * Returns an array of observable maps in the default realm tracking the
115
	 * Returns an array of observable maps in the given observable set's realm
104
	 * current values of the named propertys for the pojos in the given set.
116
	 * tracking the current values of the named properties for the beans in the
117
	 * given set. Elements in the set which do not have the named property will
118
	 * have null values, and attempts to
119
	 * {@link IObservableMap#put(Object, Object) put} values to these elements
120
	 * will be ignored.
121
	 * 
122
	 * @param domain
123
	 *            the set of objects
124
	 * @param propertyNames
125
	 *            the array of property names. May be nested e.g. "parent.name"
126
	 * @return an array of observable maps tracking the current values of the
127
	 *         named propertys for the beans in the given domain set
128
	 * @since 1.2
129
	 */
130
	public static IObservableMap[] observeMaps(IObservableSet domain,
131
			String[] propertyNames) {
132
		IObservableMap[] result = new IObservableMap[propertyNames.length];
133
		for (int i = 0; i < propertyNames.length; i++) {
134
			result[i] = observeMap(domain, propertyNames[i]);
135
		}
136
		return result;
137
	}
138
139
	/**
140
	 * Returns an array of observable maps in the given observable set's realm
141
	 * tracking the current values of the named propertys for the pojos in the
142
	 * given set.
105
	 * 
143
	 * 
106
	 * @param domain
144
	 * @param domain
107
	 *            the set of objects
145
	 *            the set of objects
108
	 * @param pojoClass
146
	 * @param pojoClass
109
	 *            the common base type of objects that may be in the set
147
	 *            the common base type of objects that may be in the set
110
	 * @param propertyNames
148
	 * @param propertyNames
111
	 *            the array of property names
149
	 *            the array of property names. May be nested e.g. "parent.name"
112
	 * @return an array of observable maps tracking the current values of the
150
	 * @return an array of observable maps tracking the current values of the
113
	 *         named propertys for the pojos in the given domain set
151
	 *         named propertys for the pojos in the given domain set
114
	 */
152
	 */
Lines 161-170 Link Here
161
	 */
199
	 */
162
	public static IObservableMap observeMap(Realm realm, Object pojo,
200
	public static IObservableMap observeMap(Realm realm, Object pojo,
163
			String propertyName, Class keyType, Class valueType) {
201
			String propertyName, Class keyType, Class valueType) {
164
		PropertyDescriptor descriptor = BeansObservables.getPropertyDescriptor(
202
		return PojoProperties.map(pojo.getClass(), propertyName, keyType,
165
				pojo.getClass(), propertyName);
203
				valueType).observe(realm, pojo);
166
		return new JavaBeanPropertyObservableMap(realm, pojo, descriptor,
167
				keyType, valueType, false);
168
	}
204
	}
169
205
170
	/**
206
	/**
Lines 250-258 Link Here
250
	 * collection-typed named property of the given bean object. The returned
286
	 * collection-typed named property of the given bean object. The returned
251
	 * list is mutable. When an item is added or removed the setter is invoked
287
	 * list is mutable. When an item is added or removed the setter is invoked
252
	 * for the list on the parent bean to provide notification to other
288
	 * for the list on the parent bean to provide notification to other
253
	 * listeners via <code>PropertyChangeEvents</code>. This is done to
289
	 * listeners via <code>PropertyChangeEvents</code>. This is done to provide
254
	 * provide the same behavior as is expected from arrays as specified in the
290
	 * the same behavior as is expected from arrays as specified in the bean
255
	 * bean spec in section 7.2.
291
	 * spec in section 7.2.
256
	 * 
292
	 * 
257
	 * @param realm
293
	 * @param realm
258
	 *            the realm
294
	 *            the realm
Lines 261-268 Link Here
261
	 * @param propertyName
297
	 * @param propertyName
262
	 *            the name of the property
298
	 *            the name of the property
263
	 * @param elementType
299
	 * @param elementType
264
	 *            type of the elements in the list. If <code>null</code> and
300
	 *            type of the elements in the list. If <code>null</code> and the
265
	 *            the property is an array the type will be inferred. If
301
	 *            property is an array the type will be inferred. If
266
	 *            <code>null</code> and the property type cannot be inferred
302
	 *            <code>null</code> and the property type cannot be inferred
267
	 *            element type will be <code>null</code>.
303
	 *            element type will be <code>null</code>.
268
	 * @return an observable list tracking the collection-typed named property
304
	 * @return an observable list tracking the collection-typed named property
Lines 270-282 Link Here
270
	 */
306
	 */
271
	public static IObservableList observeList(Realm realm, Object pojo,
307
	public static IObservableList observeList(Realm realm, Object pojo,
272
			String propertyName, Class elementType) {
308
			String propertyName, Class elementType) {
273
		PropertyDescriptor propertyDescriptor = BeansObservables
309
		return PojoProperties.list(pojo.getClass(), propertyName, elementType)
274
				.getPropertyDescriptor(pojo.getClass(), propertyName);
310
				.observe(realm, pojo);
275
		elementType = BeansObservables.getCollectionElementType(elementType,
276
				propertyDescriptor);
277
278
		return new JavaBeanObservableList(realm, pojo, propertyDescriptor,
279
				elementType, false);
280
	}
311
	}
281
312
282
	/**
313
	/**
Lines 360-372 Link Here
360
	 */
391
	 */
361
	public static IObservableSet observeSet(Realm realm, Object pojo,
392
	public static IObservableSet observeSet(Realm realm, Object pojo,
362
			String propertyName, Class elementType) {
393
			String propertyName, Class elementType) {
363
		PropertyDescriptor propertyDescriptor = BeansObservables
394
		return PojoProperties.set(pojo.getClass(), propertyName, elementType)
364
				.getPropertyDescriptor(pojo.getClass(), propertyName);
395
				.observe(realm, pojo);
365
		elementType = BeansObservables.getCollectionElementType(elementType,
366
				propertyDescriptor);
367
368
		return new JavaBeanObservableSet(realm, pojo, propertyDescriptor,
369
				elementType, false);
370
	}
396
	}
371
397
372
	/**
398
	/**
Lines 398-413 Link Here
398
	 * @param realm
424
	 * @param realm
399
	 *            the realm to use
425
	 *            the realm to use
400
	 * @param propertyName
426
	 * @param propertyName
401
	 *            the name of the property
427
	 *            the name of the property. May be nested e.g. "parent.name"
402
	 * @return an observable value factory
428
	 * @return an observable value factory
403
	 */
429
	 */
404
	public static IObservableFactory valueFactory(final Realm realm,
430
	public static IObservableFactory valueFactory(final Realm realm,
405
			final String propertyName) {
431
			final String propertyName) {
406
		return new IObservableFactory() {
432
		return PojoProperties.value(propertyName).valueFactory(realm);
407
			public IObservable createObservable(Object target) {
408
				return observeValue(realm, target, propertyName);
409
			}
410
		};
411
	}
433
	}
412
434
413
	/**
435
	/**
Lines 415-421 Link Here
415
	 * realm, tracking the given property of a particular pojo object
437
	 * realm, tracking the given property of a particular pojo object
416
	 * 
438
	 * 
417
	 * @param propertyName
439
	 * @param propertyName
418
	 *            the name of the property
440
	 *            the name of the property. May be nested e.g. "parent.name"
419
	 * @return an observable value factory
441
	 * @return an observable value factory
420
	 * @since 1.2
442
	 * @since 1.2
421
	 */
443
	 */
Lines 436-446 Link Here
436
	 */
458
	 */
437
	public static IObservableFactory listFactory(final Realm realm,
459
	public static IObservableFactory listFactory(final Realm realm,
438
			final String propertyName, final Class elementType) {
460
			final String propertyName, final Class elementType) {
439
		return new IObservableFactory() {
461
		return PojoProperties.list(propertyName, elementType)
440
			public IObservable createObservable(Object target) {
462
				.listFactory(realm);
441
				return observeList(realm, target, propertyName, elementType);
442
			}
443
		};
444
	}
463
	}
445
464
446
	/**
465
	/**
Lines 470-480 Link Here
470
	 */
489
	 */
471
	public static IObservableFactory setFactory(final Realm realm,
490
	public static IObservableFactory setFactory(final Realm realm,
472
			final String propertyName) {
491
			final String propertyName) {
473
		return new IObservableFactory() {
492
		return PojoProperties.set(propertyName).setFactory(realm);
474
			public IObservable createObservable(Object target) {
475
				return observeSet(realm, target, propertyName);
476
			}
477
		};
478
	}
493
	}
479
494
480
	/**
495
	/**
Lines 507-517 Link Here
507
	 */
522
	 */
508
	public static IObservableFactory setFactory(final Realm realm,
523
	public static IObservableFactory setFactory(final Realm realm,
509
			final String propertyName, final Class elementType) {
524
			final String propertyName, final Class elementType) {
510
		return new IObservableFactory() {
525
		return PojoProperties.set(propertyName, elementType).setFactory(realm);
511
			public IObservable createObservable(Object target) {
512
				return observeSet(realm, target, propertyName, elementType);
513
			}
514
		};
515
	}
526
	}
516
527
517
	/**
528
	/**
Lines 548-558 Link Here
548
	 */
559
	 */
549
	public static IObservableFactory mapPropertyFactory(final Realm realm,
560
	public static IObservableFactory mapPropertyFactory(final Realm realm,
550
			final String propertyName) {
561
			final String propertyName) {
551
		return new IObservableFactory() {
562
		return PojoProperties.map(propertyName).mapFactory(realm);
552
			public IObservable createObservable(Object target) {
553
				return observeMap(realm, target, propertyName);
554
			}
555
		};
556
	}
563
	}
557
564
558
	/**
565
	/**
Lines 578-583 Link Here
578
	 * @param realm
585
	 * @param realm
579
	 * @param master
586
	 * @param master
580
	 * @param propertyName
587
	 * @param propertyName
588
	 *            the property name. May be nested e.g. "parent.name"
581
	 * @param propertyType
589
	 * @param propertyType
582
	 *            can be <code>null</code>
590
	 *            can be <code>null</code>
583
	 * @return an observable value that tracks the current value of the named
591
	 * @return an observable value that tracks the current value of the named
Lines 593-604 Link Here
593
		BeansObservables.warnIfDifferentRealms(realm, master.getRealm());
601
		BeansObservables.warnIfDifferentRealms(realm, master.getRealm());
594
602
595
		IObservableValue value = MasterDetailObservables.detailValue(master,
603
		IObservableValue value = MasterDetailObservables.detailValue(master,
596
				valueFactory(realm, propertyName), propertyType);
604
				PojoProperties.value(propertyName, propertyType).valueFactory(
597
		BeanObservableValueDecorator decorator = new BeanObservableValueDecorator(
605
						realm), propertyType);
598
				value, BeansObservables.getValueTypePropertyDescriptor(master,
606
		return new BeanObservableValueDecorator(value, BeanPropertyHelper
599
						propertyName));
607
				.getValueTypePropertyDescriptor(master, propertyName));
600
601
		return decorator;
602
	}
608
	}
603
609
604
	/**
610
	/**
Lines 607-612 Link Here
607
	 * 
613
	 * 
608
	 * @param master
614
	 * @param master
609
	 * @param propertyName
615
	 * @param propertyName
616
	 *            the property name. May be nested e.g. "parent.name"
610
	 * @param propertyType
617
	 * @param propertyType
611
	 *            can be <code>null</code>
618
	 *            can be <code>null</code>
612
	 * @return an observable value that tracks the current value of the named
619
	 * @return an observable value that tracks the current value of the named
Lines 617-624 Link Here
617
	 */
624
	 */
618
	public static IObservableValue observeDetailValue(IObservableValue master,
625
	public static IObservableValue observeDetailValue(IObservableValue master,
619
			String propertyName, Class propertyType) {
626
			String propertyName, Class propertyType) {
620
		return observeDetailValue(master.getRealm(), master, propertyName,
627
		Class pojoClass = null;
621
				propertyType);
628
		if (master.getValueType() instanceof Class)
629
			pojoClass = (Class) master.getValueType();
630
		return PojoProperties.value(pojoClass, propertyName, propertyType)
631
				.observeDetail(master);
622
	}
632
	}
623
633
624
	/**
634
	/**
Lines 643-655 Link Here
643
			IObservableValue master, String propertyName, Class propertyType) {
653
			IObservableValue master, String propertyName, Class propertyType) {
644
		BeansObservables.warnIfDifferentRealms(realm, master.getRealm());
654
		BeansObservables.warnIfDifferentRealms(realm, master.getRealm());
645
		IObservableList observableList = MasterDetailObservables.detailList(
655
		IObservableList observableList = MasterDetailObservables.detailList(
646
				master, listFactory(realm, propertyName, propertyType),
656
				master, PojoProperties.list(propertyName, propertyType)
647
				propertyType);
657
						.listFactory(realm), propertyType);
648
		BeanObservableListDecorator decorator = new BeanObservableListDecorator(
658
		return new BeanObservableListDecorator(observableList,
649
				observableList, BeansObservables
659
				BeanPropertyHelper.getValueTypePropertyDescriptor(master,
650
						.getValueTypePropertyDescriptor(master, propertyName));
660
						propertyName));
651
652
		return decorator;
653
	}
661
	}
654
662
655
	/**
663
	/**
Lines 668-675 Link Here
668
	 */
676
	 */
669
	public static IObservableList observeDetailList(IObservableValue master,
677
	public static IObservableList observeDetailList(IObservableValue master,
670
			String propertyName, Class propertyType) {
678
			String propertyName, Class propertyType) {
671
		return observeDetailList(master.getRealm(), master, propertyName,
679
		Class pojoClass = null;
672
				propertyType);
680
		if (master.getValueType() instanceof Class)
681
			pojoClass = (Class) master.getValueType();
682
		return PojoProperties.list(pojoClass, propertyName).observeDetail(
683
				master);
673
	}
684
	}
674
685
675
	/**
686
	/**
Lines 695-707 Link Here
695
		BeansObservables.warnIfDifferentRealms(realm, master.getRealm());
706
		BeansObservables.warnIfDifferentRealms(realm, master.getRealm());
696
707
697
		IObservableSet observableSet = MasterDetailObservables.detailSet(
708
		IObservableSet observableSet = MasterDetailObservables.detailSet(
698
				master, setFactory(realm, propertyName, propertyType),
709
				master, PojoProperties.set(propertyName, propertyType)
699
				propertyType);
710
						.setFactory(realm), propertyType);
700
		BeanObservableSetDecorator decorator = new BeanObservableSetDecorator(
711
		return new BeanObservableSetDecorator(observableSet, BeanPropertyHelper
701
				observableSet, BeansObservables.getValueTypePropertyDescriptor(
712
				.getValueTypePropertyDescriptor(master, propertyName));
702
						master, propertyName));
703
704
		return decorator;
705
	}
713
	}
706
714
707
	/**
715
	/**
Lines 720-727 Link Here
720
	 */
728
	 */
721
	public static IObservableSet observeDetailSet(IObservableValue master,
729
	public static IObservableSet observeDetailSet(IObservableValue master,
722
			String propertyName, Class propertyType) {
730
			String propertyName, Class propertyType) {
723
		return observeDetailSet(master.getRealm(), master, propertyName,
731
		Class pojoClass = null;
724
				propertyType);
732
		if (master.getValueType() instanceof Class)
733
			pojoClass = (Class) master.getValueType();
734
		return PojoProperties.set(pojoClass, propertyName, propertyType)
735
				.observeDetail(master);
725
	}
736
	}
726
737
727
	/**
738
	/**
Lines 733-749 Link Here
733
	 * @param propertyName
744
	 * @param propertyName
734
	 * @return an observable map that tracks the map-type named property for the
745
	 * @return an observable map that tracks the map-type named property for the
735
	 *         current value of the master observable value.
746
	 *         current value of the master observable value.
736
	 * @deprecated Use {@link #observeDetailMap(IObservableValue, String)} instead
747
	 * @deprecated Use {@link #observeDetailMap(IObservableValue, String)}
748
	 *             instead
737
	 */
749
	 */
738
	public static IObservableMap observeDetailMap(Realm realm,
750
	public static IObservableMap observeDetailMap(Realm realm,
739
			IObservableValue master, String propertyName) {
751
			IObservableValue master, String propertyName) {
740
		BeansObservables.warnIfDifferentRealms(realm, master.getRealm());
752
		BeansObservables.warnIfDifferentRealms(realm, master.getRealm());
741
		IObservableMap observableMap = MasterDetailObservables.detailMap(
753
		IObservableMap observableMap = MasterDetailObservables.detailMap(
742
				master, mapPropertyFactory(realm, propertyName));
754
				master, PojoProperties.map(propertyName).mapFactory(realm));
743
		BeanObservableMapDecorator decorator = new BeanObservableMapDecorator(
755
		return new BeanObservableMapDecorator(observableMap, BeanPropertyHelper
744
				observableMap, BeansObservables.getValueTypePropertyDescriptor(
756
				.getValueTypePropertyDescriptor(master, propertyName));
745
						master, propertyName));
746
		return decorator;
747
	}
757
	}
748
758
749
	/**
759
	/**
Lines 758-763 Link Here
758
	 */
768
	 */
759
	public static IObservableMap observeDetailMap(IObservableValue master,
769
	public static IObservableMap observeDetailMap(IObservableValue master,
760
			String propertyName) {
770
			String propertyName) {
761
		return observeDetailMap(master.getRealm(), master, propertyName);
771
		Class pojoClass = null;
772
		if (master.getValueType() instanceof Class)
773
			pojoClass = (Class) master.getValueType();
774
		return PojoProperties.map(pojoClass, propertyName)
775
				.observeDetail(master);
762
	}
776
	}
763
}
777
}
(-)src/org/eclipse/core/internal/databinding/beans/PojoMapPropertyDecorator.java (+93 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.beans.IBeanMapProperty;
17
import org.eclipse.core.databinding.beans.IBeanValueProperty;
18
import org.eclipse.core.databinding.beans.PojoProperties;
19
import org.eclipse.core.databinding.observable.Realm;
20
import org.eclipse.core.databinding.observable.map.IObservableMap;
21
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
22
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.core.databinding.property.map.IMapProperty;
24
import org.eclipse.core.databinding.property.map.MapProperty;
25
26
/**
27
 * @since 3.3
28
 * 
29
 */
30
public class PojoMapPropertyDecorator extends MapProperty implements
31
		IBeanMapProperty {
32
	private final IMapProperty delegate;
33
	private final PropertyDescriptor propertyDescriptor;
34
35
	/**
36
	 * @param delegate
37
	 * @param propertyDescriptor
38
	 */
39
	public PojoMapPropertyDecorator(IMapProperty delegate,
40
			PropertyDescriptor propertyDescriptor) {
41
		this.delegate = delegate;
42
		this.propertyDescriptor = propertyDescriptor;
43
	}
44
45
	public Object getKeyType() {
46
		return delegate.getKeyType();
47
	}
48
49
	public Object getValueType() {
50
		return delegate.getValueType();
51
	}
52
53
	public PropertyDescriptor getPropertyDescriptor() {
54
		return propertyDescriptor;
55
	}
56
57
	public IBeanMapProperty values(String propertyName) {
58
		return values(propertyName, null);
59
	}
60
61
	public IBeanMapProperty values(String propertyName, Class valueType) {
62
		Class beanClass = (Class) delegate.getValueType();
63
		return values(PojoProperties.value(beanClass, propertyName, valueType));
64
	}
65
66
	public IBeanMapProperty values(IBeanValueProperty property) {
67
		return new PojoMapPropertyDecorator(super.values(property), property
68
				.getPropertyDescriptor());
69
	}
70
71
	public IObservableMap observe(Object source) {
72
		return new BeanObservableMapDecorator(delegate.observe(source),
73
				propertyDescriptor);
74
	}
75
76
	public IObservableMap observe(Realm realm, Object source) {
77
		return new BeanObservableMapDecorator(delegate.observe(realm, source),
78
				propertyDescriptor);
79
	}
80
81
	public IObservableFactory mapFactory() {
82
		return delegate.mapFactory();
83
	}
84
85
	public IObservableFactory mapFactory(Realm realm) {
86
		return delegate.mapFactory(realm);
87
	}
88
89
	public IObservableMap observeDetail(IObservableValue master) {
90
		return new BeanObservableMapDecorator(delegate.observeDetail(master),
91
				propertyDescriptor);
92
	}
93
}
(-)src/org/eclipse/core/internal/databinding/beans/AnonymousBeanMapProperty.java (+70 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.BindingException;
18
import org.eclipse.core.databinding.beans.BeanProperties;
19
import org.eclipse.core.databinding.property.map.DelegatingMapProperty;
20
import org.eclipse.core.databinding.property.map.IMapProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class AnonymousBeanMapProperty extends DelegatingMapProperty {
27
	private final String propertyName;
28
29
	private Map delegates;
30
31
	/**
32
	 * @param propertyName
33
	 * @param keyType
34
	 * @param valueType
35
	 */
36
	public AnonymousBeanMapProperty(String propertyName, Class keyType,
37
			Class valueType) {
38
		super(keyType, valueType);
39
		this.propertyName = propertyName;
40
		this.delegates = new HashMap();
41
	}
42
43
	protected IMapProperty doGetDelegate(Object source) {
44
		Class beanClass = source.getClass();
45
		if (delegates.containsKey(beanClass))
46
			return (IMapProperty) delegates.get(beanClass);
47
48
		IMapProperty delegate;
49
		try {
50
			delegate = BeanProperties.map(beanClass, propertyName,
51
					(Class) getKeyType(), (Class) getValueType());
52
		} catch (BindingException noSuchProperty) {
53
			delegate = null;
54
		}
55
		delegates.put(beanClass, delegate);
56
		return delegate;
57
	}
58
59
	public String toString() {
60
		String s = "{{Generic Bean}}." + propertyName + "{:}"; //$NON-NLS-1$ //$NON-NLS-2$
61
62
		Class keyType = (Class) getKeyType();
63
		Class valueType = (Class) getValueType();
64
		if (keyType != null || valueType != null) {
65
			s += " <" + keyType + ", " + valueType + ">"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
66
		}
67
68
		return s;
69
	}
70
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanListPropertyDecorator.java (+89 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.beans.BeanProperties;
17
import org.eclipse.core.databinding.beans.IBeanListProperty;
18
import org.eclipse.core.databinding.beans.IBeanValueProperty;
19
import org.eclipse.core.databinding.observable.Realm;
20
import org.eclipse.core.databinding.observable.list.IObservableList;
21
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
22
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.core.databinding.property.list.IListProperty;
24
import org.eclipse.core.databinding.property.list.ListProperty;
25
26
/**
27
 * @since 3.3
28
 * 
29
 */
30
public class BeanListPropertyDecorator extends ListProperty implements
31
		IBeanListProperty {
32
	private final IListProperty delegate;
33
	private final PropertyDescriptor propertyDescriptor;
34
35
	/**
36
	 * @param delegate
37
	 * @param propertyDescriptor
38
	 */
39
	public BeanListPropertyDecorator(IListProperty delegate,
40
			PropertyDescriptor propertyDescriptor) {
41
		this.delegate = delegate;
42
		this.propertyDescriptor = propertyDescriptor;
43
	}
44
45
	public Object getElementType() {
46
		return delegate.getElementType();
47
	}
48
49
	public IBeanListProperty values(String propertyName) {
50
		return values(propertyName, null);
51
	}
52
53
	public IBeanListProperty values(String propertyName, Class valueType) {
54
		Class beanClass = (Class) delegate.getElementType();
55
		return values(BeanProperties.value(beanClass, propertyName, valueType));
56
	}
57
58
	public IBeanListProperty values(IBeanValueProperty property) {
59
		return new BeanListPropertyDecorator(super.values(property), property
60
				.getPropertyDescriptor());
61
	}
62
63
	public PropertyDescriptor getPropertyDescriptor() {
64
		return propertyDescriptor;
65
	}
66
67
	public IObservableList observe(Object source) {
68
		return new BeanObservableListDecorator(delegate.observe(source),
69
				propertyDescriptor);
70
	}
71
72
	public IObservableList observe(Realm realm, Object source) {
73
		return new BeanObservableListDecorator(delegate.observe(realm, source),
74
				propertyDescriptor);
75
	}
76
77
	public IObservableFactory listFactory() {
78
		return delegate.listFactory();
79
	}
80
81
	public IObservableFactory listFactory(Realm realm) {
82
		return delegate.listFactory(realm);
83
	}
84
85
	public IObservableList observeDetail(IObservableValue master) {
86
		return new BeanObservableListDecorator(delegate.observeDetail(master),
87
				propertyDescriptor);
88
	}
89
}
(-)src/org/eclipse/core/databinding/beans/PojoProperties.java (+390 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222, 247997
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.beans;
14
15
import java.beans.PropertyChangeEvent;
16
import java.beans.PropertyDescriptor;
17
import java.util.ArrayList;
18
import java.util.List;
19
20
import org.eclipse.core.databinding.property.list.IListProperty;
21
import org.eclipse.core.databinding.property.map.IMapProperty;
22
import org.eclipse.core.databinding.property.set.ISetProperty;
23
import org.eclipse.core.databinding.property.value.IValueProperty;
24
import org.eclipse.core.internal.databinding.beans.AnonymousPojoListProperty;
25
import org.eclipse.core.internal.databinding.beans.AnonymousPojoMapProperty;
26
import org.eclipse.core.internal.databinding.beans.AnonymousPojoSetProperty;
27
import org.eclipse.core.internal.databinding.beans.AnonymousPojoValueProperty;
28
import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper;
29
import org.eclipse.core.internal.databinding.beans.PojoListProperty;
30
import org.eclipse.core.internal.databinding.beans.PojoListPropertyDecorator;
31
import org.eclipse.core.internal.databinding.beans.PojoMapProperty;
32
import org.eclipse.core.internal.databinding.beans.PojoMapPropertyDecorator;
33
import org.eclipse.core.internal.databinding.beans.PojoSetProperty;
34
import org.eclipse.core.internal.databinding.beans.PojoSetPropertyDecorator;
35
import org.eclipse.core.internal.databinding.beans.PojoValueProperty;
36
import org.eclipse.core.internal.databinding.beans.PojoValuePropertyDecorator;
37
38
/**
39
 * A factory for creating properties for POJOs (plain old java objects) that
40
 * conform to idea of an object with getters and setters but does not provide
41
 * {@link PropertyChangeEvent property change events} on change. This factory is
42
 * identical to {@link BeanProperties} except for this fact.
43
 * 
44
 * @since 1.2
45
 */
46
public class PojoProperties {
47
	/**
48
	 * Returns a value property for the given property name of an arbitrary bean
49
	 * class. Objects lacking the named property are treated the same as if the
50
	 * property always contains null.
51
	 * 
52
	 * @param propertyName
53
	 *            the property name. May be nested e.g. "parent.name"
54
	 * @return a value property for the given property name of an arbitrary bean
55
	 *         class.
56
	 */
57
	public static IBeanValueProperty value(String propertyName) {
58
		return value(null, propertyName, null);
59
	}
60
61
	/**
62
	 * Returns a value property for the given property name of an arbitrary bean
63
	 * class. Objects lacking the named property are treated the same as if the
64
	 * property always contains null.
65
	 * 
66
	 * @param propertyName
67
	 *            the property name. May be nested e.g. "parent.name"
68
	 * @param valueType
69
	 *            the value type of the returned value property
70
	 * @return a value property for the given property name of an arbitrary bean
71
	 *         class.
72
	 */
73
	public static IBeanValueProperty value(String propertyName, Class valueType) {
74
		return value(null, propertyName, valueType);
75
	}
76
77
	/**
78
	 * Returns a value property for the given property name of the given bean
79
	 * class.
80
	 * 
81
	 * @param beanClass
82
	 *            the bean class
83
	 * @param propertyName
84
	 *            the property name. May be nested e.g. "parent.name"
85
	 * @return a value property for the given property name of the given bean
86
	 *         class.
87
	 */
88
	public static IBeanValueProperty value(Class beanClass, String propertyName) {
89
		return value(beanClass, propertyName, null);
90
	}
91
92
	/**
93
	 * Returns a value property for the given property name of the given bean
94
	 * class.
95
	 * 
96
	 * @param beanClass
97
	 *            the bean class
98
	 * @param propertyName
99
	 *            the property name. May be nested e.g. "parent.name"
100
	 * @param valueType
101
	 *            the value type of the returned value property
102
	 * @return a value property for the given property name of the given bean
103
	 *         class.
104
	 */
105
	public static IBeanValueProperty value(Class beanClass,
106
			String propertyName, Class valueType) {
107
		String[] propertyNames = split(propertyName);
108
		if (propertyNames.length > 1)
109
			valueType = null;
110
111
		IValueProperty property;
112
		PropertyDescriptor propertyDescriptor;
113
		if (beanClass == null) {
114
			propertyDescriptor = null;
115
			property = new PojoValuePropertyDecorator(
116
					new AnonymousPojoValueProperty(propertyName, valueType),
117
					null);
118
		} else {
119
			propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(
120
					beanClass, propertyNames[0]);
121
			property = new PojoValueProperty(propertyDescriptor, valueType);
122
		}
123
124
		IBeanValueProperty beanProperty = new PojoValuePropertyDecorator(
125
				property, propertyDescriptor);
126
		for (int i = 1; i < propertyNames.length; i++) {
127
			beanProperty = beanProperty.value(propertyNames[i]);
128
		}
129
		return beanProperty;
130
	}
131
132
	private static String[] split(String propertyName) {
133
		if (propertyName.indexOf('.') == -1)
134
			return new String[] { propertyName };
135
		List propertyNames = new ArrayList();
136
		int index;
137
		while ((index = propertyName.indexOf('.')) != -1) {
138
			propertyNames.add(propertyName.substring(0, index));
139
			propertyName = propertyName.substring(index + 1);
140
		}
141
		propertyNames.add(propertyName);
142
		return (String[]) propertyNames
143
				.toArray(new String[propertyNames.size()]);
144
	}
145
146
	/**
147
	 * Returns a value property array for the given property names of the given
148
	 * bean class.
149
	 * 
150
	 * @param beanClass
151
	 *            the bean class
152
	 * @param propertyNames
153
	 *            array of property names. May be nested e.g. "parent.name"
154
	 * @return a value property array for the given property names of the given
155
	 *         bean class.
156
	 */
157
	public static IBeanValueProperty[] values(Class beanClass,
158
			String[] propertyNames) {
159
		IBeanValueProperty[] properties = new IBeanValueProperty[propertyNames.length];
160
		for (int i = 0; i < properties.length; i++)
161
			properties[i] = value(beanClass, propertyNames[i], null);
162
		return properties;
163
	}
164
165
	/**
166
	 * Returns a set property for the given property name of an arbitrary bean
167
	 * class. Objects lacking the named property are treated the same as if the
168
	 * property always contains an empty set.
169
	 * 
170
	 * @param propertyName
171
	 *            the property name
172
	 * @return a set property for the given property name of an arbitrary bean
173
	 *         class.
174
	 */
175
	public static IBeanSetProperty set(String propertyName) {
176
		return set(null, propertyName, null);
177
	}
178
179
	/**
180
	 * Returns a set property for the given property name of an arbitrary bean
181
	 * class. Objects lacking the named property are treated the same as if the
182
	 * property always contains an empty set.
183
	 * 
184
	 * @param propertyName
185
	 *            the property name
186
	 * @param elementType
187
	 *            the element type of the returned set property
188
	 * @return a set property for the given property name of an arbitrary bean
189
	 *         class.
190
	 */
191
	public static IBeanSetProperty set(String propertyName, Class elementType) {
192
		return set(null, propertyName, elementType);
193
	}
194
195
	/**
196
	 * Returns a set property for the given property name of the given bean
197
	 * class.
198
	 * 
199
	 * @param beanClass
200
	 *            the bean class
201
	 * @param propertyName
202
	 *            the property name
203
	 * @return a set property for the given property name of the given bean
204
	 *         class.
205
	 */
206
	public static IBeanSetProperty set(Class beanClass, String propertyName) {
207
		return set(beanClass, propertyName, null);
208
	}
209
210
	/**
211
	 * Returns a set property for the given property name of the given bean
212
	 * class.
213
	 * 
214
	 * @param beanClass
215
	 *            the bean class
216
	 * @param propertyName
217
	 *            the property name
218
	 * @param elementType
219
	 *            the element type of the returned set property
220
	 * @return a set property for the given property name of the given bean
221
	 *         class.
222
	 */
223
	public static IBeanSetProperty set(Class beanClass, String propertyName,
224
			Class elementType) {
225
		PropertyDescriptor propertyDescriptor;
226
		ISetProperty property;
227
		if (beanClass == null) {
228
			propertyDescriptor = null;
229
			property = new AnonymousPojoSetProperty(propertyName, elementType);
230
		} else {
231
			propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(
232
					beanClass, propertyName);
233
			property = new PojoSetProperty(propertyDescriptor, elementType);
234
		}
235
		return new PojoSetPropertyDecorator(property, propertyDescriptor);
236
	}
237
238
	/**
239
	 * Returns a list property for the given property name of an arbitrary bean
240
	 * class. Objects lacking the named property are treated the same as if the
241
	 * property always contains an empty list.
242
	 * 
243
	 * @param propertyName
244
	 *            the property name
245
	 * @return a list property for the given property name of an arbitrary bean
246
	 *         class.
247
	 */
248
	public static IBeanListProperty list(String propertyName) {
249
		return list(null, propertyName, null);
250
	}
251
252
	/**
253
	 * Returns a list property for the given property name of an arbitrary bean
254
	 * class. Objects lacking the named property are treated the same as if the
255
	 * property always contains an empty list.
256
	 * 
257
	 * @param propertyName
258
	 *            the property name
259
	 * @param elementType
260
	 *            the element type of the returned list property
261
	 * @return a list property for the given property name of the given bean
262
	 *         class.
263
	 */
264
	public static IBeanListProperty list(String propertyName, Class elementType) {
265
		return list(null, propertyName, elementType);
266
	}
267
268
	/**
269
	 * Returns a list property for the given property name of the given bean
270
	 * class.
271
	 * 
272
	 * @param beanClass
273
	 *            the bean class
274
	 * @param propertyName
275
	 *            the property name
276
	 * @return a list property for the given property name of the given bean
277
	 *         class.
278
	 */
279
	public static IBeanListProperty list(Class beanClass, String propertyName) {
280
		return list(beanClass, propertyName, null);
281
	}
282
283
	/**
284
	 * Returns a list property for the given property name of the given bean
285
	 * class.
286
	 * 
287
	 * @param beanClass
288
	 *            the bean class
289
	 * @param propertyName
290
	 *            the property name
291
	 * @param elementType
292
	 *            the element type of the returned list property
293
	 * @return a list property for the given property name of the given bean
294
	 *         class.
295
	 */
296
	public static IBeanListProperty list(Class beanClass, String propertyName,
297
			Class elementType) {
298
		PropertyDescriptor propertyDescriptor;
299
		IListProperty property;
300
		if (beanClass == null) {
301
			propertyDescriptor = null;
302
			property = new AnonymousPojoListProperty(propertyName, elementType);
303
		} else {
304
			propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(
305
					beanClass, propertyName);
306
			property = new PojoListProperty(propertyDescriptor, elementType);
307
		}
308
		return new PojoListPropertyDecorator(property, propertyDescriptor);
309
	}
310
311
	/**
312
	 * Returns a map property for the given property name of an arbitrary bean
313
	 * class. Objects lacking the named property are treated the same as if the
314
	 * property always contains an empty map.
315
	 * 
316
	 * @param propertyName
317
	 *            the property name
318
	 * @return a map property for the given property name of an arbitrary bean
319
	 *         class.
320
	 */
321
	public static IBeanMapProperty map(String propertyName) {
322
		return map(null, propertyName, null, null);
323
	}
324
325
	/**
326
	 * Returns a map property for the given property name of an arbitrary bean
327
	 * class. Objects lacking the named property are treated the same as if the
328
	 * property always contains an empty map.
329
	 * 
330
	 * @param propertyName
331
	 *            the property name
332
	 * @param keyType
333
	 *            the key type for the returned map property
334
	 * @param valueType
335
	 *            the value type for the returned map property
336
	 * @return a map property for the given property name of an arbitrary bean
337
	 *         class.
338
	 */
339
	public static IBeanMapProperty map(String propertyName, Class keyType,
340
			Class valueType) {
341
		return map(null, propertyName, keyType, valueType);
342
	}
343
344
	/**
345
	 * Returns a map property for the given property name of the given bean
346
	 * class.
347
	 * 
348
	 * @param beanClass
349
	 *            the bean class
350
	 * @param propertyName
351
	 *            the property name
352
	 * @return a map property for the given property name of the given bean
353
	 *         class.
354
	 */
355
	public static IBeanMapProperty map(Class beanClass, String propertyName) {
356
		return map(beanClass, propertyName, null, null);
357
	}
358
359
	/**
360
	 * Returns a map property for the given property name of the given bean
361
	 * class.
362
	 * 
363
	 * @param beanClass
364
	 *            the bean class
365
	 * @param propertyName
366
	 *            the property name
367
	 * @param keyType
368
	 *            the key type of the returned map property
369
	 * @param valueType
370
	 *            the value type of the returned map property
371
	 * @return a map property for the given property name of the given bean
372
	 *         class.
373
	 */
374
	public static IBeanMapProperty map(Class beanClass, String propertyName,
375
			Class keyType, Class valueType) {
376
		PropertyDescriptor propertyDescriptor;
377
		IMapProperty property;
378
		if (beanClass == null) {
379
			propertyDescriptor = null;
380
			property = new AnonymousPojoMapProperty(propertyName, keyType,
381
					valueType);
382
		} else {
383
			propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(
384
					beanClass, propertyName);
385
			property = new PojoMapProperty(propertyDescriptor, keyType,
386
					valueType);
387
		}
388
		return new PojoMapPropertyDecorator(property, propertyDescriptor);
389
	}
390
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanSetProperty.java (+133 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyDescriptor;
17
import java.lang.reflect.Array;
18
import java.util.Arrays;
19
import java.util.Collections;
20
import java.util.HashSet;
21
import java.util.Set;
22
23
import org.eclipse.core.databinding.observable.Diffs;
24
import org.eclipse.core.databinding.observable.set.SetDiff;
25
import org.eclipse.core.databinding.property.INativePropertyListener;
26
import org.eclipse.core.databinding.property.ISimplePropertyListener;
27
import org.eclipse.core.databinding.property.SimplePropertyEvent;
28
import org.eclipse.core.databinding.property.set.SimpleSetProperty;
29
30
/**
31
 * @since 3.3
32
 * 
33
 */
34
public class BeanSetProperty extends SimpleSetProperty {
35
	private final PropertyDescriptor propertyDescriptor;
36
	private final Class elementType;
37
38
	/**
39
	 * @param propertyDescriptor
40
	 * @param elementType
41
	 */
42
	public BeanSetProperty(PropertyDescriptor propertyDescriptor,
43
			Class elementType) {
44
		this.propertyDescriptor = propertyDescriptor;
45
		this.elementType = elementType == null ? BeanPropertyHelper
46
				.getCollectionPropertyElementType(propertyDescriptor)
47
				: elementType;
48
	}
49
50
	public Object getElementType() {
51
		return elementType;
52
	}
53
54
	protected Set doGetSet(Object source) {
55
		return asSet(BeanPropertyHelper
56
				.readProperty(source, propertyDescriptor));
57
	}
58
59
	private Set asSet(Object propertyValue) {
60
		if (propertyValue == null)
61
			return Collections.EMPTY_SET;
62
		if (propertyDescriptor.getPropertyType().isArray())
63
			return new HashSet(Arrays.asList((Object[]) propertyValue));
64
		return (Set) propertyValue;
65
	}
66
67
	protected void doSetSet(Object source, Set set, SetDiff diff) {
68
		BeanPropertyHelper.writeProperty(source, propertyDescriptor,
69
				convertSetToBeanPropertyType(set));
70
	}
71
72
	private Object convertSetToBeanPropertyType(Set set) {
73
		Object propertyValue = set;
74
		if (propertyDescriptor.getPropertyType().isArray()) {
75
			Class componentType = propertyDescriptor.getPropertyType()
76
					.getComponentType();
77
			Object[] array = (Object[]) Array.newInstance(componentType, set
78
					.size());
79
			propertyValue = set.toArray(array);
80
		}
81
		return propertyValue;
82
	}
83
84
	public INativePropertyListener adaptListener(
85
			final ISimplePropertyListener listener) {
86
		return new Listener(listener);
87
	}
88
89
	private class Listener implements INativePropertyListener,
90
			PropertyChangeListener {
91
		private final ISimplePropertyListener listener;
92
93
		private Listener(ISimplePropertyListener listener) {
94
			this.listener = listener;
95
		}
96
97
		public void propertyChange(java.beans.PropertyChangeEvent evt) {
98
			SetDiff diff;
99
			Object oldValue = evt.getOldValue();
100
			Object newValue = evt.getNewValue();
101
			if (oldValue != null && newValue != null) {
102
				diff = Diffs.computeSetDiff(asSet(oldValue), asSet(newValue));
103
			} else {
104
				diff = null;
105
			}
106
			if (propertyDescriptor.getName().equals(evt.getPropertyName())) {
107
				listener.handlePropertyChange(new SimplePropertyEvent(evt
108
						.getSource(), BeanSetProperty.this, diff));
109
			}
110
		}
111
	}
112
113
	public void doAddListener(Object source, INativePropertyListener listener) {
114
		BeanPropertyListenerSupport.hookListener(source, propertyDescriptor
115
				.getName(), (PropertyChangeListener) listener);
116
	}
117
118
	public void doRemoveListener(Object source, INativePropertyListener listener) {
119
		BeanPropertyListenerSupport.unhookListener(source, propertyDescriptor
120
				.getName(), (PropertyChangeListener) listener);
121
	}
122
123
	public String toString() {
124
		Class beanClass = propertyDescriptor.getReadMethod()
125
				.getDeclaringClass();
126
		String propertyName = propertyDescriptor.getName();
127
		String s = beanClass.getName() + "." + propertyName + "{}"; //$NON-NLS-1$ //$NON-NLS-2$
128
129
		if (elementType != null)
130
			s += " <" + elementType.getName() + ">"; //$NON-NLS-1$//$NON-NLS-2$
131
		return s;
132
	}
133
}
(-)src/org/eclipse/core/internal/databinding/beans/AnonymousPojoListProperty.java (+66 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.BindingException;
18
import org.eclipse.core.databinding.beans.PojoProperties;
19
import org.eclipse.core.databinding.property.list.DelegatingListProperty;
20
import org.eclipse.core.databinding.property.list.IListProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class AnonymousPojoListProperty extends DelegatingListProperty {
27
	private final String propertyName;
28
29
	private Map delegates;
30
31
	/**
32
	 * @param propertyName
33
	 * @param elementType
34
	 */
35
	public AnonymousPojoListProperty(String propertyName, Class elementType) {
36
		super(elementType);
37
		this.propertyName = propertyName;
38
		this.delegates = new HashMap();
39
	}
40
41
	protected IListProperty doGetDelegate(Object source) {
42
		Class beanClass = source.getClass();
43
		if (delegates.containsKey(beanClass))
44
			return (IListProperty) delegates.get(beanClass);
45
46
		IListProperty delegate;
47
		try {
48
			delegate = PojoProperties.list(beanClass, propertyName,
49
					(Class) getElementType());
50
		} catch (BindingException noSuchProperty) {
51
			delegate = null;
52
		}
53
		delegates.put(beanClass, delegate);
54
		return delegate;
55
	}
56
57
	public String toString() {
58
		String s = "{{Generic POJO}}." + propertyName + "[]"; //$NON-NLS-1$ //$NON-NLS-2$
59
60
		Class elementType = (Class) getElementType();
61
		if (elementType != null)
62
			s += " <" + elementType.getName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$
63
64
		return s;
65
	}
66
}
(-)src/org/eclipse/core/internal/databinding/beans/PojoSetProperty.java (+102 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyDescriptor;
16
import java.lang.reflect.Array;
17
import java.util.Arrays;
18
import java.util.Collections;
19
import java.util.HashSet;
20
import java.util.Set;
21
22
import org.eclipse.core.databinding.observable.set.SetDiff;
23
import org.eclipse.core.databinding.property.INativePropertyListener;
24
import org.eclipse.core.databinding.property.ISimplePropertyListener;
25
import org.eclipse.core.databinding.property.set.SimpleSetProperty;
26
27
/**
28
 * @since 3.3
29
 * 
30
 */
31
public class PojoSetProperty extends SimpleSetProperty {
32
	private final PropertyDescriptor propertyDescriptor;
33
	private final Class elementType;
34
35
	/**
36
	 * @param propertyDescriptor
37
	 * @param elementType
38
	 */
39
	public PojoSetProperty(PropertyDescriptor propertyDescriptor,
40
			Class elementType) {
41
		this.propertyDescriptor = propertyDescriptor;
42
		this.elementType = elementType == null ? BeanPropertyHelper
43
				.getCollectionPropertyElementType(propertyDescriptor)
44
				: elementType;
45
	}
46
47
	public Object getElementType() {
48
		return elementType;
49
	}
50
51
	protected Set doGetSet(Object source) {
52
		return asSet(BeanPropertyHelper
53
				.readProperty(source, propertyDescriptor));
54
	}
55
56
	private Set asSet(Object propertyValue) {
57
		if (propertyValue == null)
58
			return Collections.EMPTY_SET;
59
		if (propertyDescriptor.getPropertyType().isArray())
60
			return new HashSet(Arrays.asList((Object[]) propertyValue));
61
		return (Set) propertyValue;
62
	}
63
64
	protected void doSetSet(Object source, Set set, SetDiff diff) {
65
		BeanPropertyHelper.writeProperty(source, propertyDescriptor,
66
				convertSetToBeanPropertyType(set));
67
	}
68
69
	private Object convertSetToBeanPropertyType(Set set) {
70
		Object propertyValue = set;
71
		if (propertyDescriptor.getPropertyType().isArray()) {
72
			Class componentType = propertyDescriptor.getPropertyType()
73
					.getComponentType();
74
			Object[] array = (Object[]) Array.newInstance(componentType, set
75
					.size());
76
			propertyValue = set.toArray(array);
77
		}
78
		return propertyValue;
79
	}
80
81
	public INativePropertyListener adaptListener(
82
			ISimplePropertyListener listener) {
83
		return null;
84
	}
85
86
	public void doAddListener(Object source, INativePropertyListener listener) {
87
	}
88
89
	public void doRemoveListener(Object source, INativePropertyListener listener) {
90
	}
91
92
	public String toString() {
93
		Class beanClass = propertyDescriptor.getReadMethod()
94
				.getDeclaringClass();
95
		String propertyName = propertyDescriptor.getName();
96
		String s = beanClass.getName() + "." + propertyName + "{}"; //$NON-NLS-1$ //$NON-NLS-2$
97
98
		if (elementType != null)
99
			s += " <" + elementType.getName() + ">"; //$NON-NLS-1$//$NON-NLS-2$
100
		return s;
101
	}
102
}
(-)src/org/eclipse/core/databinding/beans/IBeanProperty.java (+34 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.property.IProperty;
17
18
/**
19
 * An IProperty extension interface providing access to details of bean
20
 * properties.
21
 * 
22
 * @since 1.2
23
 * @noextend This interface is not intended to be extended by clients.
24
 * @noimplement This interface is not intended to be implemented by clients.
25
 */
26
public interface IBeanProperty extends IProperty {
27
	/**
28
	 * Returns the property descriptor of the bean property being observed. This
29
	 * method returns null in the case of anonymous properties.
30
	 * 
31
	 * @return the property descriptor of the bean property being observed
32
	 */
33
	public PropertyDescriptor getPropertyDescriptor();
34
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanValueProperty.java (+106 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyDescriptor;
17
18
import org.eclipse.core.databinding.observable.Diffs;
19
import org.eclipse.core.databinding.observable.value.ValueDiff;
20
import org.eclipse.core.databinding.property.INativePropertyListener;
21
import org.eclipse.core.databinding.property.ISimplePropertyListener;
22
import org.eclipse.core.databinding.property.SimplePropertyEvent;
23
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
24
25
/**
26
 * @since 3.3
27
 * 
28
 */
29
public class BeanValueProperty extends SimpleValueProperty {
30
	private final PropertyDescriptor propertyDescriptor;
31
	private final Class valueType;
32
33
	/**
34
	 * @param propertyDescriptor
35
	 * @param valueType
36
	 */
37
	public BeanValueProperty(PropertyDescriptor propertyDescriptor,
38
			Class valueType) {
39
		this.propertyDescriptor = propertyDescriptor;
40
		this.valueType = valueType == null ? propertyDescriptor
41
				.getPropertyType() : valueType;
42
	}
43
44
	public Object getValueType() {
45
		return valueType;
46
	}
47
48
	protected Object doGetValue(Object source) {
49
		return BeanPropertyHelper.readProperty(source, propertyDescriptor);
50
	}
51
52
	protected void doSetValue(Object source, Object value) {
53
		BeanPropertyHelper.writeProperty(source, propertyDescriptor, value);
54
	}
55
56
	public INativePropertyListener adaptListener(
57
			final ISimplePropertyListener listener) {
58
		return new Listener(listener);
59
	}
60
61
	private class Listener implements INativePropertyListener,
62
			PropertyChangeListener {
63
		private final ISimplePropertyListener listener;
64
65
		private Listener(ISimplePropertyListener listener) {
66
			this.listener = listener;
67
		}
68
69
		public void propertyChange(java.beans.PropertyChangeEvent evt) {
70
			if (propertyDescriptor.getName().equals(evt.getPropertyName())) {
71
				ValueDiff diff;
72
				Object oldValue = evt.getOldValue();
73
				Object newValue = evt.getNewValue();
74
				if (oldValue != null && newValue != null) {
75
					diff = Diffs.createValueDiff(oldValue, newValue);
76
				} else {
77
					diff = null;
78
				}
79
				listener.handlePropertyChange(new SimplePropertyEvent(evt
80
						.getSource(), BeanValueProperty.this, diff));
81
			}
82
		}
83
	}
84
85
	protected void doAddListener(Object source, INativePropertyListener listener) {
86
		BeanPropertyListenerSupport.hookListener(source, propertyDescriptor
87
				.getName(), (PropertyChangeListener) listener);
88
	}
89
90
	protected void doRemoveListener(Object source,
91
			INativePropertyListener listener) {
92
		BeanPropertyListenerSupport.unhookListener(source, propertyDescriptor
93
				.getName(), (PropertyChangeListener) listener);
94
	}
95
96
	public String toString() {
97
		Class beanClass = propertyDescriptor.getReadMethod()
98
				.getDeclaringClass();
99
		String propertyName = propertyDescriptor.getName();
100
		String s = beanClass.getName() + "." + propertyName + ""; //$NON-NLS-1$ //$NON-NLS-2$
101
102
		if (valueType != null)
103
			s += " <" + valueType.getName() + ">"; //$NON-NLS-1$//$NON-NLS-2$
104
		return s;
105
	}
106
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanMapPropertyDecorator.java (+93 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.beans.BeanProperties;
17
import org.eclipse.core.databinding.beans.IBeanMapProperty;
18
import org.eclipse.core.databinding.beans.IBeanValueProperty;
19
import org.eclipse.core.databinding.observable.Realm;
20
import org.eclipse.core.databinding.observable.map.IObservableMap;
21
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
22
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.core.databinding.property.map.IMapProperty;
24
import org.eclipse.core.databinding.property.map.MapProperty;
25
26
/**
27
 * @since 3.3
28
 * 
29
 */
30
public class BeanMapPropertyDecorator extends MapProperty implements
31
		IBeanMapProperty {
32
	private final IMapProperty delegate;
33
	private final PropertyDescriptor propertyDescriptor;
34
35
	/**
36
	 * @param delegate
37
	 * @param propertyDescriptor
38
	 */
39
	public BeanMapPropertyDecorator(IMapProperty delegate,
40
			PropertyDescriptor propertyDescriptor) {
41
		this.delegate = delegate;
42
		this.propertyDescriptor = propertyDescriptor;
43
	}
44
45
	public PropertyDescriptor getPropertyDescriptor() {
46
		return propertyDescriptor;
47
	}
48
49
	public Object getKeyType() {
50
		return delegate.getKeyType();
51
	}
52
53
	public Object getValueType() {
54
		return delegate.getValueType();
55
	}
56
57
	public IBeanMapProperty values(String propertyName) {
58
		return values(propertyName, null);
59
	}
60
61
	public IBeanMapProperty values(String propertyName, Class valueType) {
62
		Class beanClass = (Class) delegate.getValueType();
63
		return values(BeanProperties.value(beanClass, propertyName, valueType));
64
	}
65
66
	public IBeanMapProperty values(IBeanValueProperty property) {
67
		return new BeanMapPropertyDecorator(super.values(property), property
68
				.getPropertyDescriptor());
69
	}
70
71
	public IObservableMap observe(Object source) {
72
		return new BeanObservableMapDecorator(delegate.observe(source),
73
				propertyDescriptor);
74
	}
75
76
	public IObservableMap observe(Realm realm, Object source) {
77
		return new BeanObservableMapDecorator(delegate.observe(realm, source),
78
				propertyDescriptor);
79
	}
80
81
	public IObservableFactory mapFactory() {
82
		return delegate.mapFactory();
83
	}
84
85
	public IObservableFactory mapFactory(Realm realm) {
86
		return delegate.mapFactory(realm);
87
	}
88
89
	public IObservableMap observeDetail(IObservableValue master) {
90
		return new BeanObservableMapDecorator(delegate.observeDetail(master),
91
				propertyDescriptor);
92
	}
93
}
(-)src/org/eclipse/core/databinding/beans/IBeanValueProperty.java (+233 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.beans;
13
14
import org.eclipse.core.databinding.property.value.IValueProperty;
15
16
/**
17
 * An {@link IValueProperty} extension interface with convenience methods for
18
 * creating nested bean properties.
19
 * 
20
 * @since 1.2
21
 * @noextend This interface is not intended to be extended by clients.
22
 * @noimplement This interface is not intended to be implemented by clients.
23
 */
24
public interface IBeanValueProperty extends IBeanProperty, IValueProperty {
25
	/**
26
	 * Returns a master-detail combination of this property and the specified
27
	 * value property.
28
	 * 
29
	 * @param propertyName
30
	 *            the value property to observe. May be nested e.g.
31
	 *            "parent.name"
32
	 * @return a master-detail combination of this property and the specified
33
	 *         value property.
34
	 * @see #value(IBeanValueProperty)
35
	 */
36
	public IBeanValueProperty value(String propertyName);
37
38
	/**
39
	 * Returns a master-detail combination of this property and the specified
40
	 * value property.
41
	 * 
42
	 * @param propertyName
43
	 *            the value property to observe. May be nested e.g.
44
	 *            "parent.name"
45
	 * @param valueType
46
	 *            the value type of the named property
47
	 * @return a master-detail combination of this property and the specified
48
	 *         value property.
49
	 * @see #value(IBeanValueProperty)
50
	 */
51
	public IBeanValueProperty value(String propertyName, Class valueType);
52
53
	/**
54
	 * Returns a master-detail combination of this property and the specified
55
	 * value property. The returned property will observe the specified detail
56
	 * value property for the value of the master value property.
57
	 * <p>
58
	 * Example:
59
	 * 
60
	 * <pre>
61
	 * // Observes the Node-typed &quot;parent&quot; property of a Node object
62
	 * IBeanValueProperty parent = BeanProperties.value(Node.class, &quot;parent&quot;);
63
	 * // Observes the string-typed &quot;name&quot; property of a Node object
64
	 * IBeanValueProperty name = BeanProperties.value(Node.class, &quot;name&quot;);
65
	 * // Observes the name of the parent of a Node object.
66
	 * IBeanValueProperty parentName = parent.value(name);
67
	 * </pre>
68
	 * 
69
	 * @param property
70
	 *            the detail property to observe
71
	 * @return a master-detail combination of this property and the specified
72
	 *         value property.
73
	 */
74
	public IBeanValueProperty value(IBeanValueProperty property);
75
76
	/**
77
	 * Returns a master-detail combination of this property and the specified
78
	 * list property.
79
	 * 
80
	 * @param propertyName
81
	 *            the list property to observe
82
	 * @return a master-detail combination of this property and the specified
83
	 *         list property.
84
	 * @see #list(IBeanListProperty)
85
	 */
86
	public IBeanListProperty list(String propertyName);
87
88
	/**
89
	 * Returns a master-detail combination of this property and the specified
90
	 * list property.
91
	 * 
92
	 * @param propertyName
93
	 *            the list property to observe
94
	 * @param elementType
95
	 *            the element type of the named property
96
	 * @return a master-detail combination of this property and the specified
97
	 *         list property.
98
	 * @see #list(IBeanListProperty)
99
	 */
100
	public IBeanListProperty list(String propertyName, Class elementType);
101
102
	/**
103
	 * Returns a master-detail combination of this property and the specified
104
	 * list property. The returned property will observe the specified list
105
	 * property for the value of the master property.
106
	 * <p>
107
	 * Example:
108
	 * 
109
	 * <pre>
110
	 * // Observes the Node-typed &quot;parent&quot; property of a Node object.
111
	 * IBeanValueProperty parent = BeanProperties.value(Node.class, &quot;parent&quot;);
112
	 * // Observes the List-typed &quot;children&quot; property of a Node object
113
	 * // where the elements are Node objects
114
	 * IBeanListProperty children = BeanProperties.list(Node.class, &quot;children&quot;,
115
	 * 		Node.class);
116
	 * // Observes the children of the parent (siblings) of a Node object.
117
	 * IBeanListProperty siblings = parent.list(children);
118
	 * </pre>
119
	 * 
120
	 * @param property
121
	 *            the detail property to observe
122
	 * @return a master-detail combination of this property and the specified
123
	 *         list property.
124
	 */
125
	public IBeanListProperty list(IBeanListProperty property);
126
127
	/**
128
	 * Returns a master-detail combination of this property and the specified
129
	 * set property.
130
	 * 
131
	 * @param propertyName
132
	 *            the set property to observe
133
	 * @return a master-detail combination of this property and the specified
134
	 *         set property.
135
	 * @see #set(IBeanSetProperty)
136
	 */
137
	public IBeanSetProperty set(String propertyName);
138
139
	/**
140
	 * Returns a master-detail combination of this property and the specified
141
	 * set property.
142
	 * 
143
	 * @param propertyName
144
	 *            the set property to observe
145
	 * @param elementType
146
	 *            the element type of the named property
147
	 * @return a master-detail combination of this property and the specified
148
	 *         set property.
149
	 * @see #set(IBeanSetProperty)
150
	 */
151
	public IBeanSetProperty set(String propertyName, Class elementType);
152
153
	/**
154
	 * Returns a master-detail combination of this property and the specified
155
	 * set property. The returned property will observe the specified set
156
	 * property for the value of the master property.
157
	 * <p>
158
	 * Example:
159
	 * 
160
	 * <pre>
161
	 * // Observes the Node-typed &quot;parent&quot; property of a Node object.
162
	 * IBeanValueProperty parent = BeanProperties.value(Node.class, &quot;parent&quot;);
163
	 * // Observes the Set-typed &quot;children&quot; property of a Node object
164
	 * // where the elements are Node objects
165
	 * IBeanSetProperty children = BeanProperties.set(Node.class, &quot;children&quot;,
166
	 * 		Node.class);
167
	 * // Observes the children of the parent (siblings) of a Node object.
168
	 * IBeanSetProperty siblings = parent.set(children);
169
	 * </pre>
170
	 * 
171
	 * @param property
172
	 *            the detail property to observe
173
	 * @return a master-detail combination of this property and the specified
174
	 *         set property.
175
	 */
176
	public IBeanSetProperty set(IBeanSetProperty property);
177
178
	/**
179
	 * Returns a master-detail combination of this property and the specified
180
	 * map property.
181
	 * 
182
	 * @param propertyName
183
	 *            the map property to observe
184
	 * @return a master-detail combination of this property and the specified
185
	 *         map property.
186
	 * @see #map(IBeanMapProperty)
187
	 */
188
	public IBeanMapProperty map(String propertyName);
189
190
	/**
191
	 * Returns a master-detail combination of this property and the specified
192
	 * map property.
193
	 * 
194
	 * @param propertyName
195
	 *            the map property to observe
196
	 * @param keyType
197
	 *            the key type of the named property
198
	 * @param valueType
199
	 *            the value type of the named property
200
	 * @return a master-detail combination of this property and the specified
201
	 *         map property.
202
	 * @see #map(IBeanMapProperty)
203
	 */
204
	public IBeanMapProperty map(String propertyName, Class keyType,
205
			Class valueType);
206
207
	/**
208
	 * Returns a master-detail combination of this property and the specified
209
	 * map property. The returned property will observe the specified map
210
	 * property for the value of the master property.
211
	 * <p>
212
	 * Example:
213
	 * 
214
	 * <pre>
215
	 * // Observes the Contact-typed &quot;supervisor&quot; property of a
216
	 * // Contact class 
217
	 * IBeanValueProperty supervisor = BeanProperties.value(Contact.class,
218
	 * 		&quot;supervisor&quot;);
219
	 * // Observes the property &quot;phoneNumbers&quot; of a Contact object--a property mapping
220
	 * // from PhoneNumberType to PhoneNumber &quot;set-typed &quot;children&quot;,
221
	 * IBeanMapProperty phoneNumbers = BeanProperties.map(Contact.class,
222
	 * 		&quot;phoneNumbers&quot;, PhoneNumberType.class, PhoneNumber.class);
223
	 * // Observes the phone numbers of a contact's supervisor:
224
	 * IBeanMapProperty supervisorPhoneNumbers = supervisor.map(phoneNumbers);
225
	 * </pre>
226
	 * 
227
	 * @param property
228
	 *            the detail property to observe
229
	 * @return a master-detail combination of this property and the specified
230
	 *         map property.
231
	 */
232
	public IBeanMapProperty map(IBeanMapProperty property);
233
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanListProperty.java (+135 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyDescriptor;
17
import java.lang.reflect.Array;
18
import java.util.ArrayList;
19
import java.util.Arrays;
20
import java.util.List;
21
22
import org.eclipse.core.databinding.observable.Diffs;
23
import org.eclipse.core.databinding.observable.list.ListDiff;
24
import org.eclipse.core.databinding.property.INativePropertyListener;
25
import org.eclipse.core.databinding.property.ISimplePropertyListener;
26
import org.eclipse.core.databinding.property.SimplePropertyEvent;
27
import org.eclipse.core.databinding.property.list.SimpleListProperty;
28
29
/**
30
 * @since 3.3
31
 * 
32
 */
33
public class BeanListProperty extends SimpleListProperty {
34
	private final PropertyDescriptor propertyDescriptor;
35
	private final Class elementType;
36
37
	/**
38
	 * @param propertyDescriptor
39
	 * @param elementType
40
	 */
41
	public BeanListProperty(PropertyDescriptor propertyDescriptor,
42
			Class elementType) {
43
		this.propertyDescriptor = propertyDescriptor;
44
		this.elementType = elementType == null ? BeanPropertyHelper
45
				.getCollectionPropertyElementType(propertyDescriptor)
46
				: elementType;
47
	}
48
49
	public Object getElementType() {
50
		return elementType;
51
	}
52
53
	protected List doGetList(Object source) {
54
		return asList(BeanPropertyHelper.readProperty(source,
55
				propertyDescriptor));
56
	}
57
58
	private List asList(Object propertyValue) {
59
		if (propertyValue == null)
60
			return new ArrayList();
61
		if (propertyDescriptor.getPropertyType().isArray())
62
			return new ArrayList(Arrays.asList((Object[]) propertyValue));
63
		return (List) propertyValue;
64
	}
65
66
	protected void doSetList(Object source, List list, ListDiff diff) {
67
		BeanPropertyHelper.writeProperty(source, propertyDescriptor,
68
				convertListToBeanPropertyType(list));
69
	}
70
71
	private Object convertListToBeanPropertyType(List list) {
72
		Object propertyValue = list;
73
		if (propertyDescriptor.getPropertyType().isArray()) {
74
			Class componentType = propertyDescriptor.getPropertyType()
75
					.getComponentType();
76
			Object[] array = (Object[]) Array.newInstance(componentType, list
77
					.size());
78
			list.toArray(array);
79
			propertyValue = array;
80
		}
81
		return propertyValue;
82
	}
83
84
	public INativePropertyListener adaptListener(
85
			final ISimplePropertyListener listener) {
86
		return new Listener(listener);
87
	}
88
89
	private class Listener implements INativePropertyListener,
90
			PropertyChangeListener {
91
		private final ISimplePropertyListener listener;
92
93
		private Listener(ISimplePropertyListener listener) {
94
			this.listener = listener;
95
		}
96
97
		public void propertyChange(java.beans.PropertyChangeEvent evt) {
98
			if (propertyDescriptor.getName().equals(evt.getPropertyName())) {
99
				ListDiff diff;
100
				Object oldValue = evt.getOldValue();
101
				Object newValue = evt.getNewValue();
102
				if (oldValue != null && newValue != null) {
103
					diff = Diffs.computeListDiff(asList(oldValue),
104
							asList(newValue));
105
				} else {
106
					diff = null;
107
				}
108
				listener.handlePropertyChange(new SimplePropertyEvent(evt
109
						.getSource(), BeanListProperty.this, diff));
110
			}
111
		}
112
	}
113
114
	protected void doAddListener(Object source, INativePropertyListener listener) {
115
		BeanPropertyListenerSupport.hookListener(source, propertyDescriptor
116
				.getName(), (PropertyChangeListener) listener);
117
	}
118
119
	protected void doRemoveListener(Object source,
120
			INativePropertyListener listener) {
121
		BeanPropertyListenerSupport.unhookListener(source, propertyDescriptor
122
				.getName(), (PropertyChangeListener) listener);
123
	}
124
125
	public String toString() {
126
		Class beanClass = propertyDescriptor.getReadMethod()
127
				.getDeclaringClass();
128
		String propertyName = propertyDescriptor.getName();
129
		String s = beanClass.getName() + "." + propertyName + "[]"; //$NON-NLS-1$ //$NON-NLS-2$
130
131
		if (elementType != null)
132
			s += " <" + elementType.getName() + ">"; //$NON-NLS-1$//$NON-NLS-2$
133
		return s;
134
	}
135
}
(-)src/org/eclipse/core/internal/databinding/beans/AnonymousPojoValueProperty.java (+64 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.BindingException;
18
import org.eclipse.core.databinding.beans.PojoProperties;
19
import org.eclipse.core.databinding.property.value.DelegatingValueProperty;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class AnonymousPojoValueProperty extends DelegatingValueProperty {
27
	private final String propertyName;
28
29
	private Map delegates;
30
31
	/**
32
	 * @param propertyName
33
	 * @param valueType
34
	 */
35
	public AnonymousPojoValueProperty(String propertyName, Class valueType) {
36
		super(valueType);
37
		this.propertyName = propertyName;
38
		this.delegates = new HashMap();
39
	}
40
41
	protected IValueProperty doGetDelegate(Object source) {
42
		Class pojoClass = source.getClass();
43
		if (delegates.containsKey(pojoClass))
44
			return (IValueProperty) delegates.get(pojoClass);
45
46
		IValueProperty delegate;
47
		try {
48
			delegate = PojoProperties.value(pojoClass, propertyName,
49
					(Class) getValueType());
50
		} catch (BindingException noSuchProperty) {
51
			delegate = null;
52
		}
53
		delegates.put(pojoClass, delegate);
54
		return delegate;
55
	}
56
57
	public String toString() {
58
		String s = "{{Generic POJO}}." + propertyName; //$NON-NLS-1$
59
		Class valueType = (Class) getValueType();
60
		if (valueType != null)
61
			s += " <" + valueType.getName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$
62
		return s;
63
	}
64
}
(-)src/org/eclipse/core/internal/databinding/beans/PojoListPropertyDecorator.java (+89 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.beans.IBeanListProperty;
17
import org.eclipse.core.databinding.beans.IBeanValueProperty;
18
import org.eclipse.core.databinding.beans.PojoProperties;
19
import org.eclipse.core.databinding.observable.Realm;
20
import org.eclipse.core.databinding.observable.list.IObservableList;
21
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
22
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.core.databinding.property.list.IListProperty;
24
import org.eclipse.core.databinding.property.list.ListProperty;
25
26
/**
27
 * @since 3.3
28
 * 
29
 */
30
public class PojoListPropertyDecorator extends ListProperty implements
31
		IBeanListProperty {
32
	private final IListProperty delegate;
33
	private final PropertyDescriptor propertyDescriptor;
34
35
	/**
36
	 * @param delegate
37
	 * @param propertyDescriptor
38
	 */
39
	public PojoListPropertyDecorator(IListProperty delegate,
40
			PropertyDescriptor propertyDescriptor) {
41
		this.delegate = delegate;
42
		this.propertyDescriptor = propertyDescriptor;
43
	}
44
45
	public Object getElementType() {
46
		return delegate.getElementType();
47
	}
48
49
	public IBeanListProperty values(String propertyName) {
50
		return values(propertyName, null);
51
	}
52
53
	public IBeanListProperty values(String propertyName, Class valueType) {
54
		Class beanClass = (Class) delegate.getElementType();
55
		return values(PojoProperties.value(beanClass, propertyName, valueType));
56
	}
57
58
	public IBeanListProperty values(IBeanValueProperty property) {
59
		return new PojoListPropertyDecorator(super.values(property), property
60
				.getPropertyDescriptor());
61
	}
62
63
	public PropertyDescriptor getPropertyDescriptor() {
64
		return propertyDescriptor;
65
	}
66
67
	public IObservableList observe(Object source) {
68
		return new BeanObservableListDecorator(delegate.observe(source),
69
				propertyDescriptor);
70
	}
71
72
	public IObservableList observe(Realm realm, Object source) {
73
		return new BeanObservableListDecorator(delegate.observe(realm, source),
74
				propertyDescriptor);
75
	}
76
77
	public IObservableFactory listFactory() {
78
		return delegate.listFactory();
79
	}
80
81
	public IObservableFactory listFactory(Realm realm) {
82
		return delegate.listFactory(realm);
83
	}
84
85
	public IObservableList observeDetail(IObservableValue master) {
86
		return new BeanObservableListDecorator(delegate.observeDetail(master),
87
				propertyDescriptor);
88
	}
89
}
(-)src/org/eclipse/core/databinding/beans/BeanProperties.java (+386 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222, 247997
11
 ******************************************************************************/
12
13
package org.eclipse.core.databinding.beans;
14
15
import java.beans.PropertyDescriptor;
16
import java.util.ArrayList;
17
import java.util.List;
18
19
import org.eclipse.core.databinding.property.list.IListProperty;
20
import org.eclipse.core.databinding.property.map.IMapProperty;
21
import org.eclipse.core.databinding.property.set.ISetProperty;
22
import org.eclipse.core.databinding.property.value.IValueProperty;
23
import org.eclipse.core.internal.databinding.beans.AnonymousBeanListProperty;
24
import org.eclipse.core.internal.databinding.beans.AnonymousBeanMapProperty;
25
import org.eclipse.core.internal.databinding.beans.AnonymousBeanSetProperty;
26
import org.eclipse.core.internal.databinding.beans.AnonymousBeanValueProperty;
27
import org.eclipse.core.internal.databinding.beans.BeanListProperty;
28
import org.eclipse.core.internal.databinding.beans.BeanListPropertyDecorator;
29
import org.eclipse.core.internal.databinding.beans.BeanMapProperty;
30
import org.eclipse.core.internal.databinding.beans.BeanMapPropertyDecorator;
31
import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper;
32
import org.eclipse.core.internal.databinding.beans.BeanSetProperty;
33
import org.eclipse.core.internal.databinding.beans.BeanSetPropertyDecorator;
34
import org.eclipse.core.internal.databinding.beans.BeanValueProperty;
35
import org.eclipse.core.internal.databinding.beans.BeanValuePropertyDecorator;
36
37
/**
38
 * A factory for creating properties for Java objects that conform to the <a
39
 * href="http://java.sun.com/products/javabeans/docs/spec.html">JavaBean
40
 * specification</a> for bound properties.
41
 * 
42
 * @since 1.2
43
 */
44
public class BeanProperties {
45
	/**
46
	 * Returns a value property for the given property name of an arbitrary bean
47
	 * class. Objects lacking the named property are treated the same as if the
48
	 * property always contains null.
49
	 * 
50
	 * @param propertyName
51
	 *            the property name. May be nested e.g. "parent.name"
52
	 * @return a value property for the given property name of an arbitrary bean
53
	 *         class.
54
	 */
55
	public static IBeanValueProperty value(String propertyName) {
56
		return value(null, propertyName, null);
57
	}
58
59
	/**
60
	 * Returns a value property for the given property name of an arbitrary bean
61
	 * class. Objects lacking the named property are treated the same as if the
62
	 * property always contains null.
63
	 * 
64
	 * @param propertyName
65
	 *            the property name. May be nested e.g. "parent.name"
66
	 * @param valueType
67
	 *            the value type of the returned value property
68
	 * @return a value property for the given property name of an arbitrary bean
69
	 *         class.
70
	 */
71
	public static IBeanValueProperty value(String propertyName, Class valueType) {
72
		return value(null, propertyName, valueType);
73
	}
74
75
	/**
76
	 * Returns a value property for the given property name of the given bean
77
	 * class.
78
	 * 
79
	 * @param beanClass
80
	 *            the bean class
81
	 * @param propertyName
82
	 *            the property name. May be nested e.g. "parent.name"
83
	 * @return a value property for the given property name of the given bean
84
	 *         class.
85
	 */
86
	public static IBeanValueProperty value(Class beanClass, String propertyName) {
87
		return value(beanClass, propertyName, null);
88
	}
89
90
	/**
91
	 * Returns a value property for the given property name of the given bean
92
	 * class.
93
	 * 
94
	 * @param beanClass
95
	 *            the bean class
96
	 * @param propertyName
97
	 *            the property name. May be nested e.g. "parent.name"
98
	 * @param valueType
99
	 *            the value type of the returned value property
100
	 * @return a value property for the given property name of the given bean
101
	 *         class.
102
	 */
103
	public static IBeanValueProperty value(Class beanClass,
104
			String propertyName, Class valueType) {
105
		String[] propertyNames = split(propertyName);
106
		if (propertyNames.length > 1)
107
			valueType = null;
108
109
		PropertyDescriptor propertyDescriptor;
110
		IValueProperty property;
111
		if (beanClass == null) {
112
			propertyDescriptor = null;
113
			property = new AnonymousBeanValueProperty(propertyName, valueType);
114
		} else {
115
			propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(
116
					beanClass, propertyNames[0]);
117
			property = new BeanValueProperty(propertyDescriptor, valueType);
118
		}
119
120
		IBeanValueProperty beanProperty = new BeanValuePropertyDecorator(
121
				property, propertyDescriptor);
122
		for (int i = 1; i < propertyNames.length; i++) {
123
			beanProperty = beanProperty.value(propertyNames[i]);
124
		}
125
		return beanProperty;
126
	}
127
128
	private static String[] split(String propertyName) {
129
		if (propertyName.indexOf('.') == -1)
130
			return new String[] { propertyName };
131
		List propertyNames = new ArrayList();
132
		int index;
133
		while ((index = propertyName.indexOf('.')) != -1) {
134
			propertyNames.add(propertyName.substring(0, index));
135
			propertyName = propertyName.substring(index + 1);
136
		}
137
		propertyNames.add(propertyName);
138
		return (String[]) propertyNames
139
				.toArray(new String[propertyNames.size()]);
140
	}
141
142
	/**
143
	 * Returns a value property array for the given property names of the given
144
	 * bean class.
145
	 * 
146
	 * @param beanClass
147
	 *            the bean class
148
	 * @param propertyNames
149
	 *            array of property names. May be nested e.g. "parent.name"
150
	 * @return a value property array for the given property names of the given
151
	 *         bean class.
152
	 */
153
	public static IBeanValueProperty[] values(Class beanClass,
154
			String[] propertyNames) {
155
		IBeanValueProperty[] properties = new IBeanValueProperty[propertyNames.length];
156
		for (int i = 0; i < properties.length; i++)
157
			properties[i] = value(beanClass, propertyNames[i], null);
158
		return properties;
159
	}
160
161
	/**
162
	 * Returns a set property for the given property name of an arbitrary bean
163
	 * class. Objects lacking the named property are treated the same as if the
164
	 * property always contains an empty set.
165
	 * 
166
	 * @param propertyName
167
	 *            the property name
168
	 * @return a set property for the given property name of an arbitrary bean
169
	 *         class.
170
	 */
171
	public static IBeanSetProperty set(String propertyName) {
172
		return set(null, propertyName, null);
173
	}
174
175
	/**
176
	 * Returns a set property for the given property name of an arbitrary bean
177
	 * class. Objects lacking the named property are treated the same as if the
178
	 * property always contains an empty set.
179
	 * 
180
	 * @param propertyName
181
	 *            the property name
182
	 * @param elementType
183
	 *            the element type of the returned set property
184
	 * @return a set property for the given property name of an arbitrary bean
185
	 *         class.
186
	 */
187
	public static IBeanSetProperty set(String propertyName, Class elementType) {
188
		return set(null, propertyName, elementType);
189
	}
190
191
	/**
192
	 * Returns a set property for the given property name of the given bean
193
	 * class.
194
	 * 
195
	 * @param beanClass
196
	 *            the bean class
197
	 * @param propertyName
198
	 *            the property name
199
	 * @return a set property for the given property name of the given bean
200
	 *         class.
201
	 */
202
	public static IBeanSetProperty set(Class beanClass, String propertyName) {
203
		return set(beanClass, propertyName, null);
204
	}
205
206
	/**
207
	 * Returns a set property for the given property name of the given bean
208
	 * class.
209
	 * 
210
	 * @param beanClass
211
	 *            the bean class
212
	 * @param propertyName
213
	 *            the property name
214
	 * @param elementType
215
	 *            the element type of the returned set property
216
	 * @return a set property for the given property name of the given bean
217
	 *         class.
218
	 */
219
	public static IBeanSetProperty set(Class beanClass, String propertyName,
220
			Class elementType) {
221
		PropertyDescriptor propertyDescriptor;
222
		ISetProperty property;
223
		if (beanClass == null) {
224
			propertyDescriptor = null;
225
			property = new AnonymousBeanSetProperty(propertyName, elementType);
226
		} else {
227
			propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(
228
					beanClass, propertyName);
229
			property = new BeanSetProperty(propertyDescriptor, elementType);
230
		}
231
		return new BeanSetPropertyDecorator(property, propertyDescriptor);
232
	}
233
234
	/**
235
	 * Returns a list property for the given property name of an arbitrary bean
236
	 * class. Objects lacking the named property are treated the same as if the
237
	 * property always contains an empty list.
238
	 * 
239
	 * @param propertyName
240
	 *            the property name
241
	 * @return a list property for the given property name of an arbitrary bean
242
	 *         class.
243
	 */
244
	public static IBeanListProperty list(String propertyName) {
245
		return list(null, propertyName, null);
246
	}
247
248
	/**
249
	 * Returns a list property for the given property name of an arbitrary bean
250
	 * class. Objects lacking the named property are treated the same as if the
251
	 * property always contains an empty list.
252
	 * 
253
	 * @param propertyName
254
	 *            the property name
255
	 * @param elementType
256
	 *            the element type of the returned list property
257
	 * @return a list property for the given property name of the given bean
258
	 *         class.
259
	 */
260
	public static IBeanListProperty list(String propertyName, Class elementType) {
261
		return list(null, propertyName, elementType);
262
	}
263
264
	/**
265
	 * Returns a list property for the given property name of the given bean
266
	 * class.
267
	 * 
268
	 * @param beanClass
269
	 *            the bean class
270
	 * @param propertyName
271
	 *            the property name
272
	 * @return a list property for the given property name of the given bean
273
	 *         class.
274
	 */
275
	public static IBeanListProperty list(Class beanClass, String propertyName) {
276
		return list(beanClass, propertyName, null);
277
	}
278
279
	/**
280
	 * Returns a list property for the given property name of the given bean
281
	 * class.
282
	 * 
283
	 * @param beanClass
284
	 *            the bean class
285
	 * @param propertyName
286
	 *            the property name
287
	 * @param elementType
288
	 *            the element type of the returned list property
289
	 * @return a list property for the given property name of the given bean
290
	 *         class.
291
	 */
292
	public static IBeanListProperty list(Class beanClass, String propertyName,
293
			Class elementType) {
294
		PropertyDescriptor propertyDescriptor;
295
		IListProperty property;
296
		if (beanClass == null) {
297
			propertyDescriptor = null;
298
			property = new AnonymousBeanListProperty(propertyName, elementType);
299
		} else {
300
			propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(
301
					beanClass, propertyName);
302
			property = new BeanListProperty(propertyDescriptor, elementType);
303
		}
304
		return new BeanListPropertyDecorator(property, propertyDescriptor);
305
	}
306
307
	/**
308
	 * Returns a map property for the given property name of an arbitrary bean
309
	 * class. Objects lacking the named property are treated the same as if the
310
	 * property always contains an empty map.
311
	 * 
312
	 * @param propertyName
313
	 *            the property name
314
	 * @return a map property for the given property name of an arbitrary bean
315
	 *         class.
316
	 */
317
	public static IBeanMapProperty map(String propertyName) {
318
		return map(null, propertyName, null, null);
319
	}
320
321
	/**
322
	 * Returns a map property for the given property name of an arbitrary bean
323
	 * class. Objects lacking the named property are treated the same as if the
324
	 * property always contains an empty map.
325
	 * 
326
	 * @param propertyName
327
	 *            the property name
328
	 * @param keyType
329
	 *            the key type for the returned map property
330
	 * @param valueType
331
	 *            the value type for the returned map property
332
	 * @return a map property for the given property name of an arbitrary bean
333
	 *         class.
334
	 */
335
	public static IBeanMapProperty map(String propertyName, Class keyType,
336
			Class valueType) {
337
		return map(null, propertyName, keyType, valueType);
338
	}
339
340
	/**
341
	 * Returns a map property for the given property name of the given bean
342
	 * class.
343
	 * 
344
	 * @param beanClass
345
	 *            the bean class
346
	 * @param propertyName
347
	 *            the property name
348
	 * @return a map property for the given property name of the given bean
349
	 *         class.
350
	 */
351
	public static IBeanMapProperty map(Class beanClass, String propertyName) {
352
		return map(beanClass, propertyName, null, null);
353
	}
354
355
	/**
356
	 * Returns a map property for the given property name of the given bean
357
	 * class.
358
	 * 
359
	 * @param beanClass
360
	 *            the bean class
361
	 * @param propertyName
362
	 *            the property name
363
	 * @param keyType
364
	 *            the key type for the returned map property
365
	 * @param valueType
366
	 *            the value type for the returned map property
367
	 * @return a map property for the given property name of the given bean
368
	 *         class.
369
	 */
370
	public static IBeanMapProperty map(Class beanClass, String propertyName,
371
			Class keyType, Class valueType) {
372
		PropertyDescriptor propertyDescriptor;
373
		IMapProperty property;
374
		if (beanClass == null) {
375
			propertyDescriptor = null;
376
			property = new AnonymousBeanMapProperty(propertyName, keyType,
377
					valueType);
378
		} else {
379
			propertyDescriptor = BeanPropertyHelper.getPropertyDescriptor(
380
					beanClass, propertyName);
381
			property = new BeanMapProperty(propertyDescriptor, keyType,
382
					valueType);
383
		}
384
		return new BeanMapPropertyDecorator(property, propertyDescriptor);
385
	}
386
}
(-)src/org/eclipse/core/internal/databinding/beans/PojoValuePropertyDecorator.java (+152 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.beans.IBeanListProperty;
17
import org.eclipse.core.databinding.beans.IBeanMapProperty;
18
import org.eclipse.core.databinding.beans.IBeanSetProperty;
19
import org.eclipse.core.databinding.beans.IBeanValueProperty;
20
import org.eclipse.core.databinding.beans.PojoProperties;
21
import org.eclipse.core.databinding.observable.Realm;
22
import org.eclipse.core.databinding.observable.list.IObservableList;
23
import org.eclipse.core.databinding.observable.map.IObservableMap;
24
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
25
import org.eclipse.core.databinding.observable.set.IObservableSet;
26
import org.eclipse.core.databinding.observable.value.IObservableValue;
27
import org.eclipse.core.databinding.property.value.IValueProperty;
28
import org.eclipse.core.databinding.property.value.ValueProperty;
29
30
/**
31
 * @since 3.3
32
 * 
33
 */
34
public class PojoValuePropertyDecorator extends ValueProperty implements
35
		IBeanValueProperty {
36
	private final IValueProperty delegate;
37
	private final PropertyDescriptor propertyDescriptor;
38
39
	/**
40
	 * @param delegate
41
	 * @param propertyDescriptor
42
	 */
43
	public PojoValuePropertyDecorator(IValueProperty delegate,
44
			PropertyDescriptor propertyDescriptor) {
45
		this.delegate = delegate;
46
		this.propertyDescriptor = propertyDescriptor;
47
	}
48
49
	public PropertyDescriptor getPropertyDescriptor() {
50
		return propertyDescriptor;
51
	}
52
53
	public Object getValueType() {
54
		return delegate.getValueType();
55
	}
56
57
	public IBeanValueProperty value(String propertyName) {
58
		return value(propertyName, null);
59
	}
60
61
	public IBeanValueProperty value(String propertyName, Class valueType) {
62
		Class beanClass = (Class) delegate.getValueType();
63
		return value(PojoProperties.value(beanClass, propertyName, valueType));
64
	}
65
66
	public IBeanValueProperty value(IBeanValueProperty property) {
67
		return new PojoValuePropertyDecorator(super.value(property), property
68
				.getPropertyDescriptor());
69
	}
70
71
	public IBeanListProperty list(String propertyName) {
72
		return list(propertyName, null);
73
	}
74
75
	public IBeanListProperty list(String propertyName, Class elementType) {
76
		Class beanClass = (Class) delegate.getValueType();
77
		return list(PojoProperties.list(beanClass, propertyName, elementType));
78
	}
79
80
	public IBeanListProperty list(IBeanListProperty property) {
81
		return new BeanListPropertyDecorator(super.list(property), property
82
				.getPropertyDescriptor());
83
	}
84
85
	public IBeanSetProperty set(String propertyName) {
86
		return set(propertyName, null);
87
	}
88
89
	public IBeanSetProperty set(String propertyName, Class elementType) {
90
		Class beanClass = (Class) delegate.getValueType();
91
		return set(PojoProperties.set(beanClass, propertyName, elementType));
92
	}
93
94
	public IBeanSetProperty set(IBeanSetProperty property) {
95
		return new BeanSetPropertyDecorator(super.set(property), property
96
				.getPropertyDescriptor());
97
	}
98
99
	public IBeanMapProperty map(String propertyName) {
100
		return map(propertyName, null, null);
101
	}
102
103
	public IBeanMapProperty map(String propertyName, Class keyType,
104
			Class valueType) {
105
		Class beanClass = (Class) delegate.getValueType();
106
		return map(PojoProperties.map(beanClass, propertyName, keyType,
107
				valueType));
108
	}
109
110
	public IBeanMapProperty map(IBeanMapProperty property) {
111
		return new BeanMapPropertyDecorator(super.map(property), property
112
				.getPropertyDescriptor());
113
	}
114
115
	public IObservableValue observe(Object source) {
116
		return new BeanObservableValueDecorator(delegate.observe(source),
117
				propertyDescriptor);
118
	}
119
120
	public IObservableValue observe(Realm realm, Object source) {
121
		return new BeanObservableValueDecorator(
122
				delegate.observe(realm, source), propertyDescriptor);
123
	}
124
125
	public IObservableFactory valueFactory() {
126
		return delegate.valueFactory();
127
	}
128
129
	public IObservableFactory valueFactory(Realm realm) {
130
		return delegate.valueFactory(realm);
131
	}
132
133
	public IObservableValue observeDetail(IObservableValue master) {
134
		return new BeanObservableValueDecorator(delegate.observeDetail(master),
135
				propertyDescriptor);
136
	}
137
138
	public IObservableList observeDetail(IObservableList master) {
139
		return new BeanObservableListDecorator(delegate.observeDetail(master),
140
				propertyDescriptor);
141
	}
142
143
	public IObservableMap observeDetail(IObservableSet master) {
144
		return new BeanObservableMapDecorator(delegate.observeDetail(master),
145
				propertyDescriptor);
146
	}
147
148
	public IObservableMap observeDetail(IObservableMap master) {
149
		return new BeanObservableMapDecorator(delegate.observeDetail(master),
150
				propertyDescriptor);
151
	}
152
}
(-)src/org/eclipse/core/databinding/beans/IBeanMapProperty.java (+69 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.beans;
13
14
import java.util.Map;
15
16
import org.eclipse.core.databinding.property.map.IMapProperty;
17
18
/**
19
 * An {@link IMapProperty} extension interface with convenience methods for
20
 * creating nested bean properties.
21
 * 
22
 * @since 1.2
23
 * @noextend This interface is not intended to be extended by clients.
24
 * @noimplement This interface is not intended to be implemented by clients.
25
 */
26
public interface IBeanMapProperty extends IBeanProperty, IMapProperty {
27
	/**
28
	 * Returns a master-detail combination of this property and the specified
29
	 * value property.
30
	 * 
31
	 * @param propertyName
32
	 *            the value property to observe. May be nested e.g.
33
	 *            "parent.name"
34
	 * @return a master-detail combination of this property and the specified
35
	 *         value property.
36
	 * @see #values(IBeanValueProperty)
37
	 */
38
	public IBeanMapProperty values(String propertyName);
39
40
	/**
41
	 * Returns a master-detail combination of this property and the specified
42
	 * value property.
43
	 * 
44
	 * @param propertyName
45
	 *            the value property to observe. May be nested e.g.
46
	 *            "parent.name"
47
	 * @param valueType
48
	 *            the value type of the named property
49
	 * @return a master-detail combination of this property and the specified
50
	 *         value property.
51
	 * @see #values(IBeanValueProperty)
52
	 */
53
	public IBeanMapProperty values(String propertyName, Class valueType);
54
55
	/**
56
	 * Returns a master-detail combination of this property and the specified
57
	 * value property. The returned property will observe the specified value
58
	 * property for all {@link Map#values() values} observed by this map
59
	 * property, mapping from this map property's {@link Map#keySet() key set}
60
	 * to the specified value property's value for each element in the master
61
	 * property's {@link Map#values() values} collection.
62
	 * 
63
	 * @param property
64
	 *            the detail property to observe
65
	 * @return a master-detail combination of this property and the specified
66
	 *         value property.
67
	 */
68
	public IBeanMapProperty values(IBeanValueProperty property);
69
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanSetPropertyDecorator.java (+90 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.beans.BeanProperties;
17
import org.eclipse.core.databinding.beans.IBeanMapProperty;
18
import org.eclipse.core.databinding.beans.IBeanSetProperty;
19
import org.eclipse.core.databinding.beans.IBeanValueProperty;
20
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
22
import org.eclipse.core.databinding.observable.set.IObservableSet;
23
import org.eclipse.core.databinding.observable.value.IObservableValue;
24
import org.eclipse.core.databinding.property.set.ISetProperty;
25
import org.eclipse.core.databinding.property.set.SetProperty;
26
27
/**
28
 * @since 3.3
29
 * 
30
 */
31
public class BeanSetPropertyDecorator extends SetProperty implements
32
		IBeanSetProperty {
33
	private final ISetProperty delegate;
34
	private final PropertyDescriptor propertyDescriptor;
35
36
	/**
37
	 * @param delegate
38
	 * @param propertyDescriptor
39
	 */
40
	public BeanSetPropertyDecorator(ISetProperty delegate,
41
			PropertyDescriptor propertyDescriptor) {
42
		this.delegate = delegate;
43
		this.propertyDescriptor = propertyDescriptor;
44
	}
45
46
	public PropertyDescriptor getPropertyDescriptor() {
47
		return propertyDescriptor;
48
	}
49
50
	public Object getElementType() {
51
		return delegate.getElementType();
52
	}
53
54
	public IBeanMapProperty values(String propertyName) {
55
		return values(propertyName, null);
56
	}
57
58
	public IBeanMapProperty values(String propertyName, Class valueType) {
59
		Class beanClass = (Class) delegate.getElementType();
60
		return values(BeanProperties.value(beanClass, propertyName, valueType));
61
	}
62
63
	public IBeanMapProperty values(IBeanValueProperty property) {
64
		return new BeanMapPropertyDecorator(super.values(property), property
65
				.getPropertyDescriptor());
66
	}
67
68
	public IObservableSet observe(Object source) {
69
		return new BeanObservableSetDecorator(delegate.observe(source),
70
				propertyDescriptor);
71
	}
72
73
	public IObservableSet observe(Realm realm, Object source) {
74
		return new BeanObservableSetDecorator(delegate.observe(realm, source),
75
				propertyDescriptor);
76
	}
77
78
	public IObservableFactory setFactory() {
79
		return delegate.setFactory();
80
	}
81
82
	public IObservableFactory setFactory(Realm realm) {
83
		return delegate.setFactory(realm);
84
	}
85
86
	public IObservableSet observeDetail(IObservableValue master) {
87
		return new BeanObservableSetDecorator(delegate.observeDetail(master),
88
				propertyDescriptor);
89
	}
90
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanMapProperty.java (+122 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyDescriptor;
17
import java.util.HashMap;
18
import java.util.Map;
19
20
import org.eclipse.core.databinding.observable.Diffs;
21
import org.eclipse.core.databinding.observable.map.MapDiff;
22
import org.eclipse.core.databinding.property.INativePropertyListener;
23
import org.eclipse.core.databinding.property.ISimplePropertyListener;
24
import org.eclipse.core.databinding.property.SimplePropertyEvent;
25
import org.eclipse.core.databinding.property.map.SimpleMapProperty;
26
27
/**
28
 * @since 3.3
29
 * 
30
 */
31
public class BeanMapProperty extends SimpleMapProperty {
32
	private final PropertyDescriptor propertyDescriptor;
33
	private final Class keyType;
34
	private final Class valueType;
35
36
	/**
37
	 * @param propertyDescriptor
38
	 * @param keyType
39
	 * @param valueType
40
	 */
41
	public BeanMapProperty(PropertyDescriptor propertyDescriptor,
42
			Class keyType, Class valueType) {
43
		this.propertyDescriptor = propertyDescriptor;
44
		this.keyType = keyType;
45
		this.valueType = valueType;
46
	}
47
48
	public Object getKeyType() {
49
		return keyType;
50
	}
51
52
	public Object getValueType() {
53
		return valueType;
54
	}
55
56
	protected Map doGetMap(Object source) {
57
		return asMap(BeanPropertyHelper
58
				.readProperty(source, propertyDescriptor));
59
	}
60
61
	private Map asMap(Object propertyValue) {
62
		if (propertyValue == null)
63
			return new HashMap();
64
		return (Map) propertyValue;
65
	}
66
67
	protected void doSetMap(Object source, Map map, MapDiff diff) {
68
		BeanPropertyHelper.writeProperty(source, propertyDescriptor, map);
69
	}
70
71
	public INativePropertyListener adaptListener(
72
			final ISimplePropertyListener listener) {
73
		return new Listener(listener);
74
	}
75
76
	private class Listener implements INativePropertyListener,
77
			PropertyChangeListener {
78
		private final ISimplePropertyListener listener;
79
80
		private Listener(ISimplePropertyListener listener) {
81
			this.listener = listener;
82
		}
83
84
		public void propertyChange(java.beans.PropertyChangeEvent evt) {
85
			if (propertyDescriptor.getName().equals(evt.getPropertyName())) {
86
				MapDiff diff;
87
				Object oldValue = evt.getOldValue();
88
				Object newValue = evt.getNewValue();
89
				if (oldValue != null && newValue != null) {
90
					diff = Diffs.computeMapDiff(asMap(oldValue),
91
							asMap(newValue));
92
				} else {
93
					diff = null;
94
				}
95
				listener.handlePropertyChange(new SimplePropertyEvent(evt
96
						.getSource(), BeanMapProperty.this, diff));
97
			}
98
		}
99
	}
100
101
	public void doAddListener(Object source, INativePropertyListener listener) {
102
		BeanPropertyListenerSupport.hookListener(source, propertyDescriptor
103
				.getName(), (PropertyChangeListener) listener);
104
	}
105
106
	public void doRemoveListener(Object source, INativePropertyListener listener) {
107
		BeanPropertyListenerSupport.unhookListener(source, propertyDescriptor
108
				.getName(), (PropertyChangeListener) listener);
109
	}
110
111
	public String toString() {
112
		Class beanClass = propertyDescriptor.getReadMethod()
113
				.getDeclaringClass();
114
		String propertyName = propertyDescriptor.getName();
115
		String s = beanClass.getName() + "." + propertyName + "{:}"; //$NON-NLS-1$ //$NON-NLS-2$
116
117
		if (keyType != null || valueType != null) {
118
			s += " <" + keyType + ", " + valueType + ">"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
119
		}
120
		return s;
121
	}
122
}
(-)src/org/eclipse/core/internal/databinding/beans/PojoMapProperty.java (+90 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyDescriptor;
16
import java.util.HashMap;
17
import java.util.Map;
18
19
import org.eclipse.core.databinding.observable.map.MapDiff;
20
import org.eclipse.core.databinding.property.INativePropertyListener;
21
import org.eclipse.core.databinding.property.ISimplePropertyListener;
22
import org.eclipse.core.databinding.property.map.SimpleMapProperty;
23
24
/**
25
 * @since 3.3
26
 * 
27
 */
28
public class PojoMapProperty extends SimpleMapProperty {
29
	private final PropertyDescriptor propertyDescriptor;
30
	private final Class keyType;
31
	private final Class valueType;
32
33
	/**
34
	 * @param propertyDescriptor
35
	 * @param keyType
36
	 * @param valueType
37
	 */
38
	public PojoMapProperty(PropertyDescriptor propertyDescriptor,
39
			Class keyType, Class valueType) {
40
		this.propertyDescriptor = propertyDescriptor;
41
		this.keyType = keyType;
42
		this.valueType = valueType;
43
	}
44
45
	public Object getKeyType() {
46
		return keyType;
47
	}
48
49
	public Object getValueType() {
50
		return valueType;
51
	}
52
53
	protected Map doGetMap(Object source) {
54
		return asMap(BeanPropertyHelper
55
				.readProperty(source, propertyDescriptor));
56
	}
57
58
	private Map asMap(Object propertyValue) {
59
		if (propertyValue == null)
60
			return new HashMap();
61
		return (Map) propertyValue;
62
	}
63
64
	protected void doSetMap(Object source, Map map, MapDiff diff) {
65
		BeanPropertyHelper.writeProperty(source, propertyDescriptor, map);
66
	}
67
68
	public INativePropertyListener adaptListener(
69
			ISimplePropertyListener listener) {
70
		return null;
71
	}
72
73
	public void doAddListener(Object source, INativePropertyListener listener) {
74
	}
75
76
	public void doRemoveListener(Object source, INativePropertyListener listener) {
77
	}
78
79
	public String toString() {
80
		Class beanClass = propertyDescriptor.getReadMethod()
81
				.getDeclaringClass();
82
		String propertyName = propertyDescriptor.getName();
83
		String s = beanClass.getName() + "." + propertyName + "{:}"; //$NON-NLS-1$ //$NON-NLS-2$
84
85
		if (keyType != null || valueType != null) {
86
			s += " <" + keyType + ", " + valueType + ">"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
87
		}
88
		return s;
89
	}
90
}
(-)src/org/eclipse/core/databinding/beans/IBeanSetProperty.java (+79 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.beans;
13
14
import org.eclipse.core.databinding.property.set.ISetProperty;
15
16
/**
17
 * An {@link ISetProperty} extension interface with convenience methods for
18
 * creating nested bean properties.
19
 * 
20
 * @since 1.2
21
 * @noextend This interface is not intended to be extended by clients.
22
 * @noimplement This interface is not intended to be implemented by clients.
23
 */
24
public interface IBeanSetProperty extends IBeanProperty, ISetProperty {
25
	/**
26
	 * Returns a master-detail combination of this property and the specified
27
	 * value property.
28
	 * 
29
	 * @param propertyName
30
	 *            the value property to observe. May be nested e.g.
31
	 *            "parent.name"
32
	 * @return a master-detail combination of this property and the specified
33
	 *         value property.
34
	 * @see #values(IBeanValueProperty)
35
	 */
36
	public IBeanMapProperty values(String propertyName);
37
38
	/**
39
	 * Returns a master-detail combination of this property and the specified
40
	 * value property.
41
	 * 
42
	 * @param propertyName
43
	 *            the value property to observe. May be nested e.g.
44
	 *            "parent.name"
45
	 * @param valueType
46
	 *            the value type of the named property
47
	 * @return a master-detail combination of this property and the specified
48
	 *         value property.
49
	 * @see #values(IBeanValueProperty)
50
	 */
51
	public IBeanMapProperty values(String propertyName, Class valueType);
52
53
	/**
54
	 * Returns a master-detail combination of this property and the specified
55
	 * value property. The returned property will observe the specified value
56
	 * property for all elements observed by this set property, mapping from
57
	 * this set property's elements (keys) to the specified value property's
58
	 * value for each element (values).
59
	 * <p>
60
	 * Example:
61
	 * 
62
	 * <pre>
63
	 * // Observes the set-typed &quot;children&quot; property of a Person object,
64
	 * // where the elements are Person objects
65
	 * IBeanSetProperty children = BeanProperties.set(Person.class, &quot;children&quot;,
66
	 * 		Person.class);
67
	 * // Observes the string-typed &quot;name&quot; property of a Person object
68
	 * IBeanValueProperty name = BeanProperties.value(Person.class, &quot;name&quot;);
69
	 * // Observes a map of children objects to their respective names.
70
	 * IBeanMapProperty childrenNames = children.values(name);
71
	 * </pre>
72
	 * 
73
	 * @param property
74
	 *            the detail property to observe
75
	 * @return a master-detail combination of this property and the specified
76
	 *         value property.
77
	 */
78
	public IBeanMapProperty values(IBeanValueProperty property);
79
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanValuePropertyDecorator.java (+152 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.beans.BeanProperties;
17
import org.eclipse.core.databinding.beans.IBeanListProperty;
18
import org.eclipse.core.databinding.beans.IBeanMapProperty;
19
import org.eclipse.core.databinding.beans.IBeanSetProperty;
20
import org.eclipse.core.databinding.beans.IBeanValueProperty;
21
import org.eclipse.core.databinding.observable.Realm;
22
import org.eclipse.core.databinding.observable.list.IObservableList;
23
import org.eclipse.core.databinding.observable.map.IObservableMap;
24
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
25
import org.eclipse.core.databinding.observable.set.IObservableSet;
26
import org.eclipse.core.databinding.observable.value.IObservableValue;
27
import org.eclipse.core.databinding.property.value.IValueProperty;
28
import org.eclipse.core.databinding.property.value.ValueProperty;
29
30
/**
31
 * @since 3.3
32
 * 
33
 */
34
public class BeanValuePropertyDecorator extends ValueProperty implements
35
		IBeanValueProperty {
36
	private final IValueProperty delegate;
37
	private final PropertyDescriptor propertyDescriptor;
38
39
	/**
40
	 * @param delegate
41
	 * @param propertyDescriptor
42
	 */
43
	public BeanValuePropertyDecorator(IValueProperty delegate,
44
			PropertyDescriptor propertyDescriptor) {
45
		this.delegate = delegate;
46
		this.propertyDescriptor = propertyDescriptor;
47
	}
48
49
	public PropertyDescriptor getPropertyDescriptor() {
50
		return propertyDescriptor;
51
	}
52
53
	public Object getValueType() {
54
		return delegate.getValueType();
55
	}
56
57
	public IBeanValueProperty value(String propertyName) {
58
		return value(propertyName, null);
59
	}
60
61
	public IBeanValueProperty value(String propertyName, Class valueType) {
62
		Class beanClass = (Class) delegate.getValueType();
63
		return value(BeanProperties.value(beanClass, propertyName, valueType));
64
	}
65
66
	public IBeanValueProperty value(IBeanValueProperty property) {
67
		return new BeanValuePropertyDecorator(super.value(property), property
68
				.getPropertyDescriptor());
69
	}
70
71
	public IBeanListProperty list(String propertyName) {
72
		return list(propertyName, null);
73
	}
74
75
	public IBeanListProperty list(String propertyName, Class elementType) {
76
		Class beanClass = (Class) delegate.getValueType();
77
		return list(BeanProperties.list(beanClass, propertyName, elementType));
78
	}
79
80
	public IBeanListProperty list(IBeanListProperty property) {
81
		return new BeanListPropertyDecorator(super.list(property), property
82
				.getPropertyDescriptor());
83
	}
84
85
	public IBeanSetProperty set(String propertyName) {
86
		return set(propertyName, null);
87
	}
88
89
	public IBeanSetProperty set(String propertyName, Class elementType) {
90
		Class beanClass = (Class) delegate.getValueType();
91
		return set(BeanProperties.set(beanClass, propertyName, elementType));
92
	}
93
94
	public IBeanSetProperty set(IBeanSetProperty property) {
95
		return new BeanSetPropertyDecorator(super.set(property), property
96
				.getPropertyDescriptor());
97
	}
98
99
	public IBeanMapProperty map(String propertyName) {
100
		return map(propertyName, null, null);
101
	}
102
103
	public IBeanMapProperty map(String propertyName, Class keyType,
104
			Class valueType) {
105
		Class beanClass = (Class) delegate.getValueType();
106
		return map(BeanProperties.map(beanClass, propertyName, keyType,
107
				valueType));
108
	}
109
110
	public IBeanMapProperty map(IBeanMapProperty property) {
111
		return new BeanMapPropertyDecorator(super.map(property), property
112
				.getPropertyDescriptor());
113
	}
114
115
	public IObservableValue observe(Object source) {
116
		return new BeanObservableValueDecorator(delegate.observe(source),
117
				propertyDescriptor);
118
	}
119
120
	public IObservableValue observe(Realm realm, Object source) {
121
		return new BeanObservableValueDecorator(
122
				delegate.observe(realm, source), propertyDescriptor);
123
	}
124
125
	public IObservableFactory valueFactory() {
126
		return delegate.valueFactory();
127
	}
128
129
	public IObservableFactory valueFactory(Realm realm) {
130
		return delegate.valueFactory(realm);
131
	}
132
133
	public IObservableValue observeDetail(IObservableValue master) {
134
		return new BeanObservableValueDecorator(delegate.observeDetail(master),
135
				propertyDescriptor);
136
	}
137
138
	public IObservableList observeDetail(IObservableList master) {
139
		return new BeanObservableListDecorator(delegate.observeDetail(master),
140
				propertyDescriptor);
141
	}
142
143
	public IObservableMap observeDetail(IObservableSet master) {
144
		return new BeanObservableMapDecorator(delegate.observeDetail(master),
145
				propertyDescriptor);
146
	}
147
148
	public IObservableMap observeDetail(IObservableMap master) {
149
		return new BeanObservableMapDecorator(delegate.observeDetail(master),
150
				propertyDescriptor);
151
	}
152
}
(-)src/org/eclipse/core/internal/databinding/beans/AnonymousBeanValueProperty.java (+66 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.BindingException;
18
import org.eclipse.core.databinding.beans.BeanProperties;
19
import org.eclipse.core.databinding.property.value.DelegatingValueProperty;
20
import org.eclipse.core.databinding.property.value.IValueProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class AnonymousBeanValueProperty extends DelegatingValueProperty {
27
	private final String propertyName;
28
29
	private Map delegates;
30
31
	/**
32
	 * @param propertyName
33
	 * @param valueType
34
	 */
35
	public AnonymousBeanValueProperty(String propertyName, Class valueType) {
36
		super(valueType);
37
		this.propertyName = propertyName;
38
		this.delegates = new HashMap();
39
	}
40
41
	protected IValueProperty doGetDelegate(Object source) {
42
		Class beanClass = source.getClass();
43
		if (delegates.containsKey(beanClass))
44
			return (IValueProperty) delegates.get(beanClass);
45
46
		IValueProperty delegate;
47
		try {
48
			delegate = BeanProperties.value(beanClass, propertyName,
49
					(Class) getValueType());
50
		} catch (BindingException noSuchProperty) {
51
			delegate = null;
52
		}
53
		delegates.put(beanClass, delegate);
54
		return delegate;
55
	}
56
57
	public String toString() {
58
		String s = "{{Generic Bean}}." + propertyName; //$NON-NLS-1$
59
60
		Class valueType = (Class) getValueType();
61
		if (valueType != null)
62
			s += " <" + valueType.getName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$
63
64
		return s;
65
	}
66
}
(-)src/org/eclipse/core/internal/databinding/beans/PojoListProperty.java (+102 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyDescriptor;
16
import java.lang.reflect.Array;
17
import java.util.ArrayList;
18
import java.util.Arrays;
19
import java.util.List;
20
21
import org.eclipse.core.databinding.observable.list.ListDiff;
22
import org.eclipse.core.databinding.property.INativePropertyListener;
23
import org.eclipse.core.databinding.property.ISimplePropertyListener;
24
import org.eclipse.core.databinding.property.list.SimpleListProperty;
25
26
/**
27
 * @since 3.3
28
 * 
29
 */
30
public class PojoListProperty extends SimpleListProperty {
31
	private final PropertyDescriptor propertyDescriptor;
32
	private final Class elementType;
33
34
	/**
35
	 * @param propertyDescriptor
36
	 * @param elementType
37
	 */
38
	public PojoListProperty(PropertyDescriptor propertyDescriptor,
39
			Class elementType) {
40
		this.propertyDescriptor = propertyDescriptor;
41
		this.elementType = elementType == null ? BeanPropertyHelper
42
				.getCollectionPropertyElementType(propertyDescriptor)
43
				: elementType;
44
	}
45
46
	public Object getElementType() {
47
		return elementType;
48
	}
49
50
	protected List doGetList(Object source) {
51
		return asList(BeanPropertyHelper.readProperty(source,
52
				propertyDescriptor));
53
	}
54
55
	private List asList(Object propertyValue) {
56
		if (propertyValue == null)
57
			return new ArrayList();
58
		if (propertyDescriptor.getPropertyType().isArray())
59
			return new ArrayList(Arrays.asList((Object[]) propertyValue));
60
		return (List) propertyValue;
61
	}
62
63
	protected void doSetList(Object source, List list, ListDiff diff) {
64
		BeanPropertyHelper.writeProperty(source, propertyDescriptor,
65
				convertListToBeanPropertyType(list));
66
	}
67
68
	private Object convertListToBeanPropertyType(List list) {
69
		Object propertyValue = list;
70
		if (propertyDescriptor.getPropertyType().isArray()) {
71
			Class componentType = propertyDescriptor.getPropertyType()
72
					.getComponentType();
73
			Object[] array = (Object[]) Array.newInstance(componentType, list
74
					.size());
75
			list.toArray(array);
76
			propertyValue = array;
77
		}
78
		return propertyValue;
79
	}
80
81
	public INativePropertyListener adaptListener(
82
			ISimplePropertyListener listener) {
83
		return null;
84
	}
85
86
	public void doAddListener(Object source, INativePropertyListener listener) {
87
	}
88
89
	public void doRemoveListener(Object source, INativePropertyListener listener) {
90
	}
91
92
	public String toString() {
93
		Class beanClass = propertyDescriptor.getReadMethod()
94
				.getDeclaringClass();
95
		String propertyName = propertyDescriptor.getName();
96
		String s = beanClass.getName() + "." + propertyName + "[]"; //$NON-NLS-1$ //$NON-NLS-2$
97
98
		if (elementType != null)
99
			s += " <" + elementType.getName() + ">"; //$NON-NLS-1$//$NON-NLS-2$
100
		return s;
101
	}
102
}
(-)src/org/eclipse/core/internal/databinding/beans/PojoSetPropertyDecorator.java (+90 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyDescriptor;
15
16
import org.eclipse.core.databinding.beans.IBeanMapProperty;
17
import org.eclipse.core.databinding.beans.IBeanSetProperty;
18
import org.eclipse.core.databinding.beans.IBeanValueProperty;
19
import org.eclipse.core.databinding.beans.PojoProperties;
20
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
22
import org.eclipse.core.databinding.observable.set.IObservableSet;
23
import org.eclipse.core.databinding.observable.value.IObservableValue;
24
import org.eclipse.core.databinding.property.set.ISetProperty;
25
import org.eclipse.core.databinding.property.set.SetProperty;
26
27
/**
28
 * @since 3.3
29
 * 
30
 */
31
public class PojoSetPropertyDecorator extends SetProperty implements
32
		IBeanSetProperty {
33
	private final ISetProperty delegate;
34
	private final PropertyDescriptor propertyDescriptor;
35
36
	/**
37
	 * @param delegate
38
	 * @param propertyDescriptor
39
	 */
40
	public PojoSetPropertyDecorator(ISetProperty delegate,
41
			PropertyDescriptor propertyDescriptor) {
42
		this.delegate = delegate;
43
		this.propertyDescriptor = propertyDescriptor;
44
	}
45
46
	public Object getElementType() {
47
		return delegate.getElementType();
48
	}
49
50
	public PropertyDescriptor getPropertyDescriptor() {
51
		return propertyDescriptor;
52
	}
53
54
	public IBeanMapProperty values(String propertyName) {
55
		return values(propertyName, null);
56
	}
57
58
	public IBeanMapProperty values(String propertyName, Class valueType) {
59
		Class beanClass = (Class) delegate.getElementType();
60
		return values(PojoProperties.value(beanClass, propertyName, valueType));
61
	}
62
63
	public IBeanMapProperty values(IBeanValueProperty property) {
64
		return new BeanMapPropertyDecorator(super.values(property), property
65
				.getPropertyDescriptor());
66
	}
67
68
	public IObservableSet observe(Object source) {
69
		return new BeanObservableSetDecorator(delegate.observe(source),
70
				propertyDescriptor);
71
	}
72
73
	public IObservableSet observe(Realm realm, Object source) {
74
		return new BeanObservableSetDecorator(delegate.observe(realm, source),
75
				propertyDescriptor);
76
	}
77
78
	public IObservableFactory setFactory() {
79
		return delegate.setFactory();
80
	}
81
82
	public IObservableFactory setFactory(Realm realm) {
83
		return delegate.setFactory(realm);
84
	}
85
86
	public IObservableSet observeDetail(IObservableValue master) {
87
		return new BeanObservableSetDecorator(delegate.observeDetail(master),
88
				propertyDescriptor);
89
	}
90
}
(-)src/org/eclipse/core/databinding/beans/IBeanListProperty.java (+75 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 195222)
10
 ******************************************************************************/
11
12
package org.eclipse.core.databinding.beans;
13
14
import org.eclipse.core.databinding.property.list.IListProperty;
15
16
/**
17
 * An {@link IListProperty} extension interface with convenience methods for
18
 * creating nested bean properties.
19
 * 
20
 * @since 1.2
21
 */
22
public interface IBeanListProperty extends IBeanProperty, IListProperty {
23
	/**
24
	 * Returns a master-detail combination of this property and the specified
25
	 * value property.
26
	 * 
27
	 * @param propertyName
28
	 *            the value property to observe. May be nested e.g.
29
	 *            "parent.name"
30
	 * @return a nested combination of this property and the specified value
31
	 *         property.
32
	 * @see #values(IBeanValueProperty)
33
	 */
34
	public IBeanListProperty values(String propertyName);
35
36
	/**
37
	 * Returns a master-detail combination of this property and the specified
38
	 * value property.
39
	 * 
40
	 * @param propertyName
41
	 *            the value property to observe. May be nested e.g.
42
	 *            "parent.name"
43
	 * @param valueType
44
	 *            the value type of the named property
45
	 * @return a master-detail combination of this property and the specified
46
	 *         value property.
47
	 * @see #values(IBeanValueProperty)
48
	 */
49
	public IBeanListProperty values(String propertyName, Class valueType);
50
51
	/**
52
	 * Returns a master-detail combination of this property and the specified
53
	 * value property. The returned property will observe the specified value
54
	 * property for all elements observed by this list property.
55
	 * <p>
56
	 * Example:
57
	 * 
58
	 * <pre>
59
	 * // Observes the list-typed &quot;children&quot; property of a Person object,
60
	 * // where the elements are Person objects
61
	 * IBeanListProperty children = BeanProperties.list(Person.class, &quot;children&quot;,
62
	 * 		Person.class);
63
	 * // Observes the string-typed &quot;name&quot; property of a Person object
64
	 * IBeanValueProperty name = BeanProperties.value(Person.class, &quot;name&quot;);
65
	 * // Observes the names of children of a Person object.
66
	 * IBeanListProperty childrenNames = children.values(name);
67
	 * </pre>
68
	 * 
69
	 * @param property
70
	 *            the detail property to observe
71
	 * @return a master-detail combination of this property and the specified
72
	 *         value property.
73
	 */
74
	public IBeanListProperty values(IBeanValueProperty property);
75
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanPropertyHelper.java (+169 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.BeanInfo;
15
import java.beans.IntrospectionException;
16
import java.beans.Introspector;
17
import java.beans.PropertyDescriptor;
18
import java.lang.reflect.InvocationTargetException;
19
import java.lang.reflect.Method;
20
21
import org.eclipse.core.databinding.BindingException;
22
import org.eclipse.core.databinding.beans.BeansObservables;
23
import org.eclipse.core.databinding.observable.value.IObservableValue;
24
import org.eclipse.core.databinding.util.Policy;
25
import org.eclipse.core.runtime.IStatus;
26
import org.eclipse.core.runtime.Status;
27
28
/**
29
 * @since 1.2
30
 * 
31
 */
32
public class BeanPropertyHelper {
33
	/**
34
	 * Sets the contents of the given property on the given source object to the
35
	 * given value.
36
	 * 
37
	 * @param source
38
	 *            the source object which has the property being updated
39
	 * @param propertyDescriptor
40
	 *            the property being changed
41
	 * @param value
42
	 *            the new value of the property
43
	 */
44
	public static void writeProperty(Object source,
45
			PropertyDescriptor propertyDescriptor, Object value) {
46
		try {
47
			Method writeMethod = propertyDescriptor.getWriteMethod();
48
			if (!writeMethod.isAccessible()) {
49
				writeMethod.setAccessible(true);
50
			}
51
			writeMethod.invoke(source, new Object[] { value });
52
		} catch (InvocationTargetException e) {
53
			/*
54
			 * InvocationTargetException wraps any exception thrown by the
55
			 * invoked method.
56
			 */
57
			throw new RuntimeException(e.getCause());
58
		} catch (Exception e) {
59
			if (BeansObservables.DEBUG) {
60
				Policy
61
						.getLog()
62
						.log(
63
								new Status(
64
										IStatus.WARNING,
65
										Policy.JFACE_DATABINDING,
66
										IStatus.OK,
67
										"Could not change value of " + source + "." + propertyDescriptor.getName(), e)); //$NON-NLS-1$ //$NON-NLS-2$
68
			}
69
		}
70
	}
71
72
	/**
73
	 * Returns the contents of the given property for the given bean.
74
	 * 
75
	 * @param source
76
	 *            the source bean
77
	 * @param propertyDescriptor
78
	 *            the property to retrieve
79
	 * @return the contents of the given property for the given bean.
80
	 */
81
	public static Object readProperty(Object source,
82
			PropertyDescriptor propertyDescriptor) {
83
		try {
84
			Method readMethod = propertyDescriptor.getReadMethod();
85
			if (readMethod == null) {
86
				throw new BindingException(propertyDescriptor.getName()
87
						+ " property does not have a read method."); //$NON-NLS-1$
88
			}
89
			if (!readMethod.isAccessible()) {
90
				readMethod.setAccessible(true);
91
			}
92
			return readMethod.invoke(source, null);
93
		} catch (InvocationTargetException e) {
94
			/*
95
			 * InvocationTargetException wraps any exception thrown by the
96
			 * invoked method.
97
			 */
98
			throw new RuntimeException(e.getCause());
99
		} catch (Exception e) {
100
			if (BeansObservables.DEBUG) {
101
				Policy
102
						.getLog()
103
						.log(
104
								new Status(
105
										IStatus.WARNING,
106
										Policy.JFACE_DATABINDING,
107
										IStatus.OK,
108
										"Could not read value of " + source + "." + propertyDescriptor.getName(), e)); //$NON-NLS-1$ //$NON-NLS-2$
109
			}
110
			return null;
111
		}
112
	}
113
114
	/**
115
	 * Returns the element type of the given collection-typed property for the
116
	 * given bean.
117
	 * 
118
	 * @param descriptor
119
	 *            the property being inspected
120
	 * @return the element type of the given collection-typed property if it is
121
	 *         an array property, or Object.class otherwise.
122
	 */
123
	public static Class getCollectionPropertyElementType(
124
			PropertyDescriptor descriptor) {
125
		Class propertyType = descriptor.getPropertyType();
126
		return propertyType.isArray() ? propertyType.getComponentType()
127
				: Object.class;
128
	}
129
130
	/**
131
	 * @param beanClass
132
	 * @param propertyName
133
	 * @return the PropertyDescriptor for the named property on the given bean
134
	 *         class
135
	 */
136
	public static PropertyDescriptor getPropertyDescriptor(Class beanClass,
137
			String propertyName) {
138
		BeanInfo beanInfo;
139
		try {
140
			beanInfo = Introspector.getBeanInfo(beanClass);
141
		} catch (IntrospectionException e) {
142
			// cannot introspect, give up
143
			return null;
144
		}
145
		PropertyDescriptor[] propertyDescriptors = beanInfo
146
				.getPropertyDescriptors();
147
		for (int i = 0; i < propertyDescriptors.length; i++) {
148
			PropertyDescriptor descriptor = propertyDescriptors[i];
149
			if (descriptor.getName().equals(propertyName)) {
150
				return descriptor;
151
			}
152
		}
153
		throw new BindingException(
154
				"Could not find property with name " + propertyName + " in class " + beanClass); //$NON-NLS-1$ //$NON-NLS-2$
155
	}
156
157
	/**
158
	 * @param observable
159
	 * @param propertyName
160
	 * @return property descriptor or <code>null</code>
161
	 */
162
	/* package */public static PropertyDescriptor getValueTypePropertyDescriptor(
163
			IObservableValue observable, String propertyName) {
164
		if (observable.getValueType() != null)
165
			return getPropertyDescriptor((Class) observable.getValueType(),
166
					propertyName);
167
		return null;
168
	}
169
}
(-)src/org/eclipse/core/internal/databinding/beans/PojoValueProperty.java (+76 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 194734)
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.core.internal.databinding.beans;
14
15
import java.beans.PropertyDescriptor;
16
17
import org.eclipse.core.databinding.property.INativePropertyListener;
18
import org.eclipse.core.databinding.property.ISimplePropertyListener;
19
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
20
21
/**
22
 * @since 3.3
23
 * 
24
 */
25
public class PojoValueProperty extends SimpleValueProperty {
26
	private final PropertyDescriptor propertyDescriptor;
27
	private final Class valueType;
28
29
	/**
30
	 * @param propertyDescriptor
31
	 * @param valueType
32
	 */
33
	public PojoValueProperty(PropertyDescriptor propertyDescriptor,
34
			Class valueType) {
35
		this.propertyDescriptor = propertyDescriptor;
36
		this.valueType = valueType == null ? propertyDescriptor
37
				.getPropertyType() : valueType;
38
	}
39
40
	public Object getValueType() {
41
		return valueType;
42
	}
43
44
	protected Object doGetValue(Object source) {
45
		if (source == null)
46
			return null;
47
		return BeanPropertyHelper.readProperty(source, propertyDescriptor);
48
	}
49
50
	protected void doSetValue(Object source, Object value) {
51
		BeanPropertyHelper.writeProperty(source, propertyDescriptor, value);
52
	}
53
54
	public INativePropertyListener adaptListener(
55
			ISimplePropertyListener listener) {
56
		return null;
57
	}
58
59
	protected void doAddListener(Object source, INativePropertyListener listener) {
60
	}
61
62
	protected void doRemoveListener(Object source,
63
			INativePropertyListener listener) {
64
	}
65
66
	public String toString() {
67
		Class beanClass = propertyDescriptor.getReadMethod()
68
				.getDeclaringClass();
69
		String propertyName = propertyDescriptor.getName();
70
		String s = beanClass.getName() + "." + propertyName + ""; //$NON-NLS-1$ //$NON-NLS-2$
71
72
		if (valueType != null)
73
			s += " <" + valueType.getName() + ">"; //$NON-NLS-1$//$NON-NLS-2$
74
		return s;
75
	}
76
}
(-)src/org/eclipse/core/internal/databinding/beans/AnonymousBeanListProperty.java (+66 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.BindingException;
18
import org.eclipse.core.databinding.beans.BeanProperties;
19
import org.eclipse.core.databinding.property.list.DelegatingListProperty;
20
import org.eclipse.core.databinding.property.list.IListProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class AnonymousBeanListProperty extends DelegatingListProperty {
27
	private final String propertyName;
28
29
	private Map delegates;
30
31
	/**
32
	 * @param propertyName
33
	 * @param elementType
34
	 */
35
	public AnonymousBeanListProperty(String propertyName, Class elementType) {
36
		super(elementType);
37
		this.propertyName = propertyName;
38
		this.delegates = new HashMap();
39
	}
40
41
	protected IListProperty doGetDelegate(Object source) {
42
		Class beanClass = source.getClass();
43
		if (delegates.containsKey(beanClass))
44
			return (IListProperty) delegates.get(beanClass);
45
46
		IListProperty delegate;
47
		try {
48
			delegate = BeanProperties.list(beanClass, propertyName,
49
					(Class) getElementType());
50
		} catch (BindingException noSuchProperty) {
51
			delegate = null;
52
		}
53
		delegates.put(beanClass, delegate);
54
		return delegate;
55
	}
56
57
	public String toString() {
58
		String s = "{{Generic Bean}}." + propertyName + "[]"; //$NON-NLS-1$ //$NON-NLS-2$
59
60
		Class elementType = (Class) getElementType();
61
		if (elementType != null)
62
			s += " <" + elementType.getName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$
63
64
		return s;
65
	}
66
}
(-)src/org/eclipse/core/internal/databinding/beans/AnonymousPojoSetProperty.java (+66 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.BindingException;
18
import org.eclipse.core.databinding.beans.PojoProperties;
19
import org.eclipse.core.databinding.property.set.DelegatingSetProperty;
20
import org.eclipse.core.databinding.property.set.ISetProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class AnonymousPojoSetProperty extends DelegatingSetProperty {
27
	private final String propertyName;
28
29
	private Map delegates;
30
31
	/**
32
	 * @param propertyName
33
	 * @param elementType
34
	 */
35
	public AnonymousPojoSetProperty(String propertyName, Class elementType) {
36
		super(elementType);
37
		this.propertyName = propertyName;
38
		this.delegates = new HashMap();
39
	}
40
41
	protected ISetProperty doGetDelegate(Object source) {
42
		Class beanClass = source.getClass();
43
		if (delegates.containsKey(beanClass))
44
			return (ISetProperty) delegates.get(beanClass);
45
46
		ISetProperty delegate;
47
		try {
48
			delegate = PojoProperties.set(beanClass, propertyName,
49
					(Class) getElementType());
50
		} catch (BindingException noSuchProperty) {
51
			delegate = null;
52
		}
53
		delegates.put(beanClass, delegate);
54
		return delegate;
55
	}
56
57
	public String toString() {
58
		String s = "{{Generic POJO}}." + propertyName + "{}"; //$NON-NLS-1$ //$NON-NLS-2$
59
60
		Class elementType = (Class) getElementType();
61
		if (elementType != null)
62
			s += " <" + elementType.getName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$
63
64
		return s;
65
	}
66
}
(-)src/org/eclipse/core/internal/databinding/beans/AnonymousPojoMapProperty.java (+70 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.BindingException;
18
import org.eclipse.core.databinding.beans.PojoProperties;
19
import org.eclipse.core.databinding.property.map.DelegatingMapProperty;
20
import org.eclipse.core.databinding.property.map.IMapProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class AnonymousPojoMapProperty extends DelegatingMapProperty {
27
	private final String propertyName;
28
29
	private Map delegates;
30
31
	/**
32
	 * @param propertyName
33
	 * @param keyType
34
	 * @param valueType
35
	 */
36
	public AnonymousPojoMapProperty(String propertyName, Class keyType,
37
			Class valueType) {
38
		super(keyType, valueType);
39
		this.propertyName = propertyName;
40
		this.delegates = new HashMap();
41
	}
42
43
	protected IMapProperty doGetDelegate(Object source) {
44
		Class beanClass = source.getClass();
45
		if (delegates.containsKey(beanClass))
46
			return (IMapProperty) delegates.get(beanClass);
47
48
		IMapProperty delegate;
49
		try {
50
			delegate = PojoProperties.map(beanClass, propertyName,
51
					(Class) getKeyType(), (Class) getValueType());
52
		} catch (BindingException noSuchProperty) {
53
			delegate = null;
54
		}
55
		delegates.put(beanClass, delegate);
56
		return delegate;
57
	}
58
59
	public String toString() {
60
		String s = "{{Generic POJO}}." + propertyName + "{:}"; //$NON-NLS-1$ //$NON-NLS-2$
61
62
		Class keyType = (Class) getKeyType();
63
		Class valueType = (Class) getValueType();
64
		if (keyType != null || valueType != null) {
65
			s += " <" + keyType + ", " + valueType + ">"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
66
		}
67
68
		return s;
69
	}
70
}
(-)src/org/eclipse/core/internal/databinding/beans/BeanPropertyListenerSupport.java (+135 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *     Matthew Hall - bug 118516
11
 *******************************************************************************/
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.beans.PropertyChangeListener;
15
import java.lang.reflect.InvocationTargetException;
16
import java.lang.reflect.Method;
17
18
import org.eclipse.core.databinding.beans.BeansObservables;
19
import org.eclipse.core.databinding.util.Policy;
20
import org.eclipse.core.runtime.Assert;
21
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.core.runtime.Status;
23
24
/**
25
 * This is a helper that will hook up and listen for
26
 * <code>PropertyChangeEvent</code> events for a set of target JavaBeans
27
 * 
28
 * @since 1.0
29
 */
30
public class BeanPropertyListenerSupport {
31
	/**
32
	 * Start listen to target (if it supports the JavaBean property change
33
	 * listener pattern)
34
	 * 
35
	 * @param bean
36
	 * @param propertyName
37
	 * @param listener
38
	 */
39
	public static void hookListener(Object bean, String propertyName,
40
			PropertyChangeListener listener) {
41
		Assert.isNotNull(bean, "Bean cannot be null"); //$NON-NLS-1$
42
		Assert.isNotNull(listener, "Listener cannot be null"); //$NON-NLS-1$
43
		Assert.isNotNull(propertyName, "Property name cannot be null"); //$NON-NLS-1$
44
		processListener(bean, propertyName, listener,
45
				"addPropertyChangeListener", "Could not attach listener to ");//$NON-NLS-1$ //$NON-NLS-2$
46
	}
47
48
	/**
49
	 * Stop listen to target
50
	 * 
51
	 * @param bean
52
	 * @param propertyName
53
	 * @param listener
54
	 */
55
	public static void unhookListener(Object bean, String propertyName,
56
			PropertyChangeListener listener) {
57
		Assert.isNotNull(bean, "Bean cannot be null"); //$NON-NLS-1$
58
		Assert.isNotNull(listener, "Listener cannot be null"); //$NON-NLS-1$
59
		Assert.isNotNull(propertyName, "Property name cannot be null"); //$NON-NLS-1$
60
61
		processListener(
62
				bean,
63
				propertyName,
64
				listener,
65
				"removePropertyChangeListener", "Cound not remove listener from "); //$NON-NLS-1$ //$NON-NLS-2$
66
	}
67
68
	/**
69
	 * Invokes the method for the provided <code>methodName</code> attempting to
70
	 * first use the method with the property name and then the unnamed version.
71
	 * 
72
	 * @param bean
73
	 *            object to invoke the method on
74
	 * @param methodName
75
	 *            either addPropertyChangeListener or
76
	 *            removePropertyChangeListener
77
	 * @param message
78
	 *            string that will be prefixed to the target in an error message
79
	 * 
80
	 * @return <code>true</code> if the method was invoked successfully
81
	 */
82
	private static boolean processListener(Object bean, String propertyName,
83
			PropertyChangeListener listener, String methodName, String message) {
84
		Method method = null;
85
		Object[] parameters = null;
86
87
		try {
88
			try {
89
				method = bean.getClass().getMethod(
90
						methodName,
91
						new Class[] { String.class,
92
								PropertyChangeListener.class });
93
94
				parameters = new Object[] { propertyName, listener };
95
			} catch (NoSuchMethodException e) {
96
				method = bean.getClass().getMethod(methodName,
97
						new Class[] { PropertyChangeListener.class });
98
99
				parameters = new Object[] { listener };
100
			}
101
		} catch (SecurityException e) {
102
			// ignore
103
		} catch (NoSuchMethodException e) {
104
			log(IStatus.WARNING, message + bean, e);
105
		}
106
107
		if (method != null) {
108
			if (!method.isAccessible()) {
109
				method.setAccessible(true);
110
			}
111
			try {
112
				method.invoke(bean, parameters);
113
				return true;
114
			} catch (IllegalArgumentException e) {
115
				log(IStatus.WARNING, message + bean, e);
116
			} catch (IllegalAccessException e) {
117
				log(IStatus.WARNING, message + bean, e);
118
			} catch (InvocationTargetException e) {
119
				log(IStatus.WARNING, message + bean, e);
120
			}
121
		}
122
		return false;
123
	}
124
125
	/**
126
	 * Logs a message to the Data Binding logger.
127
	 */
128
	private static void log(int severity, String message, Throwable throwable) {
129
		if (BeansObservables.DEBUG) {
130
			Policy.getLog().log(
131
					new Status(severity, Policy.JFACE_DATABINDING, IStatus.OK,
132
							message, throwable));
133
		}
134
	}
135
}
(-)src/org/eclipse/core/internal/databinding/beans/AnonymousBeanSetProperty.java (+66 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.beans;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.databinding.BindingException;
18
import org.eclipse.core.databinding.beans.BeanProperties;
19
import org.eclipse.core.databinding.property.set.DelegatingSetProperty;
20
import org.eclipse.core.databinding.property.set.ISetProperty;
21
22
/**
23
 * @since 3.3
24
 * 
25
 */
26
public class AnonymousBeanSetProperty extends DelegatingSetProperty {
27
	private final String propertyName;
28
29
	private Map delegates;
30
31
	/**
32
	 * @param propertyName
33
	 * @param elementType
34
	 */
35
	public AnonymousBeanSetProperty(String propertyName, Class elementType) {
36
		super(elementType);
37
		this.propertyName = propertyName;
38
		this.delegates = new HashMap();
39
	}
40
41
	protected ISetProperty doGetDelegate(Object source) {
42
		Class beanClass = source.getClass();
43
		if (delegates.containsKey(beanClass))
44
			return (ISetProperty) delegates.get(beanClass);
45
46
		ISetProperty delegate;
47
		try {
48
			delegate = BeanProperties.set(beanClass, propertyName,
49
					(Class) getElementType());
50
		} catch (BindingException noSuchProperty) {
51
			delegate = null;
52
		}
53
		delegates.put(beanClass, delegate);
54
		return delegate;
55
	}
56
57
	public String toString() {
58
		String s = "{{Generic Bean}}." + propertyName + "{}"; //$NON-NLS-1$ //$NON-NLS-2$
59
60
		Class elementType = (Class) getElementType();
61
		if (elementType != null)
62
			s += " <" + elementType.getName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$
63
64
		return s;
65
	}
66
}
(-)src/org/eclipse/jface/examples/databinding/snippets/Snippet025TableViewerWithPropertyDerivedColumns.java (+289 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 The Pampered Chef, Inc. 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
 *     Coconut Palm Software, Inc. - Initial API and implementation
10
 *     Matthew Hall - bug 195222
11
 ******************************************************************************/
12
13
package org.eclipse.jface.examples.databinding.snippets;
14
15
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyChangeSupport;
17
18
import org.eclipse.core.databinding.DataBindingContext;
19
import org.eclipse.core.databinding.beans.BeanProperties;
20
import org.eclipse.core.databinding.observable.Realm;
21
import org.eclipse.core.databinding.observable.list.IObservableList;
22
import org.eclipse.core.databinding.observable.list.WritableList;
23
import org.eclipse.core.databinding.observable.value.IObservableValue;
24
import org.eclipse.core.databinding.property.Properties;
25
import org.eclipse.jface.databinding.swt.SWTObservables;
26
import org.eclipse.jface.databinding.swt.WidgetProperties;
27
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
28
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
29
import org.eclipse.jface.databinding.viewers.ViewerProperties;
30
import org.eclipse.jface.layout.GridDataFactory;
31
import org.eclipse.jface.layout.GridLayoutFactory;
32
import org.eclipse.jface.viewers.ComboViewer;
33
import org.eclipse.jface.viewers.StructuredViewer;
34
import org.eclipse.jface.viewers.TableViewer;
35
import org.eclipse.jface.viewers.Viewer;
36
import org.eclipse.jface.viewers.ViewerFilter;
37
import org.eclipse.swt.SWT;
38
import org.eclipse.swt.widgets.Combo;
39
import org.eclipse.swt.widgets.Display;
40
import org.eclipse.swt.widgets.Label;
41
import org.eclipse.swt.widgets.Shell;
42
import org.eclipse.swt.widgets.Table;
43
import org.eclipse.swt.widgets.TableColumn;
44
import org.eclipse.swt.widgets.Text;
45
46
/**
47
 * Demonstrates binding a TableViewer to a collection.
48
 */
49
public class Snippet025TableViewerWithPropertyDerivedColumns {
50
	public static void main(String[] args) {
51
		final Display display = new Display();
52
53
		// Set up data binding. In an RCP application, the threading Realm
54
		// will be set for you automatically by the Workbench. In an SWT
55
		// application, you can do this once, wrapping your binding
56
		// method call.
57
		Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
58
			public void run() {
59
				ViewModel viewModel = new ViewModel();
60
				Shell shell = new View(viewModel).createShell();
61
62
				// The SWT event loop
63
				while (!shell.isDisposed()) {
64
					if (!display.readAndDispatch()) {
65
						display.sleep();
66
					}
67
				}
68
			}
69
		});
70
	}
71
72
	// Minimal JavaBeans support
73
	public static abstract class AbstractModelObject {
74
		private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
75
				this);
76
77
		public void addPropertyChangeListener(PropertyChangeListener listener) {
78
			propertyChangeSupport.addPropertyChangeListener(listener);
79
		}
80
81
		public void addPropertyChangeListener(String propertyName,
82
				PropertyChangeListener listener) {
83
			propertyChangeSupport.addPropertyChangeListener(propertyName,
84
					listener);
85
		}
86
87
		public void removePropertyChangeListener(PropertyChangeListener listener) {
88
			propertyChangeSupport.removePropertyChangeListener(listener);
89
		}
90
91
		public void removePropertyChangeListener(String propertyName,
92
				PropertyChangeListener listener) {
93
			propertyChangeSupport.removePropertyChangeListener(propertyName,
94
					listener);
95
		}
96
97
		protected void firePropertyChange(String propertyName, Object oldValue,
98
				Object newValue) {
99
			propertyChangeSupport.firePropertyChange(propertyName, oldValue,
100
					newValue);
101
		}
102
	}
103
104
	private static Person UNKNOWN = new Person("unknown", null, null);
105
106
	// The data model class. This is normally a persistent class of some sort.
107
	static class Person extends AbstractModelObject {
108
		// A property...
109
		String name = "Donald Duck";
110
		Person mother;
111
		Person father;
112
113
		public Person(String name, Person mother, Person father) {
114
			this.name = name;
115
			this.mother = mother;
116
			this.father = father;
117
		}
118
119
		public String getName() {
120
			return name;
121
		}
122
123
		public void setName(String name) {
124
			firePropertyChange("name", this.name, this.name = name);
125
		}
126
127
		public Person getMother() {
128
			return mother;
129
		}
130
131
		public void setMother(Person mother) {
132
			firePropertyChange("mother", this.mother, this.mother = mother);
133
		}
134
135
		public Person getFather() {
136
			return father;
137
		}
138
139
		public void setFather(Person father) {
140
			firePropertyChange("father", this.father, this.father = father);
141
		}
142
	}
143
144
	// The View's model--the root of our Model graph for this particular GUI.
145
	//
146
	// Typically each View class has a corresponding ViewModel class.
147
	// The ViewModel is responsible for getting the objects to edit from the
148
	// data access tier. Since this snippet doesn't have any persistent objects
149
	// ro retrieve, this ViewModel just instantiates a model object to edit.
150
	static class ViewModel {
151
		// The model to bind
152
		private IObservableList people = new WritableList();
153
		{
154
			Person fergus = new Person("Fergus McDuck", UNKNOWN, UNKNOWN);
155
			Person downy = new Person("Downy O'Drake", UNKNOWN, UNKNOWN);
156
			Person scrooge = new Person("Scrooge McDuck", downy, fergus);
157
			Person hortense = new Person("Hortense McDuck", downy, fergus);
158
			Person quackmore = new Person("Quackmore Duck", UNKNOWN, UNKNOWN);
159
			Person della = new Person("Della Duck", hortense, quackmore);
160
			Person donald = new Person("Donald Duck", hortense, quackmore);
161
			people.add(UNKNOWN);
162
			people.add(downy);
163
			people.add(fergus);
164
			people.add(scrooge);
165
			people.add(quackmore);
166
			people.add(hortense);
167
			people.add(della);
168
			people.add(donald);
169
		}
170
171
		public IObservableList getPeople() {
172
			return people;
173
		}
174
	}
175
176
	// The GUI view
177
	static class View {
178
		private ViewModel viewModel;
179
		private Table duckFamily;
180
		private Text nameText;
181
		private Combo motherCombo;
182
		private Combo fatherCombo;
183
184
		public View(ViewModel viewModel) {
185
			this.viewModel = viewModel;
186
		}
187
188
		public Shell createShell() {
189
			// Build a UI
190
			Display display = Display.getDefault();
191
			Shell shell = new Shell(display);
192
			duckFamily = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
193
			duckFamily.setHeaderVisible(true);
194
			GridDataFactory.defaultsFor(duckFamily).span(2, 1).applyTo(
195
					duckFamily);
196
			createColumn("Name");
197
			createColumn("Mother");
198
			createColumn("Father");
199
			createColumn("Maternal Grandmother");
200
			createColumn("Maternal Grandfather");
201
			createColumn("Paternal Grandmother");
202
			createColumn("Paternal Grandfather");
203
204
			duckFamily.setLinesVisible(true);
205
206
			new Label(shell, SWT.NONE).setText("Name:");
207
			nameText = new Text(shell, SWT.BORDER);
208
			GridDataFactory.defaultsFor(nameText).grab(true, false).applyTo(
209
					nameText);
210
211
			new Label(shell, SWT.NONE).setText("Mother:");
212
			motherCombo = new Combo(shell, SWT.READ_ONLY);
213
214
			new Label(shell, SWT.NONE).setText("Father:");
215
			fatherCombo = new Combo(shell, SWT.READ_ONLY);
216
217
			DataBindingContext bindingContext = new DataBindingContext();
218
			bindGUI(bindingContext);
219
220
			GridLayoutFactory.swtDefaults().numColumns(2).applyTo(shell);
221
			// Open and return the Shell
222
			shell.setSize(800, 300);
223
			shell.open();
224
			return shell;
225
		}
226
227
		private void createColumn(String string) {
228
			final TableColumn column = new TableColumn(duckFamily, SWT.NONE);
229
			column.setText(string);
230
			column.pack();
231
			if (column.getWidth() < 100)
232
				column.setWidth(100);
233
		}
234
235
		protected void bindGUI(DataBindingContext dbc) {
236
			// Since we're using a JFace Viewer, we do first wrap our Table...
237
			TableViewer peopleViewer = new TableViewer(duckFamily);
238
			peopleViewer.addFilter(new ViewerFilter() {
239
				public boolean select(Viewer viewer, Object parentElement,
240
						Object element) {
241
					return element != UNKNOWN;
242
				}
243
			});
244
245
			bindViewer(peopleViewer, viewModel.getPeople(), Person.class,
246
					new String[] { "name", "mother.name", "father.name",
247
							"mother.mother.name", "mother.father.name",
248
							"father.mother.name", "father.father.name" });
249
250
			IObservableValue masterSelection = ViewerProperties
251
					.singleSelection().observe(peopleViewer);
252
253
			dbc.bindValue(WidgetProperties.text(SWT.Modify).observe(nameText),
254
					BeanProperties.value(Person.class, "name").observeDetail(
255
							masterSelection), null, null);
256
257
			ComboViewer mothercomboViewer = new ComboViewer(motherCombo);
258
			bindViewer(mothercomboViewer, viewModel.getPeople(), Person.class,
259
					"name");
260
261
			dbc.bindValue(ViewerProperties.singleSelection().observe(
262
					mothercomboViewer), BeanProperties.value(Person.class,
263
					"mother").observeDetail(masterSelection), null, null);
264
265
			ComboViewer fatherComboViewer = new ComboViewer(fatherCombo);
266
			bindViewer(fatherComboViewer, viewModel.getPeople(), Person.class,
267
					"name");
268
269
			dbc.bindValue(ViewerProperties.singleSelection().observe(
270
					fatherComboViewer), BeanProperties.value(Person.class,
271
					"father").observeDetail(masterSelection), null, null);
272
		}
273
274
		private void bindViewer(StructuredViewer viewer, IObservableList input,
275
				Class beanClass, String propertyName) {
276
			bindViewer(viewer, input, beanClass, new String[] { propertyName });
277
		}
278
279
		private void bindViewer(StructuredViewer viewer, IObservableList input,
280
				Class beanClass, String[] propertyNames) {
281
			ObservableListContentProvider cp = new ObservableListContentProvider();
282
			viewer.setContentProvider(cp);
283
			viewer.setLabelProvider(new ObservableMapLabelProvider(Properties
284
					.observeEach(cp.getKnownElements(), BeanProperties.values(
285
							beanClass, propertyNames))));
286
			viewer.setInput(input);
287
		}
288
	}
289
}
(-)src/org/eclipse/jface/examples/databinding/snippets/Snippet026AnonymousBeanProperties.java (+410 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Matthew Hall 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
 *     Matthew Hall - initial API and implementation (bug 247997)
10
 ******************************************************************************/
11
12
package org.eclipse.jface.examples.databinding.snippets;
13
14
import java.beans.PropertyChangeListener;
15
import java.beans.PropertyChangeSupport;
16
import java.util.Collections;
17
import java.util.Iterator;
18
import java.util.Set;
19
import java.util.TreeSet;
20
21
import org.eclipse.core.databinding.DataBindingContext;
22
import org.eclipse.core.databinding.beans.BeanProperties;
23
import org.eclipse.core.databinding.beans.BeansObservables;
24
import org.eclipse.core.databinding.observable.Realm;
25
import org.eclipse.core.databinding.observable.map.IObservableMap;
26
import org.eclipse.core.databinding.observable.set.SetDiff;
27
import org.eclipse.core.databinding.observable.value.IObservableValue;
28
import org.eclipse.core.databinding.property.INativePropertyListener;
29
import org.eclipse.core.databinding.property.ISimplePropertyListener;
30
import org.eclipse.core.databinding.property.SimplePropertyEvent;
31
import org.eclipse.core.databinding.property.set.DelegatingSetProperty;
32
import org.eclipse.core.databinding.property.set.ISetProperty;
33
import org.eclipse.core.databinding.property.set.SimpleSetProperty;
34
import org.eclipse.jface.databinding.swt.SWTObservables;
35
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
36
import org.eclipse.jface.databinding.viewers.ObservableSetTreeContentProvider;
37
import org.eclipse.jface.databinding.viewers.ViewersObservables;
38
import org.eclipse.jface.viewers.ArrayContentProvider;
39
import org.eclipse.jface.viewers.ComboViewer;
40
import org.eclipse.jface.viewers.TreeViewer;
41
import org.eclipse.swt.SWT;
42
import org.eclipse.swt.layout.GridData;
43
import org.eclipse.swt.layout.GridLayout;
44
import org.eclipse.swt.widgets.Combo;
45
import org.eclipse.swt.widgets.Display;
46
import org.eclipse.swt.widgets.Label;
47
import org.eclipse.swt.widgets.Shell;
48
import org.eclipse.swt.widgets.Text;
49
import org.eclipse.swt.widgets.Tree;
50
import org.eclipse.swt.widgets.TreeColumn;
51
52
/**
53
 * @since 3.2
54
 * 
55
 */
56
public class Snippet026AnonymousBeanProperties {
57
	private ComboViewer statusViewer;
58
	private Combo combo;
59
	private Text nameText;
60
	private TreeViewer contactViewer;
61
62
	public static void main(String[] args) {
63
		Display display = new Display();
64
		Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
65
			public void run() {
66
				try {
67
					Snippet026AnonymousBeanProperties window = new Snippet026AnonymousBeanProperties();
68
					window.open();
69
				} catch (Exception e) {
70
					e.printStackTrace();
71
				}
72
			}
73
		});
74
	}
75
76
	private ApplicationModel model;
77
	private Shell shell;
78
	private Tree tree;
79
80
	// Minimal JavaBeans support
81
	public static abstract class AbstractModelObject {
82
		private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
83
				this);
84
85
		public void addPropertyChangeListener(PropertyChangeListener listener) {
86
			propertyChangeSupport.addPropertyChangeListener(listener);
87
		}
88
89
		public void addPropertyChangeListener(String propertyName,
90
				PropertyChangeListener listener) {
91
			propertyChangeSupport.addPropertyChangeListener(propertyName,
92
					listener);
93
		}
94
95
		public void removePropertyChangeListener(PropertyChangeListener listener) {
96
			propertyChangeSupport.removePropertyChangeListener(listener);
97
		}
98
99
		public void removePropertyChangeListener(String propertyName,
100
				PropertyChangeListener listener) {
101
			propertyChangeSupport.removePropertyChangeListener(propertyName,
102
					listener);
103
		}
104
105
		protected void firePropertyChange(String propertyName, Object oldValue,
106
				Object newValue) {
107
			propertyChangeSupport.firePropertyChange(propertyName, oldValue,
108
					newValue);
109
		}
110
	}
111
112
	public static class ContactGroup extends AbstractModelObject implements
113
			Comparable {
114
		private String name;
115
		private Set contacts = new TreeSet();
116
117
		ContactGroup(String name) {
118
			this.name = checkNull(name);
119
		}
120
121
		private String checkNull(String string) {
122
			if (string == null)
123
				throw new NullPointerException();
124
			return string;
125
		}
126
127
		public String getName() {
128
			return name;
129
		}
130
131
		public void setName(String name) {
132
			firePropertyChange("name", this.name, this.name = checkNull(name));
133
		}
134
135
		public Set getContacts() {
136
			return new TreeSet(contacts);
137
		}
138
139
		public void addContact(Contact contact) {
140
			Set oldValue = getContacts();
141
			contacts.add(contact);
142
			Set newValue = getContacts();
143
			firePropertyChange("contacts", oldValue, newValue);
144
		}
145
146
		public void removeContact(Contact contact) {
147
			Set oldValue = getContacts();
148
			contacts.remove(contact);
149
			Set newValue = getContacts();
150
			firePropertyChange("contacts", oldValue, newValue);
151
		}
152
153
		public int compareTo(Object o) {
154
			ContactGroup that = (ContactGroup) o;
155
			return this.name.compareTo(that.name);
156
		}
157
	}
158
159
	public static class Contact extends AbstractModelObject implements
160
			Comparable {
161
		private String name;
162
		private String status;
163
164
		private String checkNull(String string) {
165
			if (string == null)
166
				throw new NullPointerException();
167
			return string;
168
		}
169
170
		public Contact(String name, String status) {
171
			this.name = checkNull(name);
172
			this.status = checkNull(status);
173
		}
174
175
		public String getName() {
176
			return name;
177
		}
178
179
		public void setName(String name) {
180
			firePropertyChange("name", this.name, this.name = checkNull(name));
181
		}
182
183
		public String getStatus() {
184
			return status;
185
		}
186
187
		public void setStatus(String status) {
188
			firePropertyChange("status", this.status,
189
					this.status = checkNull(status));
190
		}
191
192
		public int compareTo(Object o) {
193
			Contact that = (Contact) o;
194
			int result = this.name.compareTo(that.name);
195
			if (result == 0)
196
				result = this.status.compareTo(that.status);
197
			return result;
198
		}
199
	}
200
201
	public static class ApplicationModel extends AbstractModelObject {
202
		private Set groups = new TreeSet();
203
204
		public Set getGroups() {
205
			return new TreeSet(groups);
206
		}
207
208
		public void setGroups(Set groups) {
209
			Set oldValue = getGroups();
210
			this.groups = new TreeSet(groups);
211
			Set newValue = getGroups();
212
			firePropertyChange("groups", oldValue, newValue);
213
		}
214
	}
215
216
	/**
217
	 * Set property for the "contacts" property of a ContactGroup. Since
218
	 * ContactGroup does not have a setContacts() method we have to write our
219
	 * own property to apply set changes incrementally through the addContact
220
	 * and removeContact methods.
221
	 */
222
	public static class ContactGroupContactsProperty extends SimpleSetProperty {
223
		public Object getElementType() {
224
			return Contact.class;
225
		}
226
227
		protected Set doGetSet(Object source) {
228
			if (source == null)
229
				return Collections.EMPTY_SET;
230
			return ((ContactGroup) source).getContacts();
231
		}
232
233
		protected void doSetSet(Object source, Set set, SetDiff diff) {
234
			ContactGroup group = (ContactGroup) source;
235
			for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) {
236
				Contact contact = (Contact) it.next();
237
				group.removeContact(contact);
238
			}
239
			for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) {
240
				Contact contact = (Contact) it.next();
241
				group.addContact(contact);
242
			}
243
		}
244
245
		public INativePropertyListener adaptListener(
246
				final ISimplePropertyListener listener) {
247
			return new Listener(listener);
248
		}
249
250
		private class Listener implements INativePropertyListener,
251
				PropertyChangeListener {
252
			private final ISimplePropertyListener listener;
253
254
			Listener(ISimplePropertyListener listener) {
255
				this.listener = listener;
256
			}
257
258
			public void propertyChange(java.beans.PropertyChangeEvent evt) {
259
				listener.handlePropertyChange(new SimplePropertyEvent(evt
260
						.getSource(), ContactGroupContactsProperty.this, null));
261
			}
262
		}
263
264
		protected void doAddListener(Object source,
265
				INativePropertyListener listener) {
266
			if (source != null) {
267
				((ContactGroup) source).addPropertyChangeListener("contacts",
268
						(Listener) listener);
269
			}
270
		}
271
272
		protected void doRemoveListener(Object source,
273
				INativePropertyListener listener) {
274
			if (source != null) {
275
				((ContactGroup) source).removePropertyChangeListener(
276
						"contacts", (Listener) listener);
277
			}
278
		}
279
	}
280
281
	public void open() {
282
		model = createDefaultModel();
283
284
		final Display display = Display.getDefault();
285
		createContents();
286
		bindUI();
287
		shell.open();
288
		shell.layout();
289
		while (!shell.isDisposed()) {
290
			if (!display.readAndDispatch())
291
				display.sleep();
292
		}
293
	}
294
295
	private static final String[] statuses = new String[] { "Online", "Idle",
296
			"Busy", "Offline" };
297
298
	/**
299
	 * @return
300
	 */
301
	private ApplicationModel createDefaultModel() {
302
		ContactGroup swtGroup = new ContactGroup("SWT");
303
		swtGroup.addContact(new Contact("Steve Northover", "Busy"));
304
		swtGroup.addContact(new Contact("Grant Gayed", "Online"));
305
		swtGroup.addContact(new Contact("Veronika Irvine", "Offline"));
306
		swtGroup.addContact(new Contact("Mike Wilson", "Online"));
307
		swtGroup.addContact(new Contact("Christophe Cornu", "Idle"));
308
		swtGroup.addContact(new Contact("Lynne Kues", "Online"));
309
		swtGroup.addContact(new Contact("Silenio Quarti", "Idle"));
310
311
		ContactGroup jdbGroup = new ContactGroup("JFace Data Binding");
312
		jdbGroup.addContact(new Contact("Boris Bokowski", "Online"));
313
		jdbGroup.addContact(new Contact("Matthew Hall", "Idle"));
314
315
		Set groups = new TreeSet();
316
		groups.add(swtGroup);
317
		groups.add(jdbGroup);
318
		ApplicationModel model = new ApplicationModel();
319
		model.setGroups(groups);
320
321
		return model;
322
	}
323
324
	/**
325
	 * Create contents of the window
326
	 */
327
	protected void createContents() {
328
		shell = new Shell();
329
		shell.setSize(379, 393);
330
		shell.setText("Snippet026AnonymousBeanProperties");
331
		final GridLayout gridLayout = new GridLayout();
332
		gridLayout.numColumns = 4;
333
		shell.setLayout(gridLayout);
334
335
		contactViewer = new TreeViewer(shell, SWT.BORDER);
336
		tree = contactViewer.getTree();
337
		tree.setHeaderVisible(true);
338
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1));
339
340
		final TreeColumn nameColumn = new TreeColumn(tree, SWT.NONE);
341
		nameColumn.setWidth(163);
342
		nameColumn.setText("Name");
343
344
		final TreeColumn newColumnTreeColumn = new TreeColumn(tree, SWT.NONE);
345
		newColumnTreeColumn.setWidth(100);
346
		newColumnTreeColumn.setText("Status");
347
348
		final Label nameLabel = new Label(shell, SWT.NONE);
349
		nameLabel.setText("Name");
350
351
		nameText = new Text(shell, SWT.BORDER);
352
		final GridData gd_nameText = new GridData(SWT.FILL, SWT.CENTER, true,
353
				false);
354
		nameText.setLayoutData(gd_nameText);
355
356
		final Label statusLabel = new Label(shell, SWT.NONE);
357
		statusLabel.setLayoutData(new GridData());
358
		statusLabel.setText("Status");
359
360
		statusViewer = new ComboViewer(shell, SWT.READ_ONLY);
361
		combo = statusViewer.getCombo();
362
		combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
363
	}
364
365
	private void bindUI() {
366
		ISetProperty treeChildrenProperty = new DelegatingSetProperty() {
367
			ISetProperty modelGroups = BeanProperties.set(
368
					ApplicationModel.class, "groups");
369
			ISetProperty groupContacts = BeanProperties.set(ContactGroup.class,
370
					"contacts");
371
372
			protected ISetProperty doGetDelegate(Object source) {
373
				if (source instanceof ApplicationModel)
374
					return modelGroups;
375
				if (source instanceof ContactGroup)
376
					return groupContacts;
377
				return null;
378
			}
379
		};
380
381
		ObservableSetTreeContentProvider cp = new ObservableSetTreeContentProvider(
382
				treeChildrenProperty.setFactory(), null);
383
		contactViewer.setContentProvider(cp);
384
385
		IObservableMap[] labelMaps = BeansObservables.observeMaps(cp
386
				.getKnownElements(), new String[] { "name", "status" });
387
		contactViewer
388
				.setLabelProvider(new ObservableMapLabelProvider(labelMaps));
389
390
		contactViewer.setInput(model);
391
392
		contactViewer.expandAll();
393
394
		IObservableValue selection = ViewersObservables
395
				.observeSingleSelection(contactViewer);
396
397
		DataBindingContext dbc = new DataBindingContext();
398
399
		dbc.bindValue(SWTObservables.observeText(nameText, SWT.Modify),
400
				BeanProperties.value("name").observeDetail(selection), null,
401
				null);
402
403
		statusViewer.setContentProvider(new ArrayContentProvider());
404
		statusViewer.setInput(statuses);
405
406
		dbc.bindValue(ViewersObservables.observeSingleSelection(statusViewer),
407
				BeanProperties.value("status").observeDetail(selection), null,
408
				null);
409
	}
410
}
(-)src/org/eclipse/jface/databinding/conformance/MutableObservableListContractTest.java (-227 / +138 lines)
Lines 21-33 Link Here
21
import junit.framework.Test;
21
import junit.framework.Test;
22
22
23
import org.eclipse.core.databinding.observable.list.IObservableList;
23
import org.eclipse.core.databinding.observable.list.IObservableList;
24
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
24
import org.eclipse.core.databinding.observable.list.ListDiff;
25
import org.eclipse.jface.databinding.conformance.delegate.IObservableCollectionContractDelegate;
25
import org.eclipse.jface.databinding.conformance.delegate.IObservableCollectionContractDelegate;
26
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
26
import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker;
27
import org.eclipse.jface.databinding.conformance.util.ListChangeEventTracker;
27
import org.eclipse.jface.databinding.conformance.util.ListChangeEventTracker;
28
import org.eclipse.jface.databinding.conformance.util.SuiteBuilder;
28
import org.eclipse.jface.databinding.conformance.util.SuiteBuilder;
29
29
30
31
/**
30
/**
32
 * Mutability tests for IObservableList.
31
 * Mutability tests for IObservableList.
33
 * 
32
 * 
Lines 68-89 Link Here
68
	}
67
	}
69
68
70
	public void testAdd_ListChangeEvent() throws Exception {
69
	public void testAdd_ListChangeEvent() throws Exception {
70
		final Object element = delegate.createElement(list);
71
		assertListChangeEventFired(new Runnable() {
71
		assertListChangeEventFired(new Runnable() {
72
			public void run() {
72
			public void run() {
73
				list.add(delegate.createElement(list));
73
				list.add(element);
74
			}
74
			}
75
		}, "List.add(Object)", list);
75
		}, "List.add(Object)", list, Collections.singletonList(element));
76
	}
76
	}
77
77
78
	public void testAdd_ListDiffEntry() throws Exception {
78
	public void testAdd_ListDiffEntry() throws Exception {
79
		list.add(delegate.createElement(list));
79
		Object element0 = delegate.createElement(list);
80
		final Object element = delegate.createElement(list);
80
		list.add(element0);
81
		final Object element1 = delegate.createElement(list);
81
82
82
		assertAddDiffEntry(new Runnable() {
83
		assertListChangeEventFired(new Runnable() {
83
			public void run() {
84
			public void run() {
84
				list.add(element);
85
				list.add(element1);
85
			}
86
			}
86
		}, "List.add(Object)", list, element, 1);
87
		}, "List.add(Object)", list, Arrays.asList(new Object[] { element0,
88
				element1 }));
87
	}
89
	}
88
90
89
	public void testAddAtIndex_ChangeEvent() throws Exception {
91
	public void testAddAtIndex_ChangeEvent() throws Exception {
Lines 95-105 Link Here
95
	}
97
	}
96
98
97
	public void testAddAtIndex_ListChangeEvent() throws Exception {
99
	public void testAddAtIndex_ListChangeEvent() throws Exception {
100
		final Object element = delegate.createElement(list);
98
		assertListChangeEventFired(new Runnable() {
101
		assertListChangeEventFired(new Runnable() {
99
			public void run() {
102
			public void run() {
100
				list.add(0, delegate.createElement(list));
103
				list.add(0, element);
101
			}
104
			}
102
		}, "List.add(int, Object)", list);
105
		}, "List.add(int, Object)", list, Collections.singletonList(element));
103
	}
106
	}
104
107
105
	public void testAddAtIndex_ChangeEventFiredAfterElementIsAdded()
108
	public void testAddAtIndex_ChangeEventFiredAfterElementIsAdded()
Lines 114-157 Link Here
114
	}
117
	}
115
118
116
	public void testAddAtIndex_ListDiffEntry() throws Exception {
119
	public void testAddAtIndex_ListDiffEntry() throws Exception {
117
		list.add(delegate.createElement(list));
120
		Object element0 = delegate.createElement(list);
118
		final Object element = delegate.createElement(list);
121
		list.add(element0);
122
		final Object element1 = delegate.createElement(list);
119
123
120
		assertAddDiffEntry(new Runnable() {
124
		assertListChangeEventFired(new Runnable() {
121
			public void run() {
125
			public void run() {
122
				list.add(1, element);
126
				list.add(1, element1);
123
			}
127
			}
124
		}, "List.add(int, Object)", list, element, 1);
128
		}, "List.add(int, Object)", list, Arrays.asList(new Object[] {
129
				element0, element1 }));
125
	}
130
	}
126
131
127
	public void testAddAll_ListChangeEvent() throws Exception {
132
	public void testAddAll_ListChangeEvent() throws Exception {
133
		final Object element = delegate.createElement(list);
128
		assertListChangeEventFired(new Runnable() {
134
		assertListChangeEventFired(new Runnable() {
129
			public void run() {
135
			public void run() {
130
				list.addAll(Arrays.asList(new Object[] { delegate
136
				list.addAll(Collections.singletonList(element));
131
						.createElement(list) }));
132
			}
137
			}
133
		}, "List.addAll(Collection", list);
138
		}, "List.addAll(Collection", list, Collections.singletonList(element));
134
	}
139
	}
135
140
136
	public void testAddAll_ListDiffEntry() throws Exception {
141
	public void testAddAll_ListDiffEntry() throws Exception {
137
		final Object element = delegate.createElement(list);
142
		final Object element = delegate.createElement(list);
138
143
139
		assertAddDiffEntry(new Runnable() {
144
		assertListChangeEventFired(new Runnable() {
140
			public void run() {
145
			public void run() {
141
				list.addAll(Arrays.asList(new Object[] { element }));
146
				list.addAll(Collections.singletonList(element));
142
			}
147
			}
143
		}, "List.addAll(Collection)", list, element, 0);
148
		}, "List.addAll(Collection)", list, Collections.singletonList(element));
144
	}
149
	}
145
150
146
	public void testAddAll_ListDiffEntry2() throws Exception {
151
	public void testAddAll_ListDiffEntry2() throws Exception {
147
		list.add(delegate.createElement(list));
152
		final Object element0 = delegate.createElement(list);
148
		final Object element = delegate.createElement(list);
153
		list.add(element0);
154
		final Object element1 = delegate.createElement(list);
149
155
150
		assertAddDiffEntry(new Runnable() {
156
		assertListChangeEventFired(new Runnable() {
151
			public void run() {
157
			public void run() {
152
				list.addAll(Collections.singletonList(element));
158
				list.addAll(Collections.singletonList(element1));
153
			}
159
			}
154
		}, "List.addAll(Collection)", list, element, 1);
160
		}, "List.addAll(Collection)", list, Arrays.asList(new Object[] {
161
				element0, element1 }));
155
	}
162
	}
156
163
157
	public void testAddAllAtIndex_ChangeEvent() throws Exception {
164
	public void testAddAllAtIndex_ChangeEvent() throws Exception {
Lines 164-175 Link Here
164
	}
171
	}
165
172
166
	public void testAddAllAtIndex_ListChangeEvent() throws Exception {
173
	public void testAddAllAtIndex_ListChangeEvent() throws Exception {
174
		final Object element = delegate.createElement(list);
167
		assertListChangeEventFired(new Runnable() {
175
		assertListChangeEventFired(new Runnable() {
168
			public void run() {
176
			public void run() {
169
				list.addAll(0, Arrays.asList(new Object[] { delegate
177
				list.addAll(0, Collections.singletonList(element));
170
						.createElement(list) }));
171
			}
178
			}
172
		}, "List.addAll(int, Collection)", list);
179
		}, "List.addAll(int, Collection)", list, Collections
180
				.singletonList(element));
173
	}
181
	}
174
182
175
	public void testAddAllAtIndex_ChangeEventFiredAfterElementIsAdded()
183
	public void testAddAllAtIndex_ChangeEventFiredAfterElementIsAdded()
Lines 184-197 Link Here
184
	}
192
	}
185
193
186
	public void testAddAllAtIndex_ListDiffEntry() throws Exception {
194
	public void testAddAllAtIndex_ListDiffEntry() throws Exception {
187
		list.add(delegate.createElement(list));
195
		Object element0 = delegate.createElement(list);
188
		final Object element = delegate.createElement(list);
196
		list.add(element0);
197
		final Object element1 = delegate.createElement(list);
189
198
190
		assertAddDiffEntry(new Runnable() {
199
		assertListChangeEventFired(new Runnable() {
191
			public void run() {
200
			public void run() {
192
				list.addAll(1, Arrays.asList(new Object[] { element }));
201
				list.addAll(1, Collections.singletonList(element1));
193
			}
202
			}
194
		}, "List.addAll(int, Collection)", list, element, 1);
203
		}, "List.addAll(int, Collection)", list, Arrays.asList(new Object[] {
204
				element0, element1 }));
195
	}
205
	}
196
206
197
	public void testSet_ChangeEvent() throws Exception {
207
	public void testSet_ChangeEvent() throws Exception {
Lines 205-263 Link Here
205
	}
215
	}
206
216
207
	public void testSet_ListChangeEvent() throws Exception {
217
	public void testSet_ListChangeEvent() throws Exception {
208
		list.add(delegate.createElement(list));
218
		final Object element0 = delegate.createElement(list);
219
		list.add(element0);
220
		final Object element1 = delegate.createElement(list);
209
221
210
		assertListChangeEventFired(new Runnable() {
222
		assertListChangeEventFired(new Runnable() {
211
			public void run() {
223
			public void run() {
212
				list.set(0, delegate.createElement(list));
224
				assertSame(element0, list.set(0, element1));
213
			}
225
			}
214
		}, "List.set(int, Object)", list);
226
		}, "List.set(int, Object)", list, Arrays
227
				.asList(new Object[] { element1 }));
215
	}
228
	}
216
229
217
	public void testSet_ChangeEventFiredAfterElementIsSet() throws Exception {
230
	public void testSet_ChangeEventFiredAfterElementIsSet() throws Exception {
218
		Object element1 = delegate.createElement(list);
231
		final Object element1 = delegate.createElement(list);
219
		list.add(element1);
232
		list.add(element1);
220
		final Object element2 = delegate.createElement(list);
233
		final Object element2 = delegate.createElement(list);
221
234
222
		assertContainsDuringChangeEvent(new Runnable() {
235
		assertContainsDuringChangeEvent(new Runnable() {
223
			public void run() {
236
			public void run() {
224
				list.set(0, element2);
237
				assertSame(element1, list.set(0, element2));
225
			}
238
			}
226
		}, "List.set(int, Object)", list, element2);
239
		}, "List.set(int, Object)", list, element2);
227
	}
240
	}
228
241
229
	public void testSet_ListDiffEntry() throws Exception {
242
	public void testSet_ListChangeEvent2() throws Exception {
230
		list.add(delegate.createElement(list));
243
		Object element0 = delegate.createElement(list);
231
		Object oldElement = delegate.createElement(list);
244
		list.add(element0);
232
		list.add(oldElement);
245
		Object oldElement1 = delegate.createElement(list);
233
246
		list.add(oldElement1);
234
		ListChangeEventTracker listener = ListChangeEventTracker.observe(list);
247
		final Object newElement1 = delegate.createElement(list);
235
236
		Object newElement = delegate.createElement(list);
237
		list.set(1, newElement);
238
239
		ListDiffEntry[] entries = listener.event.diff.getDifferences();
240
		assertEquals(
241
				"List.set(int, Object) should result in 2 list diff entries.",
242
				2, entries.length);
243
244
		ListDiffEntry remove = entries[0];
245
		assertFalse(remove.isAddition());
246
		assertEquals(
247
				"List.set(int, Object) removed element should be the old element.",
248
				oldElement, remove.getElement());
249
		assertEquals(
250
				"List.set(int, Object) removed index should be the index the new element was set at.",
251
				1, remove.getPosition());
252
248
253
		ListDiffEntry add = entries[1];
249
		assertListChangeEventFired(new Runnable() {
254
		assertTrue(add.isAddition());
250
			public void run() {
255
		assertEquals(
251
				list.set(1, newElement1);
256
				"List.set(int, Object) added element should be the set element.",
252
			}
257
				newElement, add.getElement());
253
		}, "List.set(int, Object)", list, Arrays.asList(new Object[] {
258
		assertEquals(
254
				element0, newElement1 }));
259
				"List.set(int, Object) add index should be the index the new element was set at.",
260
				1, add.getPosition());
261
	}
255
	}
262
256
263
	public void testMove_ChangeEvent() throws Exception {
257
	public void testMove_ChangeEvent() throws Exception {
Lines 289-304 Link Here
289
	}
283
	}
290
284
291
	public void testMove_ListChangeEvent() throws Exception {
285
	public void testMove_ListChangeEvent() throws Exception {
292
		final Object element = delegate.createElement(list);
286
		final Object element0 = delegate.createElement(list);
293
		list.add(element);
287
		list.add(element0);
294
		list.add(delegate.createElement(list));
288
		final Object element1 = delegate.createElement(list);
289
		list.add(element1);
295
290
296
		assertListChangeEventFired(new Runnable() {
291
		assertListChangeEventFired(new Runnable() {
297
			public void run() {
292
			public void run() {
298
				Object movedElement = list.move(0, 1);
293
				assertSame(element0, list.move(0, 1));
299
				assertEquals(element, movedElement);
300
			}
294
			}
301
		}, "IObservableList.move(int, int)", list);
295
		}, "IObservableList.move(int, int)", list, Arrays.asList(new Object[] {
296
				element1, element0 }));
302
	}
297
	}
303
298
304
	public void testMove_ChangeEventFiredAfterElementIsMoved() throws Exception {
299
	public void testMove_ChangeEventFiredAfterElementIsMoved() throws Exception {
Lines 316-357 Link Here
316
		assertSame(element0, list.get(1));
311
		assertSame(element0, list.get(1));
317
	}
312
	}
318
313
319
	public void testMove_ListDiffEntry() {
314
	public void testMove_ListChangeEvent2() {
320
		Object element = delegate.createElement(list);
315
		Object element0 = delegate.createElement(list);
321
		list.add(element);
316
		list.add(element0);
322
		list.add(delegate.createElement(list));
317
		Object element1 = delegate.createElement(list);
323
318
		list.add(element1);
324
		ListChangeEventTracker listener = ListChangeEventTracker.observe(list);
325
326
		list.move(0, 1);
327
328
		ListDiffEntry[] entries = listener.event.diff.getDifferences();
329
		assertEquals(
330
				"List.set(int, Object) should result in 2 list diff entries.",
331
				2, entries.length);
332
333
		ListDiffEntry remove = entries[0];
334
		ListDiffEntry add = entries[1];
335
		assertFalse(
336
				"IObservableList.move(int, int) removed element should be first in list diff",
337
				remove.isAddition());
338
		assertTrue(
339
				"IObservableList.move(int, int) added element should be second in list diff",
340
				add.isAddition());
341
342
		assertEquals(
343
				"IObservableList.move(int, int) remove entry contains incorrect element",
344
				element, remove.getElement());
345
		assertEquals(
346
				"IObservableList.move(int, int) add entry contains incorrect element",
347
				element, add.getElement());
348
319
349
		assertEquals(
320
		assertListChangeEventFired(new Runnable() {
350
				"IObservableList.move(int, int) remove entry should be the old element index",
321
			public void run() {
351
				0, remove.getPosition());
322
				list.move(0, 1);
352
		assertEquals(
323
			}
353
				"IObservableList.move(int, int) add entry should be the new element index",
324
		}, "IObservableList.move(int, int)", list, Arrays.asList(new Object[] {
354
				1, add.getPosition());
325
				element1, element0 }));
355
	}
326
	}
356
327
357
	public void testRemove_ListChangeEvent() throws Exception {
328
	public void testRemove_ListChangeEvent() throws Exception {
Lines 362-380 Link Here
362
			public void run() {
333
			public void run() {
363
				list.remove(element);
334
				list.remove(element);
364
			}
335
			}
365
		}, "List.remove(Object)", list);
336
		}, "List.remove(Object)", list, Collections.EMPTY_LIST);
366
	}
337
	}
367
338
368
	public void testRemove_ListDiffEntry() throws Exception {
339
	public void testRemove_ListDiffEntry() throws Exception {
369
		list.add(delegate.createElement(list));
340
		final Object element0 = delegate.createElement(list);
370
		final Object element = delegate.createElement(list);
341
		list.add(element0);
371
		list.add(element);
342
		final Object element1 = delegate.createElement(list);
343
		list.add(element1);
372
344
373
		assertRemoveDiffEntry(new Runnable() {
345
		assertListChangeEventFired(new Runnable() {
374
			public void run() {
346
			public void run() {
375
				list.remove(element);
347
				list.remove(element1);
376
			}
348
			}
377
		}, "List.remove(Object)", list, element, 1);
349
		}, "List.remove(Object)", list, Collections.singletonList(element0));
378
	}
350
	}
379
351
380
	public void testRemoveAtIndex_ChangeEvent() throws Exception {
352
	public void testRemoveAtIndex_ChangeEvent() throws Exception {
Lines 394-400 Link Here
394
			public void run() {
366
			public void run() {
395
				list.remove(0);
367
				list.remove(0);
396
			}
368
			}
397
		}, "List.remove(int)", list);
369
		}, "List.remove(int)", list, Collections.EMPTY_LIST);
398
	}
370
	}
399
371
400
	public void testRemoveAtIndex_ChangeEventFiredAfterElementIsRemoved()
372
	public void testRemoveAtIndex_ChangeEventFiredAfterElementIsRemoved()
Lines 410-424 Link Here
410
	}
382
	}
411
383
412
	public void testRemoveAtIndex_ListDiffEntry() throws Exception {
384
	public void testRemoveAtIndex_ListDiffEntry() throws Exception {
413
		list.add(delegate.createElement(list));
385
		Object element0 = delegate.createElement(list);
414
		Object element = delegate.createElement(list);
386
		list.add(element0);
415
		list.add(element);
387
		Object element1 = delegate.createElement(list);
388
		list.add(element1);
416
389
417
		assertRemoveDiffEntry(new Runnable() {
390
		assertListChangeEventFired(new Runnable() {
418
			public void run() {
391
			public void run() {
419
				list.remove(1);
392
				list.remove(1);
420
			}
393
			}
421
		}, "List.remove(int)", list, element, 1);
394
		}, "List.remove(int)", list, Collections.singletonList(element0));
422
	}
395
	}
423
396
424
	public void testRemoveAll_ListChangeEvent() throws Exception {
397
	public void testRemoveAll_ListChangeEvent() throws Exception {
Lines 427-483 Link Here
427
400
428
		assertListChangeEventFired(new Runnable() {
401
		assertListChangeEventFired(new Runnable() {
429
			public void run() {
402
			public void run() {
430
				list.removeAll(Arrays.asList(new Object[] { element }));
403
				list.removeAll(Collections.singletonList(element));
431
			}
404
			}
432
		}, "List.removeAll(Collection)", list);
405
		}, "List.removeAll(Collection)", list, Collections.EMPTY_LIST);
433
	}
406
	}
434
407
435
	public void testRemoveAll_ListDiffEntry() throws Exception {
408
	public void testRemoveAll_ListDiffEntry() throws Exception {
436
		final Object element = delegate.createElement(list);
409
		final Object element = delegate.createElement(list);
437
		list.add(element);
410
		list.add(element);
438
411
439
		assertRemoveDiffEntry(new Runnable() {
412
		assertListChangeEventFired(new Runnable() {
440
			public void run() {
413
			public void run() {
441
				list.removeAll(Arrays.asList(new Object[] { element }));
414
				list.removeAll(Collections.singletonList(element));
442
			}
415
			}
443
		}, "List.removeAll(Collection)", list, element, 0);
416
		}, "List.removeAll(Collection)", list, Collections.EMPTY_LIST);
444
	}
417
	}
445
418
446
	public void testRemoveAll_ListDiffEntry2() throws Exception {
419
	public void testRemoveAll_ListDiffEntry2() throws Exception {
447
		list.add(delegate.createElement(list));
420
		Object element0 = delegate.createElement(list);
448
		final Object element = delegate.createElement(list);
421
		list.add(element0);
449
		list.add(element);
422
		final Object element1 = delegate.createElement(list);
423
		list.add(element1);
450
424
451
		assertRemoveDiffEntry(new Runnable() {
425
		assertListChangeEventFired(new Runnable() {
452
			public void run() {
426
			public void run() {
453
				list.removeAll(Arrays.asList(new Object[] { element }));
427
				list.removeAll(Arrays.asList(new Object[] { element1 }));
454
			}
428
			}
455
		}, "List.removeAll(Collection)", list, element, 1);
429
		}, "List.removeAll(Collection)", list, Collections
430
				.singletonList(element0));
456
	}
431
	}
457
432
458
	public void testRetainAll_ListChangeEvent() throws Exception {
433
	public void testRetainAll_ListChangeEvent() throws Exception {
459
		final Object element1 = delegate.createElement(list);
434
		final Object element0 = delegate.createElement(list);
460
		list.add(element1);
435
		list.add(element0);
461
		list.add(delegate.createElement(list));
436
		list.add(delegate.createElement(list));
462
437
463
		assertListChangeEventFired(new Runnable() {
438
		assertListChangeEventFired(new Runnable() {
464
			public void run() {
439
			public void run() {
465
				list.retainAll(Arrays.asList(new Object[] { element1 }));
440
				list.retainAll(Arrays.asList(new Object[] { element0 }));
466
			}
441
			}
467
		}, "List.retainAll(Collection", list);
442
		}, "List.retainAll(Collection", list, Collections
443
				.singletonList(element0));
468
	}
444
	}
469
445
470
	public void testRetainAll_ListDiffEntry() throws Exception {
446
	public void testRetainAll_ListDiffEntry() throws Exception {
471
		final Object element1 = delegate.createElement(list);
447
		final Object element = delegate.createElement(list);
472
		list.add(element1);
448
		list.add(element);
473
		Object element2 = delegate.createElement(list);
449
		list.add(delegate.createElement(list));
474
		list.add(element2);
475
450
476
		assertRemoveDiffEntry(new Runnable() {
451
		assertListChangeEventFired(new Runnable() {
477
			public void run() {
452
			public void run() {
478
				list.retainAll(Arrays.asList(new Object[] { element1 }));
453
				list.retainAll(Arrays.asList(new Object[] { element }));
479
			}
454
			}
480
		}, "List.retainAll(Collection)", list, element2, 1);
455
		}, "List.retainAll(Collection)", list, Collections
456
				.singletonList(element));
481
	}
457
	}
482
458
483
	public void testClear_ListChangeEvent() throws Exception {
459
	public void testClear_ListChangeEvent() throws Exception {
Lines 487-504 Link Here
487
			public void run() {
463
			public void run() {
488
				list.clear();
464
				list.clear();
489
			}
465
			}
490
		}, "List.clear()", list);
466
		}, "List.clear()", list, Collections.EMPTY_LIST);
491
	}
467
	}
492
468
493
	public void testClear_ListDiffEntry() throws Exception {
469
	public void testClear_ListDiffEntry() throws Exception {
494
		Object element = delegate.createElement(list);
470
		list.add(delegate.createElement(list));
495
		list.add(element);
496
471
497
		assertRemoveDiffEntry(new Runnable() {
472
		assertListChangeEventFired(new Runnable() {
498
			public void run() {
473
			public void run() {
499
				list.clear();
474
				list.clear();
500
			}
475
			}
501
		}, "List.clear()", list, element, 0);
476
		}, "List.clear()", list, Collections.EMPTY_LIST);
502
	}
477
	}
503
478
504
	public void testClear_ClearsList() {
479
	public void testClear_ClearsList() {
Lines 509-528 Link Here
509
		Assert.assertEquals(Collections.EMPTY_LIST, list);
484
		Assert.assertEquals(Collections.EMPTY_LIST, list);
510
	}
485
	}
511
486
512
	/**
513
	 * Asserts standard behaviors of firing list change events.
514
	 * <ul>
515
	 * <li>Event fires once.</li>
516
	 * <li>Source of the event is the provided <code>list</code>.
517
	 * <li>The list change event is fired after the change event.</li>
518
	 * </ul>
519
	 * 
520
	 * @param runnable
521
	 * @param methodName
522
	 * @param list
523
	 */
524
	private void assertListChangeEventFired(Runnable runnable,
487
	private void assertListChangeEventFired(Runnable runnable,
525
			String methodName, IObservableList list) {
488
			String methodName, IObservableList list, List newList) {
489
		List oldList = new ArrayList(list);
490
526
		List queue = new ArrayList();
491
		List queue = new ArrayList();
527
		ListChangeEventTracker listListener = new ListChangeEventTracker(queue);
492
		ListChangeEventTracker listListener = new ListChangeEventTracker(queue);
528
		ChangeEventTracker changeListener = new ChangeEventTracker(queue);
493
		ChangeEventTracker changeListener = new ChangeEventTracker(queue);
Lines 546-617 Link Here
546
		assertEquals("ListChangeEvent of " + methodName
511
		assertEquals("ListChangeEvent of " + methodName
547
				+ " should have fired after the ChangeEvent.", listListener,
512
				+ " should have fired after the ChangeEvent.", listListener,
548
				queue.get(1));
513
				queue.get(1));
549
	}
550
551
	/**
552
	 * Asserts the list diff entry for a remove operation.
553
	 * 
554
	 * @param runnable
555
	 * @param methodName
556
	 * @param list
557
	 * @param element
558
	 * @param index
559
	 */
560
	private void assertRemoveDiffEntry(Runnable runnable, String methodName,
561
			IObservableList list, Object element, int index) {
562
		ListChangeEventTracker listener = new ListChangeEventTracker();
563
		list.addListChangeListener(listener);
564
514
565
		runnable.run();
515
		assertEquals(formatFail(methodName
516
				+ " did not leave observable list with the expected contents"),
517
				newList, list);
566
518
567
		ListDiffEntry[] entries = listener.event.diff.getDifferences();
519
		ListDiff diff = listListener.event.diff;
568
		assertEquals(methodName + " should result in one diff entry.", 1,
520
		diff.applyTo(oldList);
569
				entries.length);
570
571
		ListDiffEntry entry = entries[0];
572
		assertFalse(methodName
573
				+ " should result in a diff entry that is an removal.", entry
574
				.isAddition());
575
		assertEquals(methodName
576
				+ " remove diff entry should have removed the element.",
577
				element, entry.getElement());
578
		assertEquals(
521
		assertEquals(
579
				methodName
522
				formatFail(methodName
580
						+ " remove diff entry should have removed the element from the provided index.",
523
						+ " fired a diff which does not represent the expected list change"),
581
				index, entry.getPosition());
524
				newList, oldList);
582
	}
583
525
584
	/**
585
	 * Asserts the list diff entry for an add operation.
586
	 * 
587
	 * @param runnable
588
	 * @param methodName
589
	 * @param list
590
	 * @param element
591
	 * @param index
592
	 */
593
	private void assertAddDiffEntry(Runnable runnable, String methodName,
594
			IObservableList list, Object element, int index) {
595
		ListChangeEventTracker listener = new ListChangeEventTracker();
596
		list.addListChangeListener(listener);
597
598
		runnable.run();
599
600
		ListDiffEntry[] entries = listener.event.diff.getDifferences();
601
		assertEquals(methodName + " should result in one diff entry.", 1,
602
				entries.length);
603
604
		ListDiffEntry entry = entries[0];
605
		assertTrue(methodName
606
				+ " should result in a diff entry that is an addition.", entry
607
				.isAddition());
608
		assertEquals(methodName
609
				+ " add diff entry should have added the element.", element,
610
				entry.getElement());
611
		assertEquals(
612
				methodName
613
						+ "add diff entry should have added the element at the provided index.",
614
				index, entry.getPosition());
615
	}
526
	}
616
527
617
	public static Test suite(IObservableCollectionContractDelegate delegate) {
528
	public static Test suite(IObservableCollectionContractDelegate delegate) {

Return to bug 194734