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

Collapse All | Expand All

(-)META-INF/MANIFEST.MF (-1 / +3 lines)
Lines 19-24 Link Here
19
 org.eclipse.ui.browser;ui.workbench=split;mandatory:="ui.workbench",
19
 org.eclipse.ui.browser;ui.workbench=split;mandatory:="ui.workbench",
20
 org.eclipse.ui.commands,
20
 org.eclipse.ui.commands,
21
 org.eclipse.ui.contexts,
21
 org.eclipse.ui.contexts,
22
 org.eclipse.ui.databinding,
22
 org.eclipse.ui.dialogs;ui.workbench=split;mandatory:="ui.workbench",
23
 org.eclipse.ui.dialogs;ui.workbench=split;mandatory:="ui.workbench",
23
 org.eclipse.ui.dnd,
24
 org.eclipse.ui.dnd,
24
 org.eclipse.ui.fieldassist,
25
 org.eclipse.ui.fieldassist,
Lines 96-102 Link Here
96
 org.eclipse.swt;bundle-version="[3.3.0,4.0.0)",
97
 org.eclipse.swt;bundle-version="[3.3.0,4.0.0)",
97
 org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
98
 org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
98
 org.eclipse.jface.databinding;bundle-version="[1.1.0,2.0.0)",
99
 org.eclipse.jface.databinding;bundle-version="[1.1.0,2.0.0)",
99
 org.eclipse.core.databinding;bundle-version="[1.0.0,2.0.0)"
100
 org.eclipse.core.databinding.property;bundle-version="[1.2.0,2.0.0)",
101
 org.eclipse.core.databinding.observable;bundle-version="[1.2.0,2.0.0)"
100
Import-Package: com.ibm.icu.text,
102
Import-Package: com.ibm.icu.text,
101
 com.ibm.icu.util,
103
 com.ibm.icu.util,
102
 javax.xml.parsers,
104
 javax.xml.parsers,
