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