Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/HighPrecisionJScrollBar.java
41161 views
1
/*
2
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
package sun.jvm.hotspot.ui;
26
27
import java.awt.event.*;
28
import javax.swing.*;
29
import javax.swing.event.*;
30
import java.math.*;
31
import java.util.*;
32
33
/** A JScrollBar which uses BigIntegers as the representation for the
34
minimum, maximum, unit increment, etc. Interaction with the
35
buttons and track is accurate to unit and block increments;
36
however, if the scale of the scrollbar (defined by
37
getMaximumHP().subtract(getMinimumHP())) is very large, each
38
interaction with the thumb will necessarily cause extremely large
39
motion of the value. */
40
41
public class HighPrecisionJScrollBar extends JScrollBar {
42
private BigInteger valueHP;
43
private BigInteger visibleHP;
44
private BigInteger minimumHP;
45
private BigInteger maximumHP;
46
private BigInteger unitIncrementHP;
47
private BigInteger blockIncrementHP;
48
private BigDecimal scaleFactor;
49
private BigInteger rangeHP;
50
// The underlying scrollbar runs a range from 0..BIG_RANGE-1
51
private static final int BIG_RANGE = 10000;
52
// Do we need to scale HP values up/down to fit in 0..BIG_RANGE-1?
53
private boolean down;
54
private java.util.List<ChangeListener> changeListeners = new ArrayList<>();
55
// Number of digits after decimal point to use when scaling between
56
// high and low precision
57
private static final int SCALE = 20;
58
59
60
// This is a hack to allow us to differentiate between clicks on the
61
// arrow and track since we can't get useful information from
62
// JScrollBars' AdjustmentListener (bug in design of BasicUI
63
// classes; FIXME: file RFE.)
64
private static final int UNIT_INCREMENT = 1;
65
private static final int BLOCK_INCREMENT = 2;
66
private static final int MINIMUM = 0;
67
private static final int MAXIMUM = 65536;
68
private boolean updating = false;
69
private int lastValueSeen = -1;
70
71
public HighPrecisionJScrollBar() {
72
super();
73
initialize();
74
installListener();
75
}
76
77
public HighPrecisionJScrollBar(int orientation) {
78
super(orientation);
79
initialize();
80
installListener();
81
}
82
83
/** value, minimum and maximum should be positive */
84
public HighPrecisionJScrollBar(int orientation, BigInteger value, BigInteger minimum, BigInteger maximum) {
85
super(orientation);
86
initialize(value, minimum, maximum);
87
installListener();
88
}
89
90
public BigInteger getValueHP() {
91
return valueHP;
92
}
93
94
95
/** NOTE: the real value will always be set to be (value mod
96
unitIncrement) == 0, subtracting off the mod of the passed value
97
if necessary. */
98
99
public void setValueHP(BigInteger value) {
100
if (value.compareTo(getMaximumHP()) > 0) {
101
value = getMaximumHP();
102
} else if (value.compareTo(getMinimumHP()) < 0) {
103
value = getMinimumHP();
104
}
105
valueHP = value.subtract(value.mod(unitIncrementHP));
106
int lpValue = toUnderlyingRange(this.valueHP);
107
if (getValueHP().add(getVisibleAmountHP()).compareTo(getMaximumHP()) >= 0 ) {
108
lpValue = BIG_RANGE - getVisibleAmount();
109
}
110
lastValueSeen = lpValue;
111
setValue(lpValue);
112
fireStateChanged();
113
}
114
public BigInteger getMinimumHP() {
115
return minimumHP;
116
}
117
118
public void setMinimumHP(BigInteger minimum) {
119
setRange(minimum, maximumHP);
120
updateScrollBarValues();
121
}
122
123
public BigInteger getMaximumHP() {
124
return maximumHP;
125
}
126
127
public void setMaximumHP(BigInteger maximum) {
128
setRange(minimumHP, maximum);
129
updateScrollBarValues();
130
}
131
132
public BigInteger getVisibleAmountHP() {
133
return visibleHP;
134
}
135
136
public void setVisibleAmountHP(BigInteger visibleAmount) {
137
this.visibleHP = visibleAmount;
138
// int lpVisAmt = toUnderlyingRange(visibleAmount);
139
// Make certain that visibleAmount value that are full range come out looking like full range
140
int lpVisAmt;
141
if (visibleAmount.compareTo(rangeHP) < 0) {
142
lpVisAmt = scaleToUnderlying(visibleAmount);
143
if (lpVisAmt == 0) {
144
lpVisAmt = 1;
145
}
146
setVisible(true);
147
} else {
148
lpVisAmt = BIG_RANGE;
149
setVisible(false);
150
}
151
setVisibleAmount(lpVisAmt);
152
}
153
154
public BigInteger getBlockIncrementHP() {
155
return blockIncrementHP;
156
}
157
158
public void setBlockIncrementHP(BigInteger blockIncrement) {
159
this.blockIncrementHP = blockIncrement;
160
// NOTE we do not forward this to the underlying scrollBar because of
161
// the earlier mentioned hack.
162
}
163
164
public BigInteger getUnitIncrementHP() {
165
return unitIncrementHP;
166
}
167
168
public void setUnitIncrementHP(BigInteger unitIncrement) {
169
this.unitIncrementHP = unitIncrement;
170
// NOTE we do not forward this to the underlying scrollBar because of
171
// the earlier mentioned hack.
172
}
173
174
175
public void addChangeListener(ChangeListener l) {
176
changeListeners.add(l);
177
}
178
179
public void removeChangeListener(ChangeListener l) {
180
changeListeners.remove(l);
181
}
182
183
//----------------------------------------------------------------------
184
// Programmatic access to scrollbar functionality
185
// (Causes change events to be sent)
186
187
public void scrollUpOrLeft() {
188
if (updating) return;
189
beginUpdate();
190
setValueHP(getValueHP().subtract(getUnitIncrementHP()));
191
endUpdate();
192
}
193
194
public void scrollDownOrRight() {
195
if (updating) return;
196
beginUpdate();
197
setValueHP(getValueHP().add(getUnitIncrementHP()));
198
endUpdate();
199
}
200
201
public void pageUpOrLeft() {
202
if (updating) return;
203
beginUpdate();
204
setValueHP(getValueHP().subtract(getBlockIncrementHP()));
205
endUpdate();
206
}
207
208
public void pageDownOrRight() {
209
if (updating) return;
210
beginUpdate();
211
setValueHP(getValueHP().add(getBlockIncrementHP()));
212
endUpdate();
213
}
214
215
//----------------------------------------------------------------------
216
// Internals only below this point
217
//
218
219
private void beginUpdate() {
220
updating = true;
221
}
222
223
private void endUpdate() {
224
updating = false;
225
}
226
227
private void initialize(BigInteger value, BigInteger minimum, BigInteger maximum) {
228
// Initialize the underlying scrollbar to the standard range values
229
// The increments are important and are how we differentiate arrow from track events
230
setMinimum(0);
231
setMaximum(BIG_RANGE - 1);
232
setValue(0);
233
setVisibleAmount(1);
234
setUnitIncrement(UNIT_INCREMENT);
235
setBlockIncrement(BLOCK_INCREMENT);
236
237
setUnitIncrementHP(new BigInteger(Integer.toString(getUnitIncrement())));
238
setBlockIncrementHP(new BigInteger(Integer.toString(getBlockIncrement())));
239
240
// Must set range and value first (it sets min/max)
241
setRange(minimum, maximum);
242
243
setVisibleAmountHP(new BigInteger(Integer.toString(getVisibleAmount())));
244
setValueHP(value);
245
}
246
247
private void initialize() {
248
BigInteger min = new BigInteger(Integer.toString(getMinimum()));
249
BigInteger max = new BigInteger(Integer.toString(getMaximum()));
250
initialize(min, min, max);
251
}
252
253
private void setRange(BigInteger minimum, BigInteger maximum) {
254
if (minimum.compareTo(maximum) > 0 ) {
255
throw new RuntimeException("Bad scrollbar range " + minimum + " > " + maximum);
256
}
257
minimumHP = minimum;
258
maximumHP = maximum;
259
rangeHP = maximum.subtract(minimum).add(BigInteger.ONE);
260
BigInteger range2 = new BigInteger(Integer.toString(BIG_RANGE));
261
if (rangeHP.compareTo(range2) >= 0 ) {
262
down = true;
263
scaleFactor = new BigDecimal(rangeHP, SCALE).divide(new BigDecimal(range2, SCALE), RoundingMode.DOWN).max(new BigDecimal(BigInteger.ONE));
264
} else {
265
down = false;
266
scaleFactor = new BigDecimal(range2, SCALE).divide(new BigDecimal(rangeHP, SCALE), RoundingMode.DOWN).max(new BigDecimal(BigInteger.ONE));
267
}
268
// FIXME: should put in original scaling algorithm (shifting by
269
// number of bits) as alternative when scale between low and high
270
// precision is very large
271
}
272
273
// A range update is complete. Rescale our computed values and
274
// inform the underlying scrollBar as needed.
275
private void updateScrollBarValues() {
276
setValueHP(getValueHP());
277
setVisibleAmountHP(getVisibleAmountHP());
278
setBlockIncrementHP(getBlockIncrementHP());
279
setUnitIncrementHP(getUnitIncrementHP());
280
}
281
282
private BigDecimal getScaleFactor() {
283
return scaleFactor;
284
}
285
286
287
// Value scaling routines
288
private BigInteger scaleToHP(int i) {
289
BigDecimal ib = new BigDecimal(Integer.toString(i));
290
if (down) return ib.multiply(getScaleFactor()).toBigInteger();
291
else return ib.divide(getScaleFactor(), RoundingMode.DOWN).toBigInteger();
292
}
293
294
private int scaleToUnderlying(BigInteger i) {
295
BigDecimal d = new BigDecimal(i);
296
if (down) return d.divide(getScaleFactor(), RoundingMode.DOWN).intValue();
297
else return d.multiply(getScaleFactor()).intValue();
298
}
299
300
// Range scaling routines
301
private BigInteger toHPRange(int i) {
302
return scaleToHP(i).add(minimumHP);
303
// return ib.shiftLeft(Math.max(2, maximumHP.bitLength() - 33));
304
}
305
306
private int toUnderlyingRange(BigInteger i) {
307
return scaleToUnderlying(i.subtract(minimumHP));
308
// return i.shiftRight(Math.max(2, maximumHP.bitLength() - 33)).intValue();
309
}
310
311
private void installListener() {
312
super.addAdjustmentListener(new AdjustmentListener() {
313
public void adjustmentValueChanged(AdjustmentEvent e) {
314
if (updating) {
315
return;
316
}
317
beginUpdate();
318
switch (e.getAdjustmentType()) {
319
case AdjustmentEvent.TRACK:
320
int val = e.getValue();
321
int diff = val - lastValueSeen;
322
int absDiff = Math.abs(diff);
323
// System.err.println("diff: " + diff + " absDiff: " + absDiff);
324
if (absDiff == UNIT_INCREMENT) {
325
if (diff > 0) {
326
// System.err.println("case 1");
327
setValueHP(getValueHP().add(getUnitIncrementHP()));
328
} else {
329
// System.err.println("case 2");
330
setValueHP(getValueHP().subtract(getUnitIncrementHP()));
331
}
332
} else if (absDiff == BLOCK_INCREMENT) {
333
if (diff > 0) {
334
// System.err.println("case 3");
335
setValueHP(getValueHP().add(getBlockIncrementHP()));
336
} else {
337
// System.err.println("case 4");
338
setValueHP(getValueHP().subtract(getBlockIncrementHP()));
339
}
340
} else {
341
// System.err.println("case 5");
342
// FIXME: seem to be getting spurious update events,
343
// with diff = 0, upon mouse down/up on the track
344
if (absDiff != 0) {
345
// Convert low-precision value to high precision
346
// (note we lose the low bits)
347
BigInteger i = null;
348
if (e.getValue() == getMinimum()) {
349
i = getMinimumHP();
350
} else if (e.getValue() >= getMaximum() - 1) {
351
i = getMaximumHP();
352
} else {
353
i = toHPRange(e.getValue());
354
}
355
setValueHP(i);
356
}
357
}
358
break;
359
default:
360
// Should not reach here, but leaving it a no-op in case
361
// we later get the other events (should revisit code in
362
// that case)
363
break;
364
}
365
endUpdate();
366
}
367
});
368
}
369
370
private void fireStateChanged() {
371
ChangeEvent e = null;
372
for (Iterator iter = changeListeners.iterator(); iter.hasNext(); ) {
373
ChangeListener l = (ChangeListener) iter.next();
374
if (e == null) {
375
e = new ChangeEvent(this);
376
}
377
l.stateChanged(e);
378
}
379
}
380
381
public static void main(String[] args) {
382
JFrame frame = new JFrame();
383
frame.setSize(300, 300);
384
// 32-bit version
385
/*
386
HighPrecisionJScrollBar hpsb =
387
new HighPrecisionJScrollBar(
388
JScrollBar.VERTICAL,
389
new BigInteger(1, new byte[] {
390
(byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
391
new BigInteger(1, new byte[] {
392
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
393
new BigInteger(1, new byte[] {
394
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}));
395
hpsb.setUnitIncrementHP(new BigInteger(1, new byte[] {
396
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01}));
397
hpsb.setBlockIncrementHP(new BigInteger(1, new byte[] {
398
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x10}));
399
*/
400
401
// 64-bit version
402
HighPrecisionJScrollBar hpsb =
403
new HighPrecisionJScrollBar(
404
JScrollBar.VERTICAL,
405
new BigInteger(1, new byte[] {
406
(byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00,
407
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
408
new BigInteger(1, new byte[] {
409
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
410
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
411
new BigInteger(1, new byte[] {
412
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
413
(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}));
414
hpsb.setUnitIncrementHP(new BigInteger(1, new byte[] {
415
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
416
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01}));
417
hpsb.setBlockIncrementHP(new BigInteger(1, new byte[] {
418
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
419
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x10}));
420
hpsb.addChangeListener(new ChangeListener() {
421
public void stateChanged(ChangeEvent e) {
422
HighPrecisionJScrollBar h = (HighPrecisionJScrollBar) e.getSource();
423
System.out.println("New value = 0x" + h.getValueHP().toString(16));
424
}
425
});
426
frame.getContentPane().add(hpsb);
427
frame.setVisible(true);
428
}
429
430
}
431
432