(-)Eclipse (+103 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
 *     Matthew Hall - bugs 206839, 124684, 239302, 245647, 194734, 195222,
11
 *                    264286
12
 *******************************************************************************/
13
14
package org.eclipse.ui.databinding;
15
16
import org.eclipse.core.databinding.observable.Diffs;
17
import org.eclipse.core.databinding.observable.value.DecoratingObservableValue;
18
import org.eclipse.core.databinding.observable.value.IObservableValue;
19
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
20
import org.eclipse.core.runtime.Assert;
21
import org.eclipse.core.runtime.IAdapterManager;
22
import org.eclipse.core.runtime.Platform;
23
import org.eclipse.ui.ISelectionService;
24
import org.eclipse.ui.services.IServiceLocator;
25
26
/**
27
 * Factory methods for creating observables for JFace viewers
28
 * 
29
 * @since 3.5
30
 */
31
public class WorkbenchObservables {
32
33
	/**
34
	 * Returns an observable with values of the given target type. If the
35
	 * wrapped observable's value is of the target type, or can be adapted to
36
	 * the target type, this is taken as the value of the returned observable,
37
	 * otherwise <code>null</code>.
38
	 * 
39
	 * @param observable
40
	 *            the observable whose value should be adapted
41
	 * @param targetType
42
	 *            the target type
43
	 * @return an observable with values of the given type, or <code>null</code>
44
	 *         if the current value of the given observable does not adapt to
45
	 *         the target type
46
	 * 
47
	 */
48
	public static IObservableValue observeAdaptedValue(IObservableValue observable,
49
			final Class targetType) {
50
		final IAdapterManager adapterManager = Platform.getAdapterManager();
51
		return new DecoratingObservableValue(observable, false) {
52
			public Object getValue() {
53
				return adapted(super.getValue());
54
			}
55
56
			protected void handleValueChange(ValueChangeEvent event) {
57
				fireValueChange(Diffs.createValueDiff(adapted(event.diff.getOldValue()),
58
						adapted(event.diff.getNewValue())));
59
			}
60
61
			private Object adapted(Object object) {
62
				if (targetType.isInstance(object)) {
63
					return object;
64
				}
65
				return adapterManager.getAdapter(object, targetType);
66
			}
67
68
			public Object getValueType() {
69
				return targetType;
70
			}
71
		};
72
	}
73
74
	/**
75
	 * Returns an observable value that tracks the post selection of a selection
76
	 * service obtained through the given service locator, and adapts the first
77
	 * element of that selection to the given target type.
78
	 * <p>
79
	 * This method can be used by view or editor implementers to tie into the
80
	 * selection service, for example as follows:
81
	 * 
82
	 * <pre>
83
	 * IObservableValue selection = WorkbenchObservables.observeAdaptedSingleSelection(
84
	 * 		getSite(), IResource.class);
85
	 * </pre>
86
	 * 
87
	 * </p>
88
	 * 
89
	 * @param locator
90
	 *            a service locator with an available {@link ISelectionService}
91
	 * @param targetType
92
	 *            the target type
93
	 * @return an observable value whose value type is the given target type
94
	 */
95
	public static IObservableValue observeAdaptedSingleSelection(IServiceLocator locator,
96
			Class targetType) {
97
		ISelectionService selectionService = (ISelectionService) locator
98
				.getService(ISelectionService.class);
99
		Assert.isNotNull(selectionService);
100
		return observeAdaptedValue(WorkbenchProperties.singleSelection(null, true)
101
				.observe(selectionService), targetType);
102
	}
103
}
(-)Eclipse (+273 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
package org.eclipse.ui.databinding;
12
13
import java.util.ArrayList;
14
import java.util.Collections;
15
import java.util.List;
16
17
import org.eclipse.core.databinding.observable.list.ListDiff;
18
import org.eclipse.core.databinding.property.INativePropertyListener;
19
import org.eclipse.core.databinding.property.ISimplePropertyListener;
20
import org.eclipse.core.databinding.property.SimplePropertyEvent;
21
import org.eclipse.core.databinding.property.list.IListProperty;
22
import org.eclipse.core.databinding.property.list.SimpleListProperty;
23
import org.eclipse.core.databinding.property.value.IValueProperty;
24
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
25
import org.eclipse.jface.viewers.ISelection;
26
import org.eclipse.jface.viewers.IStructuredSelection;
27
import org.eclipse.ui.ISelectionListener;
28
import org.eclipse.ui.ISelectionService;
29
import org.eclipse.ui.IWorkbenchPart;
30
31
/**
32
 * Helper class for providing observables for the Workbench.
33
 * 
34
 * <p>
35
 * Examples:
36
 * 
37
 * <pre>
38
 * WorkbenchProperties.singleSelection().observe(
39
 * 		getSite().getService(ISelectionService.class))
40
 * </pre>
41
 * 
42
 * </p>
43
 * 
44
 * @since 3.5
45
 */
46
public class WorkbenchProperties {
47
48
	/**
49
	 * Returns a property for observing the first element of a structured
50
	 * selection as exposed by {@link ISelectionService}.
51
	 * 
52
	 * @return an observable value
53
	 */
54
	public static IValueProperty singleSelection() {
55
		return singleSelection(null, false);
56
	}
57
58
	/**
59
	 * Returns a property for observing the first element of a structured
60
	 * selection as exposed by {@link ISelectionService}.
61
	 * 
62
	 * @param partId
63
	 *            the part id, or <code>null</code> if the selection can be from
64
	 *            any part
65
	 * @param postSelection
66
	 *            <code>true</code> if the selection should be delayed for
67
	 *            keyboard-triggered selections
68
	 * 
69
	 * @return an observable value
70
	 */
71
	public static IValueProperty singleSelection(String partId, boolean postSelection) {
72
		return new SingleSelectionProperty(partId, postSelection);
73
	}
74
75
	/**
76
	 * Returns a property for observing the elements of a structured selection
77
	 * as exposed by {@link ISelectionService}.
78
	 * 
79
	 * @return an observable value
80
	 */
81
	public static IListProperty multipleSelection() {
82
		return multipleSelection(null, false);
83
	}
84
85
	/**
86
	 * Returns a property for observing the elements of a structured selection
87
	 * as exposed by {@link ISelectionService}.
88
	 * 
89
	 * @param partId
90
	 *            the part id, or <code>null</code> if the selection can be from
91
	 *            any part
92
	 * @param postSelection
93
	 *            <code>true</code> if the selection should be delayed for
94
	 *            keyboard-triggered selections
95
	 * 
96
	 * @return an observable value
97
	 */
98
	public static IListProperty multipleSelection(String partId, boolean postSelection) {
99
		return new MultiSelectionProperty(partId, postSelection);
100
	}
101
102
	static class SingleSelectionProperty extends SimpleValueProperty {
103
104
		private final String partId;
105
		private final boolean post;
106
107
		SingleSelectionProperty(String partId, boolean post) {
108
			this.partId = partId;
109
			this.post = post;
110
		}
111
112
		class SingleSelectionListener implements INativePropertyListener,
113
				ISelectionListener {
114
			private final ISimplePropertyListener wrapped;
115
116
			public SingleSelectionListener(ISimplePropertyListener wrapped) {
117
				this.wrapped = wrapped;
118
			}
119
120
			public void addTo(Object source) {
121
				if (post) {
122
					if (partId != null) {
123
						((ISelectionService) source).addPostSelectionListener(partId,
124
								this);
125
					} else {
126
						((ISelectionService) source).addPostSelectionListener(this);
127
					}
128
				} else {
129
					if (partId != null) {
130
						((ISelectionService) source).addSelectionListener(partId, this);
131
					} else {
132
						((ISelectionService) source).addSelectionListener(this);
133
					}
134
				}
135
			}
136
137
			public void removeFrom(Object source) {
138
				if (post) {
139
					if (partId != null) {
140
						((ISelectionService) source).removePostSelectionListener(partId,
141
								this);
142
					} else {
143
						((ISelectionService) source).removePostSelectionListener(this);
144
					}
145
				} else {
146
					if (partId != null) {
147
						((ISelectionService) source)
148
								.removeSelectionListener(partId, this);
149
					} else {
150
						((ISelectionService) source).removeSelectionListener(this);
151
					}
152
				}
153
			}
154
155
			public void selectionChanged(IWorkbenchPart part, ISelection selection) {
156
				wrapped.handleEvent(new SimplePropertyEvent(SimplePropertyEvent.CHANGE,
157
						null, SingleSelectionProperty.this, null));
158
			}
159
		}
160
161
		public INativePropertyListener adaptListener(ISimplePropertyListener listener) {
162
			return null;
163
		}
164
165
		protected Object doGetValue(Object source) {
166
			ISelection selection;
167
			if (partId != null) {
168
				selection = ((ISelectionService) source).getSelection(partId);
169
			} else {
170
				selection = ((ISelectionService) source).getSelection();
171
			}
172
			if (selection instanceof IStructuredSelection) {
173
				return ((IStructuredSelection) selection).getFirstElement();
174
			}
175
			return null;
176
		}
177
178
		protected void doSetValue(Object source, Object value) {
179
			throw new UnsupportedOperationException();
180
		}
181
182
		public Object getValueType() {
183
			return Object.class;
184
		}
185
186
	}
187
188
	static class MultiSelectionProperty extends SimpleListProperty {
189
190
		private final String partId;
191
		private final boolean post;
192
193
		MultiSelectionProperty(String partId, boolean post) {
194
			this.partId = partId;
195
			this.post = post;
196
		}
197
198
		class SingleSelectionListener implements INativePropertyListener,
199
				ISelectionListener {
200
			private final ISimplePropertyListener wrapped;
201
202
			public SingleSelectionListener(ISimplePropertyListener wrapped) {
203
				this.wrapped = wrapped;
204
			}
205
206
			public void addTo(Object source) {
207
				if (post) {
208
					if (partId != null) {
209
						((ISelectionService) source).addPostSelectionListener(partId,
210
								this);
211
					} else {
212
						((ISelectionService) source).addPostSelectionListener(this);
213
					}
214
				} else {
215
					if (partId != null) {
216
						((ISelectionService) source).addSelectionListener(partId, this);
217
					} else {
218
						((ISelectionService) source).addSelectionListener(this);
219
					}
220
				}
221
			}
222
223
			public void removeFrom(Object source) {
224
				if (post) {
225
					if (partId != null) {
226
						((ISelectionService) source).removePostSelectionListener(partId,
227
								this);
228
					} else {
229
						((ISelectionService) source).removePostSelectionListener(this);
230
					}
231
				} else {
232
					if (partId != null) {
233
						((ISelectionService) source)
234
								.removeSelectionListener(partId, this);
235
					} else {
236
						((ISelectionService) source).removeSelectionListener(this);
237
					}
238
				}
239
			}
240
241
			public void selectionChanged(IWorkbenchPart part, ISelection selection) {
242
				wrapped.handleEvent(new SimplePropertyEvent(SimplePropertyEvent.CHANGE,
243
						null, MultiSelectionProperty.this, null));
244
			}
245
		}
246
247
		public INativePropertyListener adaptListener(ISimplePropertyListener listener) {
248
			return null;
249
		}
250
251
		public Object getElementType() {
252
			return Object.class;
253
		}
254
255
		protected List doGetList(Object source) {
256
			ISelection selection;
257
			if (partId != null) {
258
				selection = ((ISelectionService) source).getSelection(partId);
259
			} else {
260
				selection = ((ISelectionService) source).getSelection();
261
			}
262
			if (selection instanceof IStructuredSelection) {
263
				return new ArrayList(((IStructuredSelection) selection).toList());
264
			}
265
			return Collections.EMPTY_LIST;
266
		}
267
268
		protected void doSetList(Object source, List list, ListDiff diff) {
269
			throw new UnsupportedOperationException();
270
		}
271
272
	}
273
}
(-)src/org/eclipse/core/databinding/observable/Observables.java (-11 / +39 lines)
Lines 32-38 Link Here
32
import org.eclipse.core.databinding.observable.set.ObservableSet;
32
import org.eclipse.core.databinding.observable.set.ObservableSet;
33
import org.eclipse.core.databinding.observable.value.DecoratingObservableValue;
33
import org.eclipse.core.databinding.observable.value.DecoratingObservableValue;
34
import org.eclipse.core.databinding.observable.value.IObservableValue;
34
import org.eclipse.core.databinding.observable.value.IObservableValue;
35
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
35
import org.eclipse.core.databinding.observable.value.IVetoableValue;
36
import org.eclipse.core.databinding.observable.value.IVetoableValue;
37
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
36
import org.eclipse.core.databinding.observable.value.ValueChangingEvent;
38
import org.eclipse.core.databinding.observable.value.ValueChangingEvent;
37
import org.eclipse.core.internal.databinding.observable.ConstantObservableValue;
39
import org.eclipse.core.internal.databinding.observable.ConstantObservableValue;
38
import org.eclipse.core.internal.databinding.observable.DelayedObservableValue;
40
import org.eclipse.core.internal.databinding.observable.DelayedObservableValue;
Lines 47-54 Link Here
47
import org.eclipse.core.runtime.Assert;
49
import org.eclipse.core.runtime.Assert;
48
50
49
/**
51
/**
50
 * Contains static methods to operate on or return
52
 * Contains static methods to operate on or return {@link IObservable
51
 * {@link IObservable Observables}.
53
 * Observables}.
52
 * 
54
 * 
53
 * @since 1.0
55
 * @since 1.0
54
 */
56
 */
Lines 395-401 Link Here
395
			public synchronized void addStaleListener(IStaleListener listener) {
397
			public synchronized void addStaleListener(IStaleListener listener) {
396
			}
398
			}
397
399
398
			public synchronized void addSetChangeListener(ISetChangeListener listener) {
400
			public synchronized void addSetChangeListener(
401
					ISetChangeListener listener) {
399
			}
402
			}
400
		};
403
		};
