1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
|
25 | |
|
26 | |
package com.sun.javafx.runtime.sequence; |
27 | |
|
28 | |
import com.sun.javafx.runtime.location.*; |
29 | |
|
30 | |
|
31 | |
|
32 | |
|
33 | |
|
34 | |
|
35 | 611 | public class BoundIntRangeSequence extends AbstractBoundSequence<Integer> implements SequenceLocation<Integer> { |
36 | |
|
37 | |
private final IntLocation lowerLoc, upperLoc, stepLoc; |
38 | |
private final boolean exclusive; |
39 | |
private int lower, upper, size, step; |
40 | |
|
41 | |
public BoundIntRangeSequence(IntLocation lowerLoc, IntLocation upperLoc) { |
42 | 34 | this(lowerLoc, upperLoc, IntConstant.make(1), false); |
43 | 34 | } |
44 | |
|
45 | |
public BoundIntRangeSequence(IntLocation lowerLoc, IntLocation upperLoc, IntLocation stepLoc) { |
46 | 6 | this(lowerLoc, upperLoc, stepLoc, false); |
47 | 6 | } |
48 | |
|
49 | |
public BoundIntRangeSequence(IntLocation lowerLoc, IntLocation upperLoc, boolean exclusive) { |
50 | 4 | this(lowerLoc, upperLoc, IntConstant.make(1), exclusive); |
51 | 4 | } |
52 | |
|
53 | |
public BoundIntRangeSequence(IntLocation lowerLoc, IntLocation upperLoc, IntLocation stepLoc, boolean exclusive) { |
54 | 49 | super(Integer.class); |
55 | 49 | this.lowerLoc = lowerLoc; |
56 | 49 | this.upperLoc = upperLoc; |
57 | 49 | this.stepLoc = stepLoc; |
58 | 49 | this.exclusive = exclusive; |
59 | 49 | setInitialValue(computeValue()); |
60 | 49 | addTriggers(); |
61 | 49 | } |
62 | |
|
63 | |
private Sequence<Integer> computeValue() { |
64 | 49 | computeBounds(lowerLoc.get(), upperLoc.get(), stepLoc.get()); |
65 | 49 | return computeFull(lower, upper, step); |
66 | |
} |
67 | |
|
68 | |
private Sequence<Integer> computeFull(int lower, int upper, int step) { |
69 | 83 | return exclusive ? Sequences.rangeExclusive(lower, upper, step) : Sequences.range(lower, upper, step); |
70 | |
} |
71 | |
|
72 | |
private void computeBounds(int newLower, int newUpper, int newStep) { |
73 | 119 | lower = newLower; |
74 | 119 | upper = newUpper; |
75 | 119 | step = newStep; |
76 | |
|
77 | 119 | if (Math.abs((long) newLower - (long) newUpper) + ((long) (exclusive ? 0 : 1) / step) > Integer.MAX_VALUE) |
78 | 0 | throw new IllegalArgumentException("Range sequence too big"); |
79 | |
|
80 | 119 | if (lower == upper) { |
81 | 2 | size = exclusive ? 0 : 1; |
82 | |
} |
83 | |
else { |
84 | 117 | size = Math.max(0, ((upper - lower) / step) + 1); |
85 | |
|
86 | 117 | if (exclusive) { |
87 | 28 | boolean tooBig = (step > 0) |
88 | |
? (lower + (size - 1) * step >= upper) |
89 | |
: (lower + (size - 1) * step <= upper); |
90 | 28 | if (tooBig && size > 0) |
91 | 13 | --size; |
92 | |
} |
93 | |
} |
94 | 119 | } |
95 | |
|
96 | |
private void addTriggers() { |
97 | 49 | lowerLoc.addChangeListener(new IntChangeListener() { |
98 | |
public void onChange(int oldValue, int newValue) { |
99 | |
|
100 | 23 | assert oldValue != newValue; |
101 | |
|
102 | 23 | int oldSize = size; |
103 | 23 | computeBounds(newValue, upper, step); |
104 | |
Sequence<Integer> newElements; |
105 | |
|
106 | 23 | if (oldSize == 0) { |
107 | 2 | updateSlice(0, -1, computeFull(lower, upper, step)); |
108 | |
} |
109 | 21 | else if (oldSize < size) { |
110 | |
|
111 | 5 | if (((newValue - oldValue) % step) == 0) { |
112 | 5 | updateSlice(0, -1, Sequences.rangeExclusive(lower, oldValue, step)); |
113 | |
} |
114 | |
else { |
115 | 0 | newElements = computeFull(lower, upper, step); |
116 | 0 | updateSlice(0, newElements.isEmpty() ? 0 : (size - 1), newElements, newElements); |
117 | |
} |
118 | |
} |
119 | 16 | else if (oldSize >= size) { |
120 | 16 | if (((newValue - oldValue) % step) == 0) { |
121 | 10 | updateSlice(0, oldSize - size - 1, Sequences.emptySequence(Integer.class)); |
122 | |
} |
123 | |
else { |
124 | 6 | newElements = computeFull(lower, upper, step); |
125 | 6 | updateSlice(0, newElements.isEmpty() ? 0 : (size - 1), newElements, newElements); |
126 | |
} |
127 | |
} |
128 | 23 | } |
129 | |
}); |
130 | 49 | upperLoc.addChangeListener(new IntChangeListener() { |
131 | |
public void onChange(int oldValue, int newValue) { |
132 | |
|
133 | 37 | assert oldValue != newValue; |
134 | |
|
135 | 37 | int oldSize = size; |
136 | 37 | computeBounds(lower, newValue, step); |
137 | |
|
138 | 37 | if (size == oldSize) { |
139 | 1 | return; |
140 | |
} |
141 | 36 | else if (oldSize == 0) { |
142 | 8 | updateSlice(0, -1, computeFull(lower, upper, step)); |
143 | |
} |
144 | 28 | else if (oldSize < size) { |
145 | 8 | int startPos = lower + oldSize * step; |
146 | 8 | updateSlice(oldSize, oldSize - 1, computeFull(startPos, upper, step)); |
147 | 8 | } |
148 | 20 | else if (oldSize > size) { |
149 | 20 | updateSlice(size, oldSize - 1, Sequences.emptySequence(Integer.class)); |
150 | |
} |
151 | 36 | } |
152 | |
}); |
153 | |
|
154 | 49 | stepLoc.addChangeListener(new IntChangeListener() { |
155 | |
public void onChange(int oldValue, int newValue) { |
156 | |
|
157 | 10 | assert oldValue != newValue; |
158 | |
|
159 | 10 | int oldSize = size; |
160 | 10 | computeBounds(lower, upper, newValue); |
161 | |
|
162 | 10 | Sequence<Integer> newSeq = computeFull(lower, upper, step); |
163 | 10 | updateSlice(0, oldSize - 1, newSeq, newSeq); |
164 | 10 | } |
165 | |
}); |
166 | 49 | } |
167 | |
} |