Browse Source

Pull request #14702: REPORT-127437 newui 适配插件图标

Merge in DESIGN/design from ~ZONGYU.WANG/design:fbp/feature to fbp/feature

* commit '5c244766431942a105d58f8ea0e1e0e4eba8ebe6':
  REPORT-127437 fix: 去掉不用的代码
  REPORT-127437 fix: 插件图标适配代码调整
  REPORT-127437 fix: 调整代码逻辑,插件跟设计器共用 icon 加载方式,调整插件 icon 和 set 的 id 标识
  REPORT-127437 feat:调整代码,增加 mapSet
  REPORT-127437 feat:适配插件图标
  REPORT-127437 feat:适配插件图标
fbp/feature
Zongyu.Wang-王宗雨 3 months ago
parent
commit
05d34ce831
  1. 49
      designer-base/src/main/java/com/fine/theme/icon/IconManager.java
  2. 127
      designer-base/src/main/java/com/fine/theme/icon/plugin/PluginIconSet.java
  3. 3
      designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java
  4. 2
      designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java
  5. 3
      designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java
  6. 39
      designer-base/src/main/java/com/fr/design/fun/LazyIconProvider.java
  7. 59
      designer-base/src/main/java/com/fr/design/fun/impl/AbstractLazyIconProvider.java
  8. 3
      designer-base/src/main/java/com/fr/design/mainframe/toolbar/LookAndFeelAction.java

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