401
	}
404
	}
Lines 518-524 Link Here
518
			public synchronized void addStaleListener(IStaleListener listener) {
521
			public synchronized void addStaleListener(IStaleListener listener) {
519
			}
522
			}
520
523
521
			public synchronized void addListChangeListener(IListChangeListener listener) {
524
			public synchronized void addListChangeListener(
525
					IListChangeListener listener) {
522
			}
526
			}
523
		};
527
		};
524
	}
528
	}
Lines 555-561 Link Here
555
	 *         specified key in the given map
559
	 *         specified key in the given map
556
	 * @since 1.2
560
	 * @since 1.2
557
	 */
561
	 */
558
	public static IObservableValue observeMapEntry(IObservableMap map, Object key) {
562
	public static IObservableValue observeMapEntry(IObservableMap map,
563
			Object key) {
559
		return observeMapEntry(map, key, map.getValueType());
564
		return observeMapEntry(map, key, map.getValueType());
560
	}
565
	}
561
566
Lines 573-580 Link Here
573
	 * @param key
578
	 * @param key
574
	 *            the key identifying the map entry to track.
579
	 *            the key identifying the map entry to track.
575
	 * @param valueType
580
	 * @param valueType
576
	 *            the type of the value. May be <code>null</code>, meaning
581
	 *            the type of the value. May be <code>null</code>, meaning the
