diff --git a/platform/platform-tests/testSrc/com/intellij/util/ui/JBValueTest.java b/platform/platform-tests/testSrc/com/intellij/util/ui/JBValueTest.java index 31805b46ab9e..2d30f28b1c1b 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/ui/JBValueTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/ui/JBValueTest.java @@ -2,6 +2,8 @@ package com.intellij.util.ui; import com.intellij.ui.RestoreScaleRule; +import com.intellij.ui.paint.PaintUtil.RoundingMode; +import com.intellij.util.ui.JBValue.JBValueGroup; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.ExternalResource; @@ -20,41 +22,30 @@ public class JBValueTest { public static final ExternalResource manageState = new RestoreScaleRule(); @Test - public void testInt() { + public void testSeparateValue() { JBUI.setUserScaleFactor(1); - JBValue value1 = JBUI.intValue(2); - JBValue.SelfCachedInteger value2 = new JBValue.SelfCachedInteger(2); + JBValue value1 = JBUI.value(2); + JBValue value2 = JBUI.value(2.6f); + JBValue value3 = JBUI.value(2.9f); JBUI.setUserScaleFactor(2); assertEquals(JBUI.scale(2), value1.get()); - assertEquals(JBUI.scale(2), value2.get()); - } - - @Test - public void testFloat() { - JBUI.setUserScaleFactor(1); - - JBValue.Float value1 = JBUI.floatValue(2.6f); - JBValue.SelfCachedFloat value2 = new JBValue.SelfCachedFloat(2.6f); - - JBUI.setUserScaleFactor(2); - - assertEquals(Math.round(JBUI.scale(2.6f)), value1.get()); assertEquals(Math.round(JBUI.scale(2.6f)), value2.get()); - assertEquals(JBUI.scale(2.6f), value1.getFloat()); assertEquals(JBUI.scale(2.6f), value2.getFloat()); + assertEquals((int)Math.ceil(JBUI.scale(2.6f)), value2.get(RoundingMode.CEIL)); + assertEquals((int)Math.floor(JBUI.scale(2.6f)), value3.get(RoundingMode.FLOOR)); } @Test - public void testUpdateTracker() { + public void testGroup() { JBUI.setUserScaleFactor(1); - JBValue.UpdateTracker tracker = new JBValue.UpdateTracker(); - JBValue value1 = JBUI.intValue(1, tracker); - JBValue value2 = JBUI.intValue(2, tracker); - JBValue.Float value3 = JBUI.floatValue(3.6f, tracker); + JBValueGroup values = new JBValueGroup(); + JBValue value1 = values.add(1); + JBValue value2 = values.add(2); + JBValue value3 = values.add(3.6f); JBUI.setUserScaleFactor(2); @@ -63,38 +54,35 @@ public class JBValueTest { assertEquals(Math.round(JBUI.scale(3.6f)), value3.get()); assertEquals(JBUI.scale(3.6f), value3.getFloat()); - tracker.forget((JBValue.Cacheable)value3); + values.dispose(); int scale = JBUI.scale(1); - JBUI.setUserScaleFactor(3); - - assertEquals(Math.round(scale * 3.6f), value3.get()); - assertEquals(scale * 3.6f, value3.getFloat()); - - tracker.dispose(); - - scale = JBUI.scale(1); JBUI.setUserScaleFactor(1); assertEquals(scale, value1.get()); assertEquals(scale * 2, value2.get()); + assertEquals(Math.round(scale * 3.6f), value3.get()); + assertEquals(scale * 3.6f, value3.getFloat()); } @Test - public void testUIDefaultsInteger() { + public void testUIInteger() { JBUI.setUserScaleFactor(1); String key = "JBValue.int"; + String absentKey = "JBValue.absent"; UIManager.put(key, 2); - JBValue.UIDefaultsInteger value = new JBValue.UIDefaultsInteger(key); + JBValue value1 = JBUI.uiIntValue(key, 1); + JBValue value2 = JBUI.uiIntValue(absentKey, 1); JBUI.setUserScaleFactor(2); - assertEquals(JBUI.scale(2), value.get()); + assertEquals(JBUI.scale(2), value1.get()); + assertEquals(JBUI.scale(1), value2.get()); UIManager.put(key, 3); - assertEquals(JBUI.scale(3), value.get()); + assertEquals(JBUI.scale(3), value1.get()); UIManager.put(key, null); } diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 690571d95241..6609d76d6717 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -483,20 +483,13 @@ public class JBUI { } @NotNull - public static JBValue.Integer intValue(int value) { - return new JBValue.Integer(value); - } - - public static JBValue.Integer intValue(int value, JBValue.UpdateTracker tracker) { - return new JBValue.CachedInteger(value, tracker); - } - - public static JBValue.Float floatValue(float value) { + public static JBValue value(float value) { return new JBValue.Float(value); } - public static JBValue.Float floatValue(float value, JBValue.UpdateTracker tracker) { - return new JBValue.CachedFloat(value, tracker); + @NotNull + public static JBValue uiIntValue(@NotNull String key, int defValue) { + return new JBValue.UIInteger(key, defValue); } public static JBDimension size(int width, int height) { diff --git a/platform/util/src/com/intellij/util/ui/JBValue.java b/platform/util/src/com/intellij/util/ui/JBValue.java index afa8b84c42bb..7abe02f43475 100644 --- a/platform/util/src/com/intellij/util/ui/JBValue.java +++ b/platform/util/src/com/intellij/util/ui/JBValue.java @@ -16,21 +16,15 @@ import static com.intellij.ui.paint.PaintUtil.RoundingMode.ROUND; /** * A wrapper over an unscaled numeric value, auto-scaled via {@link JBUI#scale}. *
- * Use {@link Integer} or {@link Float} classes for on-demand value scaling. + * {@code JBValue} can be used separately or in a group, see {@link JBValueGroup}. *
- * If the same JBValue object is used multiple times in a code block, then in order to save scaling ops, - * a {@link CachedInteger} or {@link CachedFloat} classes can be used instead. Either with a separate - * {@link UpdateTracker} (better to use for many JBValue objects), or with a dedicated one (for a single - * JBValue object) as in the {@link SelfCachedInteger} or {@link SelfCachedFloat} classes. - *
- * Also, the {@link UIDefaultsInteger} class can be used for auto-scaling an integer value stored in
- * {@link UIDefaults}.
+ * Also, a {@link UIInteger} value can be used as a wrapper over an integer value stored in {@link UIDefaults}.
+ *
+ * @see JBUI#value(float)
+ * @see JBValueGroup#add(float)
+ * @see JBUI#uiIntValue(String, int)
*
* @author tav
- * @see JBUI#intValue(int)
- * @see JBUI#intValue(int,UpdateTracker)
- * @see JBUI#floatValue(float)
- * @see JBUI#floatValue(float,UpdateTracker)
*/
public abstract class JBValue {
protected JBValue() {}
@@ -39,8 +33,14 @@ public abstract class JBValue {
* Returns scaled rounded to int value.
*/
public int get() {
- // for backward compatibility rely on the rounding mode applied in JBUI.scale(int)
- return JBUI.scale((int)getUnscaled());
+ return ROUND.round(JBUI.scale(getUnscaled()));
+ }
+
+ /**
+ * Returns scaled float value.
+ */
+ public float getFloat() {
+ return JBUI.scale(getUnscaled());
}
/**
@@ -55,143 +55,53 @@ public abstract class JBValue {
*/
protected abstract float getUnscaled();
- public interface Cacheable {
- /**
- * Scales and caches the value.
- */
- void cache();
- }
-
/**
* JBValue wrapper over an integer value in {@link UIDefaults}.
+ *
+ * @see JBUI#uiIntValue(String,int)
*/
- public static class UIDefaultsInteger extends JBValue {
+ public static class UIInteger extends JBValue {
private final @NotNull String key;
+ private final int defValue;
- public UIDefaultsInteger(@NotNull String key) {
+ public UIInteger(@NotNull String key, int defValue) {
this.key = key;
+ this.defValue = defValue;
}
@Override
protected float getUnscaled() {
- return UIManager.getInt(key);
- }
- }
-
- /**
- * JBValue wrapper over an integer.
- */
- public static class Integer extends JBValue {
- private final int value;
-
- /**
- * @param value unscaled value
- * @see JBUI#intValue(int)
- */
- public Integer(int value) {
- this.value = value;
- }
-
- @Override
- protected float getUnscaled() {
- return value;
+ return JBUI.getInt(key, defValue);
}
}
/**
* JBValue wrapper over a float.
+ *
+ * @see JBUI#value(float)
*/
public static class Float extends JBValue {
private final float value;
/**
* @param value unscaled value
- * @see JBUI#floatValue(float)
*/
public Float(float value) {
this.value = value;
}
- @Override
- public int get() {
- return ROUND.round(JBUI.scale(value));
- }
-
- /**
- * Scales the value and returns.
- */
- public float getFloat() {
- return JBUI.scale(value);
- }
-
@Override
protected float getUnscaled() {
return value;
}
}
- /**
- * Integer JBValue which caches its scaled value on JBUI.scale change.
- */
- public static class CachedInteger extends Integer implements Cacheable {
- private int cachedScaledValue;
-
- protected CachedInteger(int value) {
- super(value);
- }
-
- /**
- * @param value unscaled value
- * @param tracker updates the value
- * @see JBUI#intValue(int, UpdateTracker)
- */
- public CachedInteger(int value, @NotNull UpdateTracker tracker) {
- super(value);
- cachedScaledValue = JBUI.scale(value);
- tracker.track(this);
- }
-
- @Override
- public int get() {
- return cachedScaledValue;
- }
-
- public void cache() {
- cachedScaledValue = JBUI.scale((int)getUnscaled());
- }
- }
-
- /**
- * CachedInteger with a dedicated UpdateTracker.
- */
- public static class SelfCachedInteger extends CachedInteger {
- private final @NotNull UpdateTracker tracker = new UpdateTracker();
-
- public SelfCachedInteger(int value) {
- super(value);
- this.tracker.track(this);
- }
- }
-
- /**
- * Float JBValue which caches its scaled value on JBUI.scale change.
- */
- public static class CachedFloat extends Float implements Cacheable {
+ private static class CachedFloat extends Float {
private float cachedScaledValue;
protected CachedFloat(float value) {
super(value);
- }
-
- /**
- * @param value unscaled value
- * @param tracker updates the value
- * @see JBUI#floatValue(float, UpdateTracker)
- */
- public CachedFloat(float value, UpdateTracker tracker) {
- super(value);
- cachedScaledValue = JBUI.scale(value);
- tracker.track(this);
+ scaleAndCache();
}
@Override
@@ -204,50 +114,46 @@ public abstract class JBValue {
return cachedScaledValue;
}
- public void cache() {
+ @Override
+ public int get(@NotNull RoundingMode rm) {
+ return rm.round(cachedScaledValue);
+ }
+
+ public void scaleAndCache() {
cachedScaledValue = JBUI.scale(getUnscaled());
}
}
/**
- * CachedFloat with a dedicated UpdateTracker.
+ * A group of values, utilizing caching strategy per value. The group listens to the global user scale factor change and updates
+ * all of the values. The {@link JBValue#get()} method of a value returns a cached scaled value, saving recalculation.
+ * This can be a better choice when values are used multiple times in a code block.
*/
- public static class SelfCachedFloat extends CachedFloat {
- private final @NotNull UpdateTracker tracker = new UpdateTracker();
-
- public SelfCachedFloat(float value) {
- super(value);
- this.tracker.track(this);
- }
- }
-
- /**
- * Tracks for a list of {@link Cacheable} values and auto-updates them on {@link JBUI#USER_SCALE_FACTOR_PROPERTY}} change.
- */
- public static class UpdateTracker {
- private final List