@ -1,5 +1,8 @@
package com.fine.theme.icon; package com.fine.theme.icon;
import com.fine.theme.icon.plugin.PluginIconSet;
import com.fine.theme.light.ui.FineLightIconSet;
import com.formdev.flatlaf.FlatLaf;
import com.fr.base.extension.FileExtension; import com.fr.base.extension.FileExtension;
import com.fr.general.IOUtils; import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory; import com.fr.log.FineLoggerFactory;
@ -8,10 +11,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import java.awt.Dimension; import java.awt.Dimension;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
/** /**
* 图标管理器 * 图标管理器
@ -26,12 +32,42 @@ import java.util.HashMap;
*/ */
@Immutable @Immutable
public class IconManager { public class IconManager {
public static final String ICON_DISABLE_SUFFIX = "_disable"; public static final String ICON_DISABLE_SUFFIX = "_disable";
public static final Dimension DEFAULT_DIMENSION = new Dimension(16, 16); public static final Dimension DEFAULT_DIMENSION = new Dimension(16, 16);
private static final ArrayList<IconSet> ICON_SETS = new ArrayList<>(2); private static final ArrayList<IconSet> ICON_SETS = new ArrayList<>();
private static final HashMap<String, WeakReference<Icon>> CACHE = new HashMap<>(64); private static final HashMap<String, WeakReference<Icon>> CACHE = new HashMap<>(64);
/**
* 初始化 IconFineIconPluginIcon
*/
public static void initializeIcon() {
addIconSet();
}
/**
* 切换 Icon
*/
public static void updateIcon() {
ICON_SETS.clear();
clearCache();
addIconSet();
}
private static void addIconSet() {
boolean dark = false;
LookAndFeel laf = UIManager.getLookAndFeel();
if (laf instanceof FlatLaf) {
dark = ((FlatLaf) laf).isDark();
}
if (dark) {
// dark 主题还没适配
addSet(new FineLightIconSet());
} else {
addSet(new FineLightIconSet());
}
addSet(new PluginIconSet());
}
/** /**
* 获取图标集 * 获取图标集
@ -40,10 +76,17 @@ public class IconManager {
* @return 图标集 * @return 图标集
*/ */
public static IconSet getSet(String id) { public static IconSet getSet(String id) {
IconSet iconSet = null;
for (IconSet set : ICON_SETS) { for (IconSet set : ICON_SETS) {
if (set.getId().equals(id)) { if (set.getId().equals(id)) {
return set; iconSet = set;
} }
if (set instanceof PluginIconSet && iconSet == null) {
iconSet = PluginIconSet.getIconSet(id);
}
}
if (iconSet != null) {
return iconSet;
} }
throw new IconException("[IconManager] Can not find icon set by id: " + id); throw new IconException("[IconManager] Can not find icon set by id: " + id);
} }

127
designer-base/src/main/java/com/fine/theme/icon/plugin/PluginIconSet.java

@ -0,0 +1,127 @@
package com.fine.theme.icon.plugin;
import com.fine.theme.icon.AbstractIconSet;
import com.fine.theme.icon.IconSet;
import com.fine.theme.icon.IconType;
import com.fine.theme.icon.JsonIconSet;
import com.fine.theme.icon.UrlIconResource;
import com.formdev.flatlaf.FlatLaf;
import com.fr.design.fun.LazyIconProvider;
import com.fr.general.GeneralContext;
import com.fr.plugin.manage.PluginFilter;
import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.plugin.observer.PluginEventType;
import com.fr.stable.AssistUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.Icon;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Set;
import java.util.function.Consumer;
/**
* 管理插件 iconSet
* @author lemon
* @since
* Created on
*/
public class PluginIconSet extends AbstractIconSet {
private static final String NAME = "Plugin Icon Set";
private static final ArrayList<IconSet> PLUGIN_ICON_SETS = new ArrayList<>();
public PluginIconSet() {
name = NAME;
listenPluginIcons();
}
/**
* 适配插件图标 Icon
*/
public static void listenPluginIcons() {
//注册插件监听
PluginFilter filter = context -> context.contain(LazyIconProvider.MARK_STRING);
PluginEventListener insert = new PluginEventListener() {
@Override
public void on(PluginEvent event) {
handlePluginEvent(event, (provider) -> PLUGIN_ICON_SETS.add(generateJsonIconSet(provider)));
}
};
PluginEventListener remove = new PluginEventListener() {
@Override
public void on(PluginEvent event) {
handlePluginEvent(event, (provider) -> PLUGIN_ICON_SETS.removeIf(iconSet -> iconSet.getId().equals(provider.pluginId())));
}
};
GeneralContext.listenPlugin(PluginEventType.AfterRun, insert, filter);
GeneralContext.listenPlugin(PluginEventType.AfterInstall, insert, filter);
GeneralContext.listenPlugin(PluginEventType.AfterForbid, remove, filter);
GeneralContext.listenPlugin(PluginEventType.AfterUninstall, remove, filter);
}
private static void handlePluginEvent(PluginEvent event, Consumer<LazyIconProvider> consumer) {
Set<LazyIconProvider> set = event.getContext().getRuntime().get(LazyIconProvider.MARK_STRING);
for (LazyIconProvider provider : set) {
consumer.accept(provider);
}
}
private static JsonIconSet generateJsonIconSet(LazyIconProvider provider) {
LookAndFeel laf = UIManager.getLookAndFeel();
boolean dark = ((FlatLaf) laf).isDark();
String jsonPath = dark ? provider.darkJsonPath() : provider.lightJsonPath();
return new JsonIconSet(new UrlIconResource(jsonPath)) {
@Override
public @NotNull String getId() {
return provider.pluginId();
}
};
}
@Override
public @Nullable Icon findIcon(@NotNull String id, @NotNull Dimension dimension, IconType type) {
Icon icon;
for (IconSet iconSet : PLUGIN_ICON_SETS) {
icon = iconSet.findIcon(id, dimension, type);
if (icon != null) {
return icon;
}
}
return null;
}
/**
* 根据 id 匹配 icon set
* @param id 对于 plugin icon set, id plugin_id
* @return icon set
*/
public static IconSet getIconSet(@NotNull final String id ) {
for (IconSet iconSet : PLUGIN_ICON_SETS) {
if (iconSet.getId().equals(id)) {
return iconSet;
}
}
return null;
}
@Override
public boolean equals(Object obj) {
return obj instanceof PluginIconSet
&& AssistUtils.equals(this.name, ((PluginIconSet) obj).name);
}
@Override
public int hashCode() {
return AssistUtils.hashCode(name);
}
}

3
designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java

@ -2,7 +2,6 @@ package com.fine.theme.light.ui.laf;
import com.fine.swing.ui.layout.Layouts; import com.fine.swing.ui.layout.Layouts;
import com.fine.theme.icon.IconManager; import com.fine.theme.icon.IconManager;
import com.fine.theme.light.ui.FineLightIconSet;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
import com.fr.stable.StringUtils; import com.fr.stable.StringUtils;
@ -25,7 +24,7 @@ public class FineDarkLaf extends FineLaf {
* @return 是否安装成功 * @return 是否安装成功
*/ */
public static boolean setup() { public static boolean setup() {
IconManager.addSet(new FineLightIconSet()); IconManager.initializeIcon();
Layouts.setScaleFactor(UIScale.getUserScaleFactor()); Layouts.setScaleFactor(UIScale.getUserScaleFactor());
UIScale.addPropertyChangeListener(evt -> { UIScale.addPropertyChangeListener(evt -> {
if (StringUtils.equals(evt.getPropertyName(), USER_SCALE_FACTOR)) { if (StringUtils.equals(evt.getPropertyName(), USER_SCALE_FACTOR)) {

2
designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java

@ -18,7 +18,6 @@ public abstract class FineLaf extends FlatLaf {
private static final String NAME = "FineLaf"; private static final String NAME = "FineLaf";
@Override @Override
public String getName() { public String getName() {
return NAME; return NAME;
@ -53,4 +52,5 @@ public abstract class FineLaf extends FlatLaf {
System.setProperty("flatlaf.menuBarEmbedded", "false"); System.setProperty("flatlaf.menuBarEmbedded", "false");
} }
} }
} }

3
designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java

@ -2,7 +2,6 @@ package com.fine.theme.light.ui.laf;
import com.fine.swing.ui.layout.Layouts; import com.fine.swing.ui.layout.Layouts;
import com.fine.theme.icon.IconManager; import com.fine.theme.icon.IconManager;
import com.fine.theme.light.ui.FineLightIconSet;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
import com.fr.stable.StringUtils; import com.fr.stable.StringUtils;
@ -25,7 +24,7 @@ public class FineLightLaf extends FineLaf {
* @return 是否安装成功 * @return 是否安装成功
*/ */
public static boolean setup() { public static boolean setup() {
IconManager.addSet(new FineLightIconSet()); IconManager.initializeIcon();
Layouts.setScaleFactor(UIScale.getUserScaleFactor()); Layouts.setScaleFactor(UIScale.getUserScaleFactor());
UIScale.addPropertyChangeListener(evt -> { UIScale.addPropertyChangeListener(evt -> {
if (StringUtils.equals(evt.getPropertyName(), USER_SCALE_FACTOR)) { if (StringUtils.equals(evt.getPropertyName(), USER_SCALE_FACTOR)) {

39
designer-base/src/main/java/com/fr/design/fun/LazyIconProvider.java

@ -0,0 +1,39 @@
package com.fr.design.fun;
import com.fr.stable.fun.mark.Mutable;
/**
* 插件图标适配接口
*
* @author lemon
* @since
* Created on
*/
public interface LazyIconProvider extends Mutable {
String MARK_STRING = "LazyIconProvider";
int CURRENT_LEVEL = 1;
/**
* 插件 idicon 来源标识
*
* @return 来源标识
*/
String pluginId();
/**
* light 主题
*
* @return 图标注册 json 路径
*/
String lightJsonPath();
/**
* dark 主题
*
* @return 图标注册 json 路径
*/
String darkJsonPath();
}

59
designer-base/src/main/java/com/fr/design/fun/impl/AbstractLazyIconProvider.java

@ -0,0 +1,59 @@
package com.fr.design.fun.impl;
import com.fr.design.fun.LazyIconProvider;
import com.fr.stable.fun.impl.AbstractProvider;
import com.fr.stable.fun.mark.API;
import java.util.List;
/**
* 插件图标 LazyIcon 加载适配抽象类
*
* @author lemon
* @since
* Created on
*/
@API(level = LazyIconProvider.CURRENT_LEVEL)
public abstract class AbstractLazyIconProvider extends AbstractProvider implements LazyIconProvider {
/**
* 当前接口的API等级,用于判断是否需要升级插件
* @return API等级
*/
@Override
public int currentAPILevel() {
return CURRENT_LEVEL;
}
/**
* 区分插件
*
* @return 插件 id
*/
@Override
public String pluginId() {
throw new RuntimeException("plugin id is blank");
}
/**
* light 主题
*
* @return 图标注册 json 路径
*/
@Override
public String lightJsonPath() {
return "";
}
/**
* dark 主题
*
* @return 图标注册 json 路径
*/
@Override
public String darkJsonPath() {
return "";
}
}

3
designer-base/src/main/java/com/fr/design/mainframe/toolbar/LookAndFeelAction.java

@ -5,6 +5,7 @@
package com.fr.design.mainframe.toolbar; package com.fr.design.mainframe.toolbar;
import com.fine.theme.icon.IconManager;
import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.extras.FlatAnimatedLafChange; import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
import com.fr.design.actions.UpdateAction; import com.fr.design.actions.UpdateAction;
@ -32,6 +33,8 @@ public class LookAndFeelAction extends UpdateAction {
FlatAnimatedLafChange.showSnapshot(); FlatAnimatedLafChange.showSnapshot();
try { try {
UIManager.setLookAndFeel( lookAndFeel ); UIManager.setLookAndFeel( lookAndFeel );
// 多主题场景下,需要判断是否需要切换图标
IconManager.updateIcon();
} catch (UnsupportedLookAndFeelException e) { } catch (UnsupportedLookAndFeelException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

Loading…
Cancel
Save