sclass JTargetAndActualSlider extends MetaWithChangeListeners is Swingable { new TargetAndActual data; settableWithVar bool sliderEnabled = true; settableWithVar double min; settableWithVar double max = 100; settableWithVar int decimalsToShow = 1; settableWithVar int widthOfNumbers = 50; transient JColorBar bar; transient JSlider slider; transient JLabel lblActual, lblTarget; *() {} *(TargetAndActual *data) {} double value() { ret unnull(data.value()); } double target() { ret unnull(data.target()); } cachedVisualize { bar = swing(-> new JColorBar().max(max)); slider = jLiveValueSlider_double_bothWays(min, max, data.varTarget()); lblActual = jlabel(); lblTarget = jlabel(); data.varActual().onChangeAndNow(-> { bar.setValue(value()); setText(lblActual, renderValue(value())); }); data.varTarget().onChangeAndNow(-> { //slider.setValue(target()); setText(lblTarget, renderValue(target())); }); varSliderEnabled().onChangeAndNow(-> setEnabled(slider, sliderEnabled)); ret vstackWithSpacing( westCenterAndEastWithMargin(jlabel("Actual:"), bar, jMinWidth(widthOfNumbers, lblActual)), westCenterAndEastWithMargin(jlabel("Target:"), slider, jMinWidth(widthOfNumbers, lblTarget))); } swappable S renderValue(double value) { ret formatDoubleX(value, decimalsToShow); } }