1 | package geniusweb.domaineditor.model;
|
---|
2 |
|
---|
3 | import java.math.BigDecimal;
|
---|
4 | import java.util.HashMap;
|
---|
5 | import java.util.Map;
|
---|
6 |
|
---|
7 | import geniusweb.issuevalue.NumberValueSet;
|
---|
8 | import geniusweb.issuevalue.ValueSet;
|
---|
9 | import tudelft.utilities.immutablelist.Range;
|
---|
10 | import tudelft.utilities.listener.DefaultListenable;
|
---|
11 | import tudelft.utilities.logging.Reporter;
|
---|
12 | import tudelft.utilities.mvc.model.BasicModel;
|
---|
13 | import tudelft.utilities.mvc.model.ListModel;
|
---|
14 | import tudelft.utilities.mvc.model.NumberModel;
|
---|
15 | import tudelft.utilities.mvc.model.events.Changed;
|
---|
16 | import tudelft.utilities.mvc.model.events.Event;
|
---|
17 |
|
---|
18 | /**
|
---|
19 | * Model for a {@link NumberValueSet}
|
---|
20 | *
|
---|
21 | */
|
---|
22 | public class NumberValueSetModel extends DefaultListenable<Event>
|
---|
23 | implements ValueSetModel {
|
---|
24 |
|
---|
25 | private final NumberModel low, high, step;
|
---|
26 | protected final Reporter log;
|
---|
27 |
|
---|
28 | public NumberValueSetModel(NumberModel lowv, NumberModel highv,
|
---|
29 | NumberModel stepv, Reporter log) {
|
---|
30 | this.low = lowv;
|
---|
31 | this.high = highv;
|
---|
32 | this.step = stepv;
|
---|
33 | this.log = log;
|
---|
34 |
|
---|
35 | check();
|
---|
36 |
|
---|
37 | // 'this' refers to surrounding class inside lambda.
|
---|
38 | low.addListener((e) -> check());
|
---|
39 | high.addListener((e) -> check());
|
---|
40 | step.addListener((e) -> check());
|
---|
41 | }
|
---|
42 |
|
---|
43 | private void check() throws IllegalStateException {
|
---|
44 | if (low.getValue().compareTo(high.getValue()) > 0)
|
---|
45 | throw new IllegalStateException("low must be <= high");
|
---|
46 | if (step.getValue().compareTo(BigDecimal.ZERO) <= 0)
|
---|
47 | throw new IllegalStateException("step must be >0");
|
---|
48 | notifyListeners(new Changed(this, null));
|
---|
49 | }
|
---|
50 |
|
---|
51 | /*
|
---|
52 | * Default, bit arbitrary values.
|
---|
53 | */
|
---|
54 | public NumberValueSetModel(Reporter log) {
|
---|
55 | this(new NumberModel(BigDecimal.ZERO, log),
|
---|
56 | new NumberModel(BigDecimal.TEN, log),
|
---|
57 | new NumberModel(BigDecimal.ONE, log), log);
|
---|
58 | }
|
---|
59 |
|
---|
60 | @Override
|
---|
61 | public String toString() {
|
---|
62 | return "(" + low + high + step + ")";
|
---|
63 | }
|
---|
64 |
|
---|
65 | public NumberModel getLow() {
|
---|
66 | return low;
|
---|
67 | }
|
---|
68 |
|
---|
69 | public NumberModel getHigh() {
|
---|
70 | return high;
|
---|
71 |
|
---|
72 | }
|
---|
73 |
|
---|
74 | public NumberModel getStep() {
|
---|
75 | return step;
|
---|
76 | }
|
---|
77 |
|
---|
78 | @Override
|
---|
79 | public BasicModel first() {
|
---|
80 | return low;
|
---|
81 | }
|
---|
82 |
|
---|
83 | @Override
|
---|
84 | public ListModel getList() {
|
---|
85 | /**
|
---|
86 | * Return a ListModel backed up by the original set. It contains the
|
---|
87 | * possible values in the range.
|
---|
88 | */
|
---|
89 | return new MyListModel(this);
|
---|
90 | }
|
---|
91 |
|
---|
92 | @Override
|
---|
93 | public NumberValueSet getCurrentValue() throws IllegalStateException {
|
---|
94 | return new NumberValueSet(
|
---|
95 | new Range(low.getValue(), high.getValue(), step.getValue()));
|
---|
96 | }
|
---|
97 |
|
---|
98 | @Override
|
---|
99 | public void setCurrentValue(ValueSet obj) throws IllegalArgumentException {
|
---|
100 | if (!(obj instanceof NumberValueSet))
|
---|
101 | throw new IllegalArgumentException(
|
---|
102 | "Argument must be a NumberValueSet but got " + obj);
|
---|
103 | NumberValueSet nv = (NumberValueSet) obj;
|
---|
104 | // order of change is important, avoiding illegal ranges:
|
---|
105 | // if low must be increased, change high first.
|
---|
106 | // if high must be decreased, change low first.
|
---|
107 | // otherwise the change order is irrelevant.
|
---|
108 | if (nv.getRange().getLow().compareTo(low.getValue()) > 0) {
|
---|
109 | high.setValue(nv.getRange().getHigh());
|
---|
110 | low.setValue(nv.getRange().getLow());
|
---|
111 | } else {
|
---|
112 | low.setValue(nv.getRange().getLow());
|
---|
113 | high.setValue(nv.getRange().getHigh());
|
---|
114 | }
|
---|
115 | step.setValue(nv.getRange().getStep());
|
---|
116 | }
|
---|
117 |
|
---|
118 | }
|
---|
119 |
|
---|
120 | /**
|
---|
121 | * A ListModel view of this object. Editing is not supported.
|
---|
122 | *
|
---|
123 | */
|
---|
124 | class MyListModel extends DefaultListenable<Event>
|
---|
125 | implements ListModel<NumberModel> {
|
---|
126 |
|
---|
127 | private NumberValueSetModel numvalset;
|
---|
128 | /**
|
---|
129 | * A "cache" Map with the actual values from the range. Although
|
---|
130 | * NumberModels, they really should not be edited. This map ensures we
|
---|
131 | * return the SAME NumberModel every time a value from the range is
|
---|
132 | * selected.
|
---|
133 | */
|
---|
134 | private final transient Map<BigDecimal, NumberModel> itemsCache = new HashMap<>();
|
---|
135 |
|
---|
136 | public MyListModel(NumberValueSetModel valset) {
|
---|
137 | this.numvalset = valset;
|
---|
138 | valset.addListener((e) -> notifyListeners(e));
|
---|
139 | }
|
---|
140 |
|
---|
141 | @Override
|
---|
142 | public NumberModel get(int n) {
|
---|
143 | BigDecimal val = numvalset.getCurrentValue().getRange().get(n);
|
---|
144 | if (!itemsCache.containsKey(val))
|
---|
145 | itemsCache.put(val, new NumberModel(val, numvalset.log));
|
---|
146 | return itemsCache.get(val);
|
---|
147 | }
|
---|
148 |
|
---|
149 | @Override
|
---|
150 | public int getSize() {
|
---|
151 | return numvalset.getCurrentValue().getRange().size().intValue();
|
---|
152 | }
|
---|
153 |
|
---|
154 | @Override
|
---|
155 | public void remove(NumberModel value) {
|
---|
156 | throw new UnsupportedOperationException();
|
---|
157 | }
|
---|
158 |
|
---|
159 | @Override
|
---|
160 | public void add(NumberModel value) {
|
---|
161 | throw new UnsupportedOperationException();
|
---|
162 | }
|
---|
163 |
|
---|
164 | @Override
|
---|
165 | public boolean contains(Object o) {
|
---|
166 | return o instanceof NumberModel && numvalset.getCurrentValue()
|
---|
167 | .getRange().contains(((NumberModel) o).getValue());
|
---|
168 | }
|
---|
169 |
|
---|
170 | }
|
---|