1 | |
package com.sun.javafx.runtime.sequence; |
2 | |
|
3 | |
import com.sun.javafx.runtime.Util; |
4 | |
import com.sun.javafx.runtime.location.SequenceLocation; |
5 | |
import com.sun.javafx.runtime.location.SequenceChangeListener; |
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | 32 | public abstract class SimpleBoundComprehension<T, V> extends AbstractBoundSequence<V> implements SequenceLocation<V> { |
14 | |
private final SequenceLocation<T> sequenceLocation; |
15 | |
private final boolean dependsOnIndex; |
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
|
25 | |
|
26 | |
public SimpleBoundComprehension(Class<V> clazz, |
27 | |
SequenceLocation<T> sequenceLocation, |
28 | |
boolean dependsOnIndex) { |
29 | 5 | super(clazz); |
30 | 5 | this.sequenceLocation = sequenceLocation; |
31 | 5 | this.dependsOnIndex = dependsOnIndex; |
32 | 5 | setInitialValue(computeValue()); |
33 | 5 | addTriggers(); |
34 | 5 | } |
35 | |
|
36 | |
public SimpleBoundComprehension(Class<V> clazz, SequenceLocation<T> sequenceLocation) { |
37 | 0 | this(clazz, sequenceLocation, false); |
38 | 0 | } |
39 | |
|
40 | |
protected abstract V computeElement$(T element, int index); |
41 | |
|
42 | |
private Sequence<V> computeValue() { |
43 | 5 | Sequence<T> sequence = sequenceLocation.getAsSequence(); |
44 | 5 | V[] intermediateResults = Util.<V>newObjectArray(sequence.size()); |
45 | 20 | for (int i = 0; i < intermediateResults.length; i++) |
46 | 15 | intermediateResults[i] = computeElement$(sequence.get(i), i); |
47 | 5 | return Sequences.make(getClazz(), intermediateResults); |
48 | |
} |
49 | |
|
50 | |
private void addTriggers() { |
51 | 5 | sequenceLocation.addChangeListener(new SequenceChangeListener<T>() { |
52 | |
public void onChange(int startPos, int endPos, Sequence<? extends T> newElements, Sequence<T> oldValue, Sequence<T> newValue) { |
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | 18 | int directlyAffectedSize = Sequences.size(newElements); |
58 | 18 | int elementsAdded = directlyAffectedSize - (endPos - startPos + 1); |
59 | 18 | boolean updateTrailingElements = dependsOnIndex |
60 | |
&& (elementsAdded != 0) |
61 | |
&& (endPos + 1 < Sequences.size(oldValue)); |
62 | 18 | int indirectlyAffectedStart=0, indirectlyAffectedEnd=0, indirectlyAffectedSize=0; |
63 | 18 | if (updateTrailingElements) { |
64 | 3 | indirectlyAffectedStart = endPos + 1; |
65 | 3 | indirectlyAffectedEnd = oldValue.size() - 1; |
66 | 3 | indirectlyAffectedSize = indirectlyAffectedEnd - indirectlyAffectedStart + 1; |
67 | |
} |
68 | 18 | V[] ourNewElements = Util.<V>newObjectArray(directlyAffectedSize + indirectlyAffectedSize); |
69 | 32 | for (int i = 0; i < directlyAffectedSize; i++) |
70 | 14 | ourNewElements[i] = computeElement$(newElements.get(i), dependsOnIndex ? startPos + i : -1); |
71 | 26 | for (int i = 0; i < indirectlyAffectedSize; i++) |
72 | 8 | ourNewElements[directlyAffectedSize + i] |
73 | |
= computeElement$(oldValue.get(indirectlyAffectedStart + i), indirectlyAffectedStart + i + elementsAdded); |
74 | |
|
75 | 18 | Sequence<V> vSequence = Sequences.make(getClazz(), ourNewElements); |
76 | 18 | updateSlice(startPos, updateTrailingElements ? indirectlyAffectedEnd : endPos, vSequence); |
77 | 18 | } |
78 | |
}); |
79 | 5 | } |
80 | |
} |