diff --git a/designer-base/src/main/java/com/fine/theme/icon/IconManager.java b/designer-base/src/main/java/com/fine/theme/icon/IconManager.java index aa2ef8b173..01f722e24b 100644 --- a/designer-base/src/main/java/com/fine/theme/icon/IconManager.java +++ b/designer-base/src/main/java/com/fine/theme/icon/IconManager.java @@ -1,5 +1,8 @@ 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.general.IOUtils; import com.fr.log.FineLoggerFactory; @@ -8,10 +11,13 @@ 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.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; /** * 图标管理器 @@ -26,12 +32,42 @@ import java.util.HashMap; */ @Immutable public class IconManager { - public static final String ICON_DISABLE_SUFFIX = "_disable"; public static final Dimension DEFAULT_DIMENSION = new Dimension(16, 16); - private static final ArrayList ICON_SETS = new ArrayList<>(2); + private static final ArrayList ICON_SETS = new ArrayList<>(); private static final HashMap> CACHE = new HashMap<>(64); + /** + * 初始化 Icon:FineIcon、PluginIcon + */ + 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 图标集 */ public static IconSet getSet(String id) { + IconSet iconSet = null; for (IconSet set : ICON_SETS) { 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); } diff --git a/designer-base/src/main/java/com/fine/theme/icon/plugin/PluginIconSet.java b/designer-base/src/main/java/com/fine/theme/icon/plugin/PluginIconSet.java new file mode 100644 index 0000000000..39d8c04112 --- /dev/null +++ b/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 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 consumer) { + Set 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); + } +} diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java index e568f5af32..0af36de488 100644 --- a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineDarkLaf.java +++ b/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.theme.icon.IconManager; -import com.fine.theme.light.ui.FineLightIconSet; import com.formdev.flatlaf.util.UIScale; import com.fr.stable.StringUtils; @@ -25,7 +24,7 @@ public class FineDarkLaf extends FineLaf { * @return 是否安装成功 */ public static boolean setup() { - IconManager.addSet(new FineLightIconSet()); + IconManager.initializeIcon(); Layouts.setScaleFactor(UIScale.getUserScaleFactor()); UIScale.addPropertyChangeListener(evt -> { if (StringUtils.equals(evt.getPropertyName(), USER_SCALE_FACTOR)) { diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java index edb038dd0f..aa67a7d2ca 100644 --- a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLaf.java +++ b/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"; - @Override public String getName() { return NAME; @@ -53,4 +52,5 @@ public abstract class FineLaf extends FlatLaf { System.setProperty("flatlaf.menuBarEmbedded", "false"); } } + } diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java b/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java index 9e95b76f7e..5ccc51a8b1 100644 --- a/designer-base/src/main/java/com/fine/theme/light/ui/laf/FineLightLaf.java +++ b/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.theme.icon.IconManager; -import com.fine.theme.light.ui.FineLightIconSet; import com.formdev.flatlaf.util.UIScale; import com.fr.stable.StringUtils; @@ -25,7 +24,7 @@ public class FineLightLaf extends FineLaf { * @return 是否安装成功 */ public static boolean setup() { - IconManager.addSet(new FineLightIconSet()); + IconManager.initializeIcon(); Layouts.setScaleFactor(UIScale.getUserScaleFactor()); UIScale.addPropertyChangeListener(evt -> { if (StringUtils.equals(evt.getPropertyName(), USER_SCALE_FACTOR)) { diff --git a/designer-base/src/main/java/com/fr/design/fun/LazyIconProvider.java b/designer-base/src/main/java/com/fr/design/fun/LazyIconProvider.java new file mode 100644 index 0000000000..f51a2323d7 --- /dev/null +++ b/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; + + /** + * 插件 id,icon 来源标识 + * + * @return 来源标识 + */ + String pluginId(); + + + /** + * light 主题 + * + * @return 图标注册 json 路径 + */ + String lightJsonPath(); + + /** + * dark 主题 + * + * @return 图标注册 json 路径 + */ + String darkJsonPath(); + +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractLazyIconProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractLazyIconProvider.java new file mode 100644 index 0000000000..916a100923 --- /dev/null +++ b/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 ""; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/LookAndFeelAction.java b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/LookAndFeelAction.java index 613fe0a0c1..3edf09d953 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/LookAndFeelAction.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/LookAndFeelAction.java @@ -5,6 +5,7 @@ package com.fr.design.mainframe.toolbar; +import com.fine.theme.icon.IconManager; import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.extras.FlatAnimatedLafChange; import com.fr.design.actions.UpdateAction; @@ -32,6 +33,8 @@ public class LookAndFeelAction extends UpdateAction { FlatAnimatedLafChange.showSnapshot(); try { UIManager.setLookAndFeel( lookAndFeel ); + // 多主题场景下,需要判断是否需要切换图标 + IconManager.updateIcon(); } catch (UnsupportedLookAndFeelException e) { throw new RuntimeException(e); } diff --git a/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java b/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java index 0ed7554075..93a47a9280 100644 --- a/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java +++ b/designer-realize/src/main/java/com/fanruan/boot/env/DesignEnvComponent.java @@ -244,27 +244,27 @@ public class DesignEnvComponent { * ----------- logger -------- */ private void startLogger() { - String realPath = Carina.properties(LoggerProperties.class).getXml(); - URI uri = Log4jUtils.buildUserConfigURI(realPath); + URI uri = Log4jUtils.buildUserConfigURI(StringUtils.EMPTY); FRLogger.getLogger().config(uri); // 日志配置更新的监听在FRLogger里面,fbp去掉了但是设计器本地还是需要这个监听的,初始化的时候监听一下 listenConfig(); } private void listenConfig() { - ValidateConfigManger.getInstance().registerListener(new ConfigChangeListener() { - - @Override - public boolean accept(Class configClass) { - return configClass.equals(Log4jConfig.class); - } - - @Override - public void change() { - // The root logger is the topmost logger with a name of "" (the empty string). - Configurator.setAllLevels("", Log4jConfig.getInstance().getRootLevel()); - } - }); +/// 等fbp改完,现在先配合打包注释掉 +// ValidateConfigManger.getInstance().registerListener(new ConfigChangeListener() { +// +// @Override +// public boolean accept(Class configClass) { +// return configClass.equals(Log4jConfig.class); +// } +// +// @Override +// public void change() { +// // The root logger is the topmost logger with a name of "" (the empty string). +// Configurator.setAllLevels("", Log4jConfig.getInstance().getRootLevel()); +// } +// }); } diff --git a/designer-realize/src/main/java/com/fanruan/boot/env/DesignFunctionComponent.java b/designer-realize/src/main/java/com/fanruan/boot/env/DesignFunctionComponent.java index 6c584ca3a3..63de9d0d27 100644 --- a/designer-realize/src/main/java/com/fanruan/boot/env/DesignFunctionComponent.java +++ b/designer-realize/src/main/java/com/fanruan/boot/env/DesignFunctionComponent.java @@ -7,7 +7,7 @@ import com.fanruan.carina.annotions.Start; import com.fanruan.messenger.ums.config.email.FineEmailSecurityProviderImpl; import com.fr.base.email.EmailCenter; import com.fr.base.email.impl.EmailAccountManagerImpl; -import com.fr.base.email.impl.FREmailDispatcherImpl; +import com.fr.base.email.impl.EmailDispatcherImpl; import com.fr.base.email.impl.FineEmailExtensionProviderImpl; import com.fr.base.email.impl.FineEmailResourceProviderImpl; import com.fr.base.email.provider.FineEmailExtensionProvider; @@ -78,7 +78,7 @@ public class DesignFunctionComponent { fineEmailExtensionProvider, fineEmailResourceProvider, new FineEmailSecurityProviderImpl()); - EmailCenter.setDispatcher(new FREmailDispatcherImpl()); + EmailCenter.setDispatcher(new EmailDispatcherImpl()); EmailCenter.setAccountManager(new EmailAccountManagerImpl()); EmailTaskManagement.getInstance().start(); } diff --git a/designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java b/designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java index eca6315272..06459b8fe3 100644 --- a/designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java +++ b/designer-realize/src/main/java/com/fanruan/boot/pre/DesignPreStartComponent.java @@ -61,7 +61,7 @@ import com.fr.tenant.config.TenantConfigProvider; import com.fr.tenant.context.CurrentTenantProviderStater; import com.fr.tenant.context.TenantContext; import com.fr.tenant.context.provider.CurrentTenantKey; -import com.fr.tenant.store.impl.DefaultTenantStorage; +import com.fr.tenant.store.impl.MemoryTenantStorage; import com.fr.workspace.WorkContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -208,7 +208,7 @@ public class DesignPreStartComponent { private void startTenant() { - TenantContext.registerStorage(new DefaultTenantStorage()); + TenantContext.registerStorage(new MemoryTenantStorage()); TenantContext.registerConfigProvider(new TenantConfigProvider() { @Override public boolean isMultiTenantOpen() {