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

Collapse All | Expand All

(-)src/org/eclipse/core/internal/databinding/observable/masterdetail/ListDetailObservableList.java (+168 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 Ovidio Mallo 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
 *     Ovidio Mallo - initial API and implementation (bug 175737)
10
 ******************************************************************************/
11
12
package org.eclipse.core.internal.databinding.observable.masterdetail;
13
14
import java.util.ArrayList;
15
import java.util.Collections;
16
import java.util.Iterator;
17
18
import org.eclipse.core.databinding.observable.Diffs;
19
import org.eclipse.core.databinding.observable.ObservableTracker;
20
import org.eclipse.core.databinding.observable.list.AbstractObservableList;
21
import org.eclipse.core.databinding.observable.list.IListChangeListener;
22
import org.eclipse.core.databinding.observable.list.IObservableList;
23
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
24
import org.eclipse.core.databinding.observable.list.ListDiff;
25
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
26
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
27
import org.eclipse.core.databinding.observable.value.IObservableValue;
28
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
29
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
30
31
/**
32
 *
33
 */
34
public class ListDetailObservableList extends AbstractObservableList {
35
36
	private IObservableList masterList;
37
38
	private IObservableFactory detailFactory;
39
40
	private Object detailType;
41
42
	private ArrayList detailList;
43
44
	private IListChangeListener masterListListener = new IListChangeListener() {
45
		public void handleListChange(ListChangeEvent event) {
46
			applyMasterListDiff(event.diff);
47
		}
48
	};
49
50
	private IValueChangeListener detailValueListener = new IValueChangeListener() {
51
		public void handleValueChange(ValueChangeEvent event) {
52
			handleDetailValueChange(event);
53
		}
54
	};
55
56
	/**
57
	 * 
58
	 * @param masterObservableList
59
	 * @param detailFactory
60
	 * @param detailType
61
	 */
62
	public ListDetailObservableList(IObservableList masterObservableList,
63
			IObservableFactory detailFactory, Object detailType) {
64
		super(masterObservableList.getRealm());
65
		this.masterList = masterObservableList;
66
		this.detailFactory = detailFactory;
67
		this.detailType = detailType;
68
		this.detailList = new ArrayList();
69
70
		masterObservableList.addListChangeListener(masterListListener);
71
72
		ListDiff initMasterDiff = Diffs.computeListDiff(Collections.EMPTY_LIST,
73
				masterObservableList);
74
		applyMasterListDiff(initMasterDiff);
75
	}
76
77
	private void applyMasterListDiff(ListDiff masterListDiff) {
78
		ListDiffEntry[] masterEntries = masterListDiff.getDifferences();
79
		ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length];
80
		for (int i = 0; i < masterEntries.length; i++) {
81
			ListDiffEntry masterEntry = masterEntries[i];
82
			int index = masterEntry.getPosition();
83
84
			Object detailValue;
85
			if (masterEntry.isAddition()) {
86
				// When adding a new master, we must create a new detail.
87
				Object masterElement = masterEntry.getElement();
88
				IObservableValue detail = (IObservableValue) detailFactory
89
						.createObservable(masterElement);
90
91
				// Perform the actual addition and add a value change listener.
92
				detailList.add(index, detail);
93
				detailValue = detail.getValue();
94
				detail.addValueChangeListener(detailValueListener);
95
			} else {
96
				// When removing an existing master, we remove and dispose the
97
				// corresponding detail.
98
				IObservableValue detail = (IObservableValue) detailList
99
						.remove(index);
100
				detailValue = detail.getValue();
101
				detail.dispose();
102
			}
103
104
			// Create the corresponding diff for the detail list.
105
			detailEntries[i] = Diffs.createListDiffEntry(index, masterEntry
106
					.isAddition(), detailValue);
107
		}
108
109
		// Fire a list change event with the adapted diffs on the detail list.
110
		fireListChange(Diffs.createListDiff(detailEntries));
111
	}
112
113
	private void handleDetailValueChange(ValueChangeEvent event) {
114
		IObservableValue detail = event.getObservableValue();
115
		for (int i = 0; i < detailList.size(); i++) {
116
			if (detailList.get(i) == detail) {
117
				Object oldValue = event.diff.getOldValue();
118
				Object newValue = event.diff.getNewValue();
119
120
				ListDiffEntry[] diffEntries = new ListDiffEntry[2];
121
				diffEntries[0] = Diffs.createListDiffEntry(i, false, oldValue);
122
				diffEntries[1] = Diffs.createListDiffEntry(i, true, newValue);
123
				fireListChange(Diffs.createListDiff(diffEntries));
124
				break;
125
			}
126
		}
127
	}
128
129
	protected int doGetSize() {
130
		return detailList.size();
131
	}
132
133
	public Object get(int index) {
134
		ObservableTracker.getterCalled(this);
135
		return ((IObservableValue) detailList.get(index)).getValue();
136
	}
137
138
	public Object set(int index, Object element) {
139
		IObservableValue detail = (IObservableValue) detailList.get(index);
140
		Object oldElement = detail.getValue();
141
		detail.setValue(element);
142
		return oldElement;
143
	}
144
145
	public Object getElementType() {
146
		return detailType;
147
	}
148
149
	public synchronized void dispose() {
150
		if (masterList != null) {
151
			masterList.removeListChangeListener(masterListListener);
152
		}
153
154
		if (detailList != null) {
155
			for (Iterator iter = detailList.iterator(); iter.hasNext();) {
156
				((IObservableValue) iter.next()).dispose();
157
			}
158
		}
159
160
		masterList = null;
161
		detailFactory = null;
162
		detailType = null;
163
		masterListListener = null;
164
		detailValueListener = null;
165
166
		super.dispose();
167
	}
168
}

Return to bug 175737