@@ -84,7 +84,7 @@ public class SwingNumberWidget extends SwingInputWidget<Number> implements
84
84
@ Parameter
85
85
private LogService log ;
86
86
87
- private JScrollBar scrollBar ;
87
+ private CalibratedScrollBar scrollBar ;
88
88
private CalibratedSlider slider ;
89
89
private JSpinner spinner ;
90
90
@@ -116,6 +116,7 @@ else if (model.isStyle(NumberWidget.SLIDER_STYLE)) {
116
116
}
117
117
118
118
// add spinner widget
119
+ // TODO fix spinner size for integer min/max with double stepSize
119
120
final Class <?> type = model .getItem ().getType ();
120
121
final Number value = (Number ) model .getValue ();
121
122
final SpinnerNumberModel spinnerModel =
@@ -143,7 +144,7 @@ public boolean supports(final WidgetModel model) {
143
144
@ Override
144
145
public void adjustmentValueChanged (final AdjustmentEvent e ) {
145
146
// sync spinner with scroll bar value
146
- final int value = scrollBar .getValue ();
147
+ final Number value = scrollBar .getCalibratedValue ();
147
148
spinner .setValue (value );
148
149
}
149
150
@@ -184,14 +185,27 @@ private void addScrollBar(final Number min, final Number max,
184
185
log .warn ("Invalid min/max/step; cannot render scroll bar" );
185
186
return ;
186
187
}
188
+
189
+ int sMin = 0 ;
190
+ int sMax = (int ) ((max .doubleValue () - min .doubleValue ()) / step .doubleValue ());
191
+ long range = sMax - sMin ;
192
+ if (range > Integer .MAX_VALUE ) {
193
+ log .warn ("Scrollbar span too large; max - min < 2^31 required." );
194
+ return ;
195
+ }
196
+ /*
187
197
int mn = min.intValue();
188
198
if (mn == Integer.MIN_VALUE) mn = Integer.MIN_VALUE + 1;
189
199
int mx = max.intValue();
190
200
if (mx < Integer.MAX_VALUE) mx++;
191
201
final int st = step.intValue();
202
+ */
192
203
193
- scrollBar = new JScrollBar (Adjustable .HORIZONTAL , mn , 1 , mn , mx );
204
+ scrollBar = new CalibratedScrollBar (min , max , step );
205
+ /*
206
+ scrollBar = new JScrollBar(HORIZONTAL, mn, 1, mn, mx);
194
207
scrollBar.setUnitIncrement(st);
208
+ */
195
209
setToolTip (scrollBar );
196
210
getComponent ().add (scrollBar );
197
211
scrollBar .addAdjustmentListener (this );
@@ -316,12 +330,13 @@ private void syncSliders() {
316
330
}
317
331
if (scrollBar != null ) {
318
332
// clamp value within scroll bar bounds
319
- int value = getValue ().intValue ();
320
- if (value < scrollBar .getMinimum ()) value = scrollBar .getMinimum ();
321
- else if (value > scrollBar .getMaximum ()) value = scrollBar .getMaximum ();
333
+ Number value = getValue ().intValue ();
334
+ if (value . doubleValue () < scrollBar .getCalibratedMinimum (). doubleValue ()) value = scrollBar .getCalibratedMinimum ();
335
+ else if (value . doubleValue () > scrollBar .getCalibratedMaximum (). doubleValue ()) value = scrollBar .getCalibratedMaximum ();
322
336
scrollBar .removeAdjustmentListener (this );
323
- scrollBar .setValue ( getValue (). intValue () );
337
+ scrollBar .setCalibratedValue ( value );
324
338
scrollBar .addAdjustmentListener (this );
339
+ // TODO avoid snapping back to next floor integer when adjusting
325
340
}
326
341
}
327
342
@@ -421,4 +436,55 @@ private JLabel makeLabel(Number n, int scale) {
421
436
}
422
437
423
438
}
439
+
440
+ private class CalibratedScrollBar extends JScrollBar {
441
+
442
+ private Number min ;
443
+ private Number max ;
444
+ private Number stepSize ;
445
+
446
+ private CalibratedScrollBar (final Number min , final Number max , final Number stepSize ) {
447
+ // set extent to 1 to make sure the scroll bar is visible
448
+ super (HORIZONTAL , 0 , 1 , 0 , 1 );
449
+
450
+ this .min = min ;
451
+ this .max = max ;
452
+ this .stepSize = stepSize ;
453
+
454
+ int sMin = 0 ;
455
+ int sMax = (int ) ((max .doubleValue () - min .doubleValue ()) / stepSize .doubleValue ());
456
+
457
+ // Adjust max to be an integer multiple of stepSize
458
+ this .max = min .doubleValue () + (sMax -sMin ) * stepSize .doubleValue ();
459
+
460
+ setMinimum (sMin );
461
+ setMaximum (sMax );
462
+ setValue (sMin );
463
+ }
464
+
465
+ private void setCalibratedValue (Number value ) {
466
+ setValue (fromCalibrated (value ));
467
+ }
468
+
469
+ private Number getCalibratedValue () {
470
+ return toCalibrated (getValue ());
471
+ }
472
+
473
+ private Number getCalibratedMinimum () {
474
+ return min ;
475
+ }
476
+
477
+ private Number getCalibratedMaximum () {
478
+ return max ;
479
+ }
480
+
481
+ private int fromCalibrated (Number n ) {
482
+ return (int ) ((n .doubleValue () - min .doubleValue ()) / stepSize .doubleValue ());
483
+ }
484
+
485
+ private Number toCalibrated (int n ) {
486
+ return n * stepSize .doubleValue () + min .doubleValue ();
487
+ }
488
+
489
+ }
424
490
}
0 commit comments