Browse Source

REPORT-99485 修复白化图标高DPI下显示不正确的问题

newui
jinsihou 11 months ago
parent
commit
397ba58db7
  1. 49
      designer-base/src/main/java/com/fine/theme/icon/IconManager.java
  2. 23
      designer-base/src/main/java/com/fine/theme/icon/IconType.java
  3. 29
      designer-base/src/main/java/com/fine/theme/icon/LazyIcon.java
  4. 53
      designer-base/src/main/java/com/fine/theme/icon/svg/SvgIcon.java
  5. 6
      designer-base/src/main/java/com/fine/theme/light/ui/FineLightIconSet.java
  6. 23
      designer-base/src/test/java/com/fr/design/gui/storybook/components/ButtonGroupStoryBoard.java

49
designer-base/src/main/java/com/fine/theme/icon/IconManager.java

@ -23,11 +23,11 @@ import java.util.HashMap;
@Immutable @Immutable
public class IconManager { public class IconManager {
public static boolean initialized = false; private static final ArrayList<IconSet> ICON_SETS = new ArrayList<>(2);
public static ArrayList<IconSet> iconSets = new ArrayList<>(2);
public static HashMap<String, WeakReference<Icon>> cache = new HashMap<>(64); private static final HashMap<String, WeakReference<Icon>> CACHE = new HashMap<>(64);
public static HashMap<String, WeakReference<Icon>> disableCache = new HashMap<>(64); private static final HashMap<String, WeakReference<Icon>> DISABLE_CACHE = new HashMap<>(64);
public static HashMap<String, WeakReference<Icon>> whiteCache = new HashMap<>(32); private static final HashMap<String, WeakReference<Icon>> WHITE_CACHE = new HashMap<>(32);
/** /**
@ -37,7 +37,7 @@ public class IconManager {
* @return 图标集 * @return 图标集
*/ */
public static IconSet getSet(String id) { public static IconSet getSet(String id) {
for (IconSet set : iconSets) { for (IconSet set : ICON_SETS) {
if (set.getId().equals(id)) { if (set.getId().equals(id)) {
return set; return set;
} }
@ -51,8 +51,8 @@ public class IconManager {
* @param set 图标集 * @param set 图标集
*/ */
public static void addSet(@NotNull IconSet set) { public static void addSet(@NotNull IconSet set) {
if (!iconSets.contains(set)) { if (!ICON_SETS.contains(set)) {
iconSets.add(set); ICON_SETS.add(set);
// 清理可能来自其他图集相同名称图标 // 清理可能来自其他图集相同名称图标
clearIconSetCache(set); clearIconSetCache(set);
} else { } else {
@ -85,14 +85,14 @@ public class IconManager {
*/ */
@NotNull @NotNull
public static <I extends Icon> I getWhiteIcon(String id) { public static <I extends Icon> I getWhiteIcon(String id) {
final WeakReference<Icon> reference = whiteCache.get(id); final WeakReference<Icon> reference = WHITE_CACHE.get(id);
I icon = reference != null ? (I) reference.get() : null; I icon = reference != null ? (I) reference.get() : null;
if (icon == null) { if (icon == null) {
for (IconSet set : iconSets) { for (IconSet set : ICON_SETS) {
Icon f = set.findWhiteIcon(id); Icon f = set.findWhiteIcon(id);
if (f != null) { if (f != null) {
icon = (I) f; icon = (I) f;
whiteCache.put(id, new WeakReference<>(icon)); WHITE_CACHE.put(id, new WeakReference<>(icon));
} }
} }
} }
@ -120,14 +120,14 @@ public class IconManager {
@Nullable @Nullable
private static <I extends Icon> I findDisableIcon(String id) { private static <I extends Icon> I findDisableIcon(String id) {
final WeakReference<Icon> reference = disableCache.get(id); final WeakReference<Icon> reference = DISABLE_CACHE.get(id);
I icon = reference != null ? (I) reference.get() : null; I icon = reference != null ? (I) reference.get() : null;
if (icon == null) { if (icon == null) {
for (IconSet set : iconSets) { for (IconSet set : ICON_SETS) {
Icon f = set.findDisableIcon(id); Icon f = set.findDisableIcon(id);
if (f != null) { if (f != null) {
icon = (I) f; icon = (I) f;
disableCache.put(id, new WeakReference<>(icon)); DISABLE_CACHE.put(id, new WeakReference<>(icon));
} }
} }
} }
@ -136,14 +136,14 @@ public class IconManager {
@Nullable @Nullable
private static <I extends Icon> I findIcon(String id) { private static <I extends Icon> I findIcon(String id) {
final WeakReference<Icon> reference = cache.get(id); final WeakReference<Icon> reference = CACHE.get(id);
I icon = reference != null ? (I) reference.get() : null; I icon = reference != null ? (I) reference.get() : null;
if (icon == null) { if (icon == null) {
for (IconSet set : iconSets) { for (IconSet set : ICON_SETS) {
Icon f = set.findIcon(id); Icon f = set.findIcon(id);
if (f != null) { if (f != null) {
icon = (I) f; icon = (I) f;
cache.put(id, new WeakReference<>(icon)); CACHE.put(id, new WeakReference<>(icon));
} }
} }
} }
@ -154,22 +154,25 @@ public class IconManager {
* 清理所有缓存 * 清理所有缓存
*/ */
public static void clearCache() { public static void clearCache() {
cache.clear(); CACHE.clear();
disableCache.clear(); DISABLE_CACHE.clear();
WHITE_CACHE.clear();
} }
/** /**
* 清理图标缓存 * 清理图标缓存
*/ */
public static void clearIconCache(String id) { public static void clearIconCache(String id) {
cache.remove(id); CACHE.remove(id);
disableCache.remove(id); DISABLE_CACHE.remove(id);
WHITE_CACHE.clear();
} }
private static void clearIconSetCache(@NotNull IconSet set) { private static void clearIconSetCache(@NotNull IconSet set) {
for (String id : set.getIds()) { for (String id : set.getIds()) {
cache.remove(id); CACHE.remove(id);
disableCache.remove(id); DISABLE_CACHE.remove(id);
WHITE_CACHE.remove(id);
} }
} }
} }

23
designer-base/src/main/java/com/fine/theme/icon/IconType.java

@ -0,0 +1,23 @@
package com.fine.theme.icon;
/**
* 图标类型
*
* @author vito
* @since 11.0
* Created on 2024/01/09
*/
public enum IconType {
/**
* 灰化图
*/
disable,
/**
* 白化图用于反白场景
*/
white,
/**
* 原始图
*/
normal
}

29
designer-base/src/main/java/com/fine/theme/icon/LazyIcon.java

@ -6,6 +6,7 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.Icon; import javax.swing.Icon;
import java.awt.Component; import java.awt.Component;
import java.awt.Graphics; import java.awt.Graphics;
import java.util.StringJoiner;
/** /**
* 懒加载图标 * 懒加载图标
@ -19,8 +20,16 @@ public class LazyIcon implements Identifiable, DisabledIcon, WhiteIcon, Icon {
@NotNull @NotNull
private final String id; private final String id;
private final IconType type;
public LazyIcon(@NotNull final String id) { public LazyIcon(@NotNull final String id) {
this.id = id; this.id = id;
this.type = IconType.normal;
}
private LazyIcon(@NotNull final String id, IconType type) {
this.id = id;
this.type = type;
} }
@ -48,7 +57,14 @@ public class LazyIcon implements Identifiable, DisabledIcon, WhiteIcon, Icon {
@NotNull @NotNull
public <I extends Icon> I getIcon() { public <I extends Icon> I getIcon() {
return IconManager.getIcon(getId()); switch (type) {
case white:
return IconManager.getWhiteIcon(getId());
case disable:
return IconManager.getDisableIcon(getId());
default:
return IconManager.getIcon(getId());
}
} }
/** /**
@ -59,7 +75,7 @@ public class LazyIcon implements Identifiable, DisabledIcon, WhiteIcon, Icon {
@NotNull @NotNull
@Override @Override
public Icon disabled() { public Icon disabled() {
return IconManager.getDisableIcon(getId()); return new LazyIcon(getId(), IconType.disable);
} }
/** /**
@ -70,14 +86,15 @@ public class LazyIcon implements Identifiable, DisabledIcon, WhiteIcon, Icon {
@NotNull @NotNull
@Override @Override
public Icon white() { public Icon white() {
return IconManager.getWhiteIcon(getId()); return new LazyIcon(getId(), IconType.white);
} }
@NotNull
@Override @Override
public String toString() { public String toString() {
return getClass().getCanonicalName() + "[id=" + getId() + "]"; return new StringJoiner(", ", LazyIcon.class.getSimpleName() + "[", "]")
.add("id='" + id + "'")
.add("type=" + type)
.toString();
} }
} }

53
designer-base/src/main/java/com/fine/theme/icon/svg/SvgIcon.java

@ -3,6 +3,7 @@ package com.fine.theme.icon.svg;
import com.fine.theme.icon.DisabledIcon; import com.fine.theme.icon.DisabledIcon;
import com.fine.theme.icon.GraphicsFilter; import com.fine.theme.icon.GraphicsFilter;
import com.fine.theme.icon.IconResource; import com.fine.theme.icon.IconResource;
import com.fine.theme.icon.IconType;
import com.fine.theme.icon.WhiteIcon; import com.fine.theme.icon.WhiteIcon;
import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.ui.FlatUIUtils;
@ -42,41 +43,28 @@ import static com.fine.theme.utils.FineUIScale.scale;
@Immutable @Immutable
public class SvgIcon implements DisabledIcon, WhiteIcon, Icon { public class SvgIcon implements DisabledIcon, WhiteIcon, Icon {
public enum Type {
/**
* 灰化图
*/
disable,
/**
* 白化图用于反白场景
*/
white,
/**
* 原始效果图
*/
origin
}
private final Dimension size; private final Dimension size;
private final Dimension scaleSize;
private final IconResource resource; private final IconResource resource;
private final Type type; private final IconType type;
private final NullableLazyValue<SVGDocument> svgDocument = NullableLazyValue.createValue(() -> load(Type.origin)); private final NullableLazyValue<SVGDocument> svgDocument = NullableLazyValue.createValue(() -> load(IconType.normal));
private final NullableLazyValue<SVGDocument> whiteSvgDocument = NullableLazyValue.createValue(() -> load(Type.white)); private final NullableLazyValue<SVGDocument> whiteSvgDocument = NullableLazyValue.createValue(() -> load(IconType.white));
public SvgIcon(IconResource resource, Dimension size) { public SvgIcon(IconResource resource, Dimension size) {
this(resource, size, Type.origin); this(resource, size, IconType.normal);
} }
public SvgIcon(IconResource resource, Dimension size, Type type) { public SvgIcon(IconResource resource, Dimension size, IconType type) {
this.resource = resource; this.resource = resource;
this.size = size;
// 根据dpi进行缩放 // 根据dpi进行缩放
this.size = scale(size); this.scaleSize = scale(size);
this.type = type; this.type = type;
} }
public SvgIcon(IconResource resource, int side) { public SvgIcon(IconResource resource, int side) {
this(resource, new Dimension(side, side), Type.origin); this(resource, new Dimension(side, side), IconType.normal);
} }
/** /**
@ -85,7 +73,7 @@ public class SvgIcon implements DisabledIcon, WhiteIcon, Icon {
*/ */
@Override @Override
public void paintIcon(Component c, Graphics g, int x, int y) { public void paintIcon(Component c, Graphics g, int x, int y) {
if (type == Type.disable) { if (type == IconType.disable) {
g = grayGraphics(g); g = grayGraphics(g);
} }
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints(g); Object[] oldRenderingHints = FlatUIUtils.setRenderingHints(g);
@ -104,22 +92,22 @@ public class SvgIcon implements DisabledIcon, WhiteIcon, Icon {
@Override @Override
public int getIconWidth() { public int getIconWidth() {
return size.width; return scaleSize.width;
} }
@Override @Override
public int getIconHeight() { public int getIconHeight() {
return size.height; return scaleSize.height;
} }
private void render(Component c, Graphics g, int x, int y) { private void render(Component c, Graphics g, int x, int y) {
try { try {
if (type == Type.white) { if (type == IconType.white) {
Objects.requireNonNull(whiteSvgDocument.getValue()) Objects.requireNonNull(whiteSvgDocument.getValue())
.render((JComponent) c, (Graphics2D) g, new ViewBox(x, y, size.width, size.height)); .render((JComponent) c, (Graphics2D) g, new ViewBox(x, y, scaleSize.width, scaleSize.height));
} else { } else {
Objects.requireNonNull(svgDocument.getValue()) Objects.requireNonNull(svgDocument.getValue())
.render((JComponent) c, (Graphics2D) g, new ViewBox(x, y, size.width, size.height)); .render((JComponent) c, (Graphics2D) g, new ViewBox(x, y, scaleSize.width, scaleSize.height));
} }
} catch (Exception e) { } catch (Exception e) {
FineLoggerFactory.getLogger().error("SvgIcon from url: " + resource + "can not paint.", e); FineLoggerFactory.getLogger().error("SvgIcon from url: " + resource + "can not paint.", e);
@ -127,9 +115,9 @@ public class SvgIcon implements DisabledIcon, WhiteIcon, Icon {
} }
private SVGDocument load(Type type) { private SVGDocument load(IconType type) {
SVGLoader loader = new SVGLoader(); SVGLoader loader = new SVGLoader();
return type == Type.white return type == IconType.white
? loader.load(resource.getInputStream(), new WhiteParser()) ? loader.load(resource.getInputStream(), new WhiteParser())
: loader.load(resource.getInputStream()); : loader.load(resource.getInputStream());
} }
@ -141,6 +129,7 @@ public class SvgIcon implements DisabledIcon, WhiteIcon, Icon {
.add("resource=" + resource) .add("resource=" + resource)
.add("type=" + type) .add("type=" + type)
.add("size=" + size) .add("size=" + size)
.add("scaleSize=" + scaleSize)
.toString(); .toString();
} }
@ -149,7 +138,7 @@ public class SvgIcon implements DisabledIcon, WhiteIcon, Icon {
*/ */
@Override @Override
public @NotNull SvgIcon white() { public @NotNull SvgIcon white() {
return new SvgIcon(resource, size, Type.white); return new SvgIcon(resource, size, IconType.white);
} }
@ -158,6 +147,6 @@ public class SvgIcon implements DisabledIcon, WhiteIcon, Icon {
*/ */
@Override @Override
public @NotNull SvgIcon disabled() { public @NotNull SvgIcon disabled() {
return new SvgIcon(resource, size, Type.disable); return new SvgIcon(resource, size, IconType.disable);
} }
} }

6
designer-base/src/main/java/com/fine/theme/light/ui/FineLightIconSet.java

@ -45,9 +45,9 @@ public class FineLightIconSet extends AbstractIconSet {
new SvgIconSource("connection", "com/fine/theme/icon/dataset/connection.svg"), new SvgIconSource("connection", "com/fine/theme/icon/dataset/connection.svg"),
new SvgIconSource("class_table_data", "com/fine/theme/icon/dataset/class_table_data.svg", true), new SvgIconSource("class_table_data", "com/fine/theme/icon/dataset/class_table_data.svg", true),
new SvgIconSource("data_table", "com/fine/theme/icon/dataset/data_table.svg", true), new SvgIconSource("data_table", "com/fine/theme/icon/dataset/data_table.svg", true),
new SvgIconSource("multi", "com/fine/theme/icon/dataset/multi.svg", true), new SvgIconSource("multi", "com/fine/theme/icon/dataset/multi.svg"),
new SvgIconSource("file", "com/fine/theme/icon/dataset/file.svg", true), new SvgIconSource("file", "com/fine/theme/icon/dataset/file.svg"),
new SvgIconSource("tree", "com/fine/theme/icon/dataset/tree.svg", true), new SvgIconSource("tree", "com/fine/theme/icon/dataset/tree.svg"),
new SvgIconSource("store_procedure", "com/fine/theme/icon/dataset/store_procedure.svg", true), new SvgIconSource("store_procedure", "com/fine/theme/icon/dataset/store_procedure.svg", true),
new SvgIconSource("batch_esd_on", "com/fine/theme/icon/dataset/batch_esd_on.svg", true), new SvgIconSource("batch_esd_on", "com/fine/theme/icon/dataset/batch_esd_on.svg", true),
new SvgIconSource("batch_esd_off", "com/fine/theme/icon/dataset/batch_esd_off.svg", true), new SvgIconSource("batch_esd_off", "com/fine/theme/icon/dataset/batch_esd_off.svg", true),

23
designer-base/src/test/java/com/fr/design/gui/storybook/components/ButtonGroupStoryBoard.java

@ -8,6 +8,7 @@ import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.storybook.Story; import com.fr.design.gui.storybook.Story;
import com.fr.design.gui.storybook.StoryBoard; import com.fr.design.gui.storybook.StoryBoard;
import com.fr.stable.ArrayUtils; import com.fr.stable.ArrayUtils;
import com.fr.value.NotNullLazyValue;
import javax.swing.Icon; import javax.swing.Icon;
import java.awt.Component; import java.awt.Component;
@ -49,6 +50,17 @@ public class ButtonGroupStoryBoard extends StoryBoard {
); );
} }
private static final NotNullLazyValue<Icon[]> iconArray = NotNullLazyValue.createValue(() -> ArrayUtils.toArray(
new LazyIcon("edit"),
new LazyIcon("preview"),
new LazyIcon("connection")
));
private static final NotNullLazyValue<Icon[][]> iconArrayWithWhite = NotNullLazyValue.createValue(() -> ArrayUtils.toArray(
ArrayUtils.toArray(new LazyIcon("edit"), new LazyIcon("copy")),
ArrayUtils.toArray(new LazyIcon("preview"), new LazyIcon("save"))
));
private static Component getToolbar(){ private static Component getToolbar(){
UIToolbar toolbar = new UIToolbar(); UIToolbar toolbar = new UIToolbar();
UIButtonGroup<Object> objectUIButtonGroup = new UIButtonGroup<>(iconArrayWithWhite(),null,true); UIButtonGroup<Object> objectUIButtonGroup = new UIButtonGroup<>(iconArrayWithWhite(),null,true);
@ -58,18 +70,11 @@ public class ButtonGroupStoryBoard extends StoryBoard {
} }
private static Icon[] iconArray() { private static Icon[] iconArray() {
return ArrayUtils.toArray( return iconArray.getValue();
new LazyIcon("edit"),
new LazyIcon("preview"),
new LazyIcon("connection")
);
} }
private static Icon[][] iconArrayWithWhite() { private static Icon[][] iconArrayWithWhite() {
return ArrayUtils.toArray( return iconArrayWithWhite.getValue();
ArrayUtils.toArray(new LazyIcon("edit"), new LazyIcon("copy")),
ArrayUtils.toArray(new LazyIcon("preview"), new LazyIcon("save"))
);
} }
private String[] fiveTextArray() { private String[] fiveTextArray() {

Loading…
Cancel
Save