577
	 *            the value is untyped.
582
	 *            value is untyped.
578
	 * @return an observable value that tracks the value associated with the
583
	 * @return an observable value that tracks the value associated with the
579
	 *         specified key in the given map
584
	 *         specified key in the given map
580
	 * @since 1.1
585
	 * @since 1.1
Lines 594-601 Link Here
594
	 * @param map
599
	 * @param map
595
	 *            the observable map whose entry will be tracked.
600
	 *            the observable map whose entry will be tracked.
596
	 * @param valueType
601
	 * @param valueType
597
	 *            the type of the value. May be <code>null</code>, meaning
602
	 *            the type of the value. May be <code>null</code>, meaning the
598
	 *            the value is untyped.
603
	 *            value is untyped.
599
	 * @return a factory for creating observable values tracking the value of
604
	 * @return a factory for creating observable values tracking the value of
600
	 *         the observable map entry identified by a particular key object.
605
	 *         the observable map entry identified by a particular key object.
601
	 * @since 1.1
606
	 * @since 1.1
Lines 618-625 Link Here
618
	 * @param master
623
	 * @param master
619
	 *            the observable value that identifies which map entry to track.
624
	 *            the observable value that identifies which map entry to track.
620
	 * @param valueType
625
	 * @param valueType
621
	 *            the type of the value. May be <code>null</code>, meaning
