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 |
} |