626
	 *            the type of the value. May be <code>null</code>, meaning the
622
	 *            the value is untyped.
627
	 *            value is untyped.
623
	 * @return an observable value tracking the current value of the specified
628
	 * @return an observable value tracking the current value of the specified
624
	 *         key in the given map an observable value that tracks the current
629
	 *         key in the given map an observable value that tracks the current
625
	 *         value of the named property for the current value of the master
630
	 *         value of the named property for the current value of the master
Lines 631-634 Link Here
631
		return MasterDetailObservables.detailValue(master,
636
		return MasterDetailObservables.detailValue(master,
632
				mapEntryValueFactory(map, valueType), valueType);
637
				mapEntryValueFactory(map, valueType), valueType);
633
	}
638
	}
639
640
	/**
641
	 * Copies the current value of the source observable to the destination
642
	 * observable, and upon value change events fired by the source observable,
643
	 * updates the destination observable accordingly, until the source
644
	 * observable is disposed. This method assumes that both observables are on
645
	 * the same realm.
646
	 * 
647
	 * @param source
648
	 *            the source observable
649
	 * @param destination
650
	 *            the destination observable
651
	 * @since 1.2
652
	 */
653
	public static void pipe(IObservableValue source,
654
			final IObservableValue destination) {
655
		destination.setValue(source.getValue());
656
		source.addValueChangeListener(new IValueChangeListener() {
657
			public void handleValueChange(ValueChangeEvent event) {
658
				destination.setValue(event.diff.getNewValue());
659
			}
660
		});
661
	}
634
}
662
}

Return to bug 218884