5 changed files with 617 additions and 0 deletions
@ -0,0 +1,213 @@ |
|||||||
|
package com.fine.theme.icon.plugin; |
||||||
|
|
||||||
|
import com.fine.theme.icon.IconException; |
||||||
|
import com.fine.theme.icon.IconManager; |
||||||
|
import com.fine.theme.icon.IconSet; |
||||||
|
import com.fine.theme.icon.IconType; |
||||||
|
import com.fine.theme.icon.LazyIcon; |
||||||
|
import com.fr.base.extension.FileExtension; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import org.jetbrains.annotations.NotNull; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.lang.ref.WeakReference; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 管理插件图标集 |
||||||
|
* |
||||||
|
* @author lemon |
||||||
|
* @since |
||||||
|
* Created on 2024/08/23 |
||||||
|
*/ |
||||||
|
public class PluginIconManager { |
||||||
|
|
||||||
|
public static final String ICON_DISABLE_SUFFIX = "_disable"; |
||||||
|
public static final Dimension DEFAULT_DIMENSION = new Dimension(16, 16); |
||||||
|
private static final Map<String, IconSet> SOURCE_ICON_MAPS = new HashMap<>(2); |
||||||
|
private static final HashMap<String, HashMap<String, WeakReference<Icon>>> CACHE = new HashMap<>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 获取图标集 |
||||||
|
* |
||||||
|
* @param id 图标集ID |
||||||
|
* @return 图标集 |
||||||
|
*/ |
||||||
|
public static IconSet getSet(String source, String id) { |
||||||
|
IconSet set = SOURCE_ICON_MAPS.get(source); |
||||||
|
|
||||||
|
if (set != null && set.getId().equals(id)) { |
||||||
|
return set; |
||||||
|
} |
||||||
|
throw new IconException("[PluginIconManager] Can not find icon set by id: " + id); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 添加图标集 |
||||||
|
* |
||||||
|
* @param source 插件 |
||||||
|
* @param set 图标集 |
||||||
|
*/ |
||||||
|
public static void addSet(@NotNull String source, @NotNull IconSet set) { |
||||||
|
if (SOURCE_ICON_MAPS.containsKey(source)) { |
||||||
|
FineLoggerFactory.getLogger().warn("[PluginIconManager] plugin:{} icon set already exists: " + source); |
||||||
|
} |
||||||
|
SOURCE_ICON_MAPS.put(source, set); |
||||||
|
clearCacheBySource(source); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新指定插件图标集 |
||||||
|
* |
||||||
|
* @param source 插件 |
||||||
|
* @param set 图标集 |
||||||
|
*/ |
||||||
|
public static void updateSet(@NotNull String source, @NotNull IconSet set) { |
||||||
|
SOURCE_ICON_MAPS.put(source, set); |
||||||
|
clearCacheBySource(source); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除指定插件图标集 |
||||||
|
* |
||||||
|
* @param source 插件 |
||||||
|
*/ |
||||||
|
public static void removeSet(@NotNull String source) { |
||||||
|
SOURCE_ICON_MAPS.remove(source); |
||||||
|
clearCacheBySource(source); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据图标ID获取图标 |
||||||
|
* <p> |
||||||
|
* 查找路径 |
||||||
|
* 1)查找图集图标 |
||||||
|
* 2)路径为图片图标,从路径再查找 |
||||||
|
* 3)提供默认svg图标 |
||||||
|
* |
||||||
|
* @param id 图标ID |
||||||
|
* @param <I> 图标类型 |
||||||
|
* @return 图标 |
||||||
|
*/ |
||||||
|
@NotNull |
||||||
|
public static <I extends Icon> I getIcon(@NotNull String source, @NotNull final String id, @NotNull Dimension dimension, @NotNull IconType type) { |
||||||
|
Icon icon = findIcon(source, id, dimension, type); |
||||||
|
if (icon == null) { |
||||||
|
// 只有找不到再进行其他fallback,提升效率
|
||||||
|
if (IconManager.isImageIcon(id)) { |
||||||
|
return (I) fallbackLegacyIcon(id); |
||||||
|
} else { |
||||||
|
FineLoggerFactory.getLogger().warn("[PluginIconManager] Can not find icon by id: " + id); |
||||||
|
return (I) new LazyIcon("default"); |
||||||
|
} |
||||||
|
} |
||||||
|
return (I) icon; |
||||||
|
} |
||||||
|
|
||||||
|
private static Icon fallbackLegacyIcon(String id) { |
||||||
|
return IOUtils.readIcon(id); |
||||||
|
} |
||||||
|
|
||||||
|
@Nullable |
||||||
|
private static <I extends Icon> I findIcon(String source, String id, Dimension dimension, IconType type) { |
||||||
|
String cacheKey = genCacheKey(source, id, dimension, type); |
||||||
|
HashMap<String, WeakReference<Icon>> sourceCache = CACHE.getOrDefault(cacheKey, new HashMap<>(64)); |
||||||
|
final WeakReference<Icon> reference = sourceCache.get(cacheKey); |
||||||
|
I icon = reference != null ? (I) reference.get() : null; |
||||||
|
if (icon == null) { |
||||||
|
IconSet set = SOURCE_ICON_MAPS.get(source); |
||||||
|
if (set == null) { |
||||||
|
return icon; |
||||||
|
} |
||||||
|
Icon f = set.findIcon(id, dimension, type); |
||||||
|
if (f != null) { |
||||||
|
icon = (I) f; |
||||||
|
sourceCache.put(cacheKey, new WeakReference<>(icon)); |
||||||
|
CACHE.put(source, sourceCache); |
||||||
|
} |
||||||
|
} |
||||||
|
return icon; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 生成缓存key |
||||||
|
* |
||||||
|
* @param id id |
||||||
|
* @param dimension 尺寸 |
||||||
|
* @param type 图标类型 |
||||||
|
* @return 缓存key |
||||||
|
*/ |
||||||
|
public static @NotNull String genCacheKey(String source, String id, Dimension dimension, IconType type) { |
||||||
|
if (DEFAULT_DIMENSION.equals(dimension)) { |
||||||
|
return source + "_" + id + "_" + type; |
||||||
|
} |
||||||
|
return source + "_" + id + "_" + dimension.width + "_" + dimension.height + "_" + type; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否SVG图标格式 |
||||||
|
* |
||||||
|
* @param path 路径 |
||||||
|
* @return 是否SVG图标格式 |
||||||
|
*/ |
||||||
|
public static boolean isSvgIcon(String path) { |
||||||
|
return FileExtension.SVG.matchExtension(path); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否支持的图片图标格式,目前只支持png和jpg |
||||||
|
* |
||||||
|
* @param path 路径 |
||||||
|
* @return 是否支持的图片图标格式 |
||||||
|
*/ |
||||||
|
public static boolean isImageIcon(String path) { |
||||||
|
return FileExtension.PNG.matchExtension(path) |
||||||
|
|| FileExtension.JPG.matchExtension(path); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断是否存在指定id的icon,非io读取行为,而是从已注册的sourceMap中遍历判断 |
||||||
|
* |
||||||
|
* @param id id |
||||||
|
* @return 是否存在 |
||||||
|
*/ |
||||||
|
public static boolean existIcon(String id, String source) { |
||||||
|
IconSet set = SOURCE_ICON_MAPS.get(source); |
||||||
|
if (set != null && set.getIds().contains(id)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 清理所有缓存 |
||||||
|
*/ |
||||||
|
public static void clearCache() { |
||||||
|
CACHE.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 清楚指定插件缓存 |
||||||
|
* @param source 插件标识 |
||||||
|
*/ |
||||||
|
public static void clearCacheBySource(String source) { |
||||||
|
CACHE.remove(source); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 查找灰化图标 |
||||||
|
* |
||||||
|
* @param path 原始路径 |
||||||
|
* @return 灰化路径 |
||||||
|
*/ |
||||||
|
public static String findDisablePath(String path) { |
||||||
|
int i = path.lastIndexOf('.'); |
||||||
|
return path.substring(0, i) + ICON_DISABLE_SUFFIX + path.substring(i); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,136 @@ |
|||||||
|
package com.fine.theme.icon.plugin; |
||||||
|
|
||||||
|
import com.fine.theme.icon.AbstractIconSet; |
||||||
|
import com.fine.theme.icon.IconManager; |
||||||
|
import com.fine.theme.icon.IconType; |
||||||
|
import com.formdev.flatlaf.json.Json; |
||||||
|
import com.formdev.flatlaf.json.ParseException; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.io.Reader; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* 插件图标集 |
||||||
|
* |
||||||
|
* @author lemon |
||||||
|
* @since |
||||||
|
* Created on 2024/08/20 |
||||||
|
*/ |
||||||
|
public class PluginIconSet extends AbstractIconSet { |
||||||
|
|
||||||
|
private String base; |
||||||
|
|
||||||
|
|
||||||
|
public PluginIconSet(PluginUrlIconResource resource, Map<String, String> iconId2Path) { |
||||||
|
addIconWithMap(iconId2Path); |
||||||
|
|
||||||
|
if (resource.getPath() == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
Map<String, Object> json; |
||||||
|
try (InputStream in = resource.getInputStream()) { |
||||||
|
try (Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8)) { |
||||||
|
json = (Map<String, Object>) Json.parse(reader); |
||||||
|
} |
||||||
|
} catch (ParseException | IOException ex) { |
||||||
|
throw new RuntimeException(ex.getMessage(), ex); |
||||||
|
} |
||||||
|
|
||||||
|
name = (String) json.get("name"); |
||||||
|
dark = Boolean.parseBoolean((String) json.get("dark")); |
||||||
|
base = (String) json.get("base"); |
||||||
|
if (base == null) { |
||||||
|
base = StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
Map<String, Object> icons = (Map<String, Object>) json.get("icons"); |
||||||
|
|
||||||
|
for (Map.Entry<String, Object> icon : icons.entrySet()) { |
||||||
|
applyIcon(icon.getKey(), icon.getValue()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void applyIcon(String key, Object value) { |
||||||
|
if (value instanceof String) { |
||||||
|
dealWithIconString(key, (String) value); |
||||||
|
} else if (value instanceof Map) { |
||||||
|
dealWithIconMap(key, (Map<String, Object>) value); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void dealWithIconString(String key, String value) { |
||||||
|
if (IconManager.isSvgIcon(value)) { |
||||||
|
// 默认字符串提供正常图和灰化图
|
||||||
|
addIcon(new PluginSvgIconSource(key, |
||||||
|
base + value, |
||||||
|
IconManager.findDisablePath(base + value), |
||||||
|
null |
||||||
|
)); |
||||||
|
} else if (IconManager.isImageIcon(value)) { |
||||||
|
addIcon(new PluginImageIconSource(key, base + value)); |
||||||
|
} |
||||||
|
// 其他无法识别格式不处理
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 处理object形式的icon配置 |
||||||
|
*/ |
||||||
|
private void dealWithIconMap(String key, Map<String, Object> value) { |
||||||
|
String normalPath = (String) value.get(IconType.normal.name()); |
||||||
|
String disablePath = (String) value.get(IconType.disable.name()); |
||||||
|
String whitePath = (String) value.get(IconType.white.name()); |
||||||
|
// 暂不支持混合格式,每个id的格式需要保持一致
|
||||||
|
if (IconManager.isSvgIcon(normalPath)) { |
||||||
|
addIcon(new PluginSvgIconSource(key, |
||||||
|
base + normalPath, |
||||||
|
StringUtils.isNotBlank(disablePath) ? base + disablePath : null, |
||||||
|
StringUtils.isNotBlank(whitePath) ? base + whitePath : null |
||||||
|
)); |
||||||
|
} else if (IconManager.isImageIcon(normalPath)) { |
||||||
|
addIcon(new PluginImageIconSource(key, |
||||||
|
base + normalPath, |
||||||
|
StringUtils.isNotBlank(disablePath) ? base + disablePath : null, |
||||||
|
StringUtils.isNotBlank(whitePath) ? base + whitePath : null |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据 map 注册图标 |
||||||
|
* @param iconId2Path key: id, value: icon path |
||||||
|
*/ |
||||||
|
public void addIconWithMap(Map<String, String> iconId2Path) { |
||||||
|
for (Map.Entry<String, String> entry: iconId2Path.entrySet()) { |
||||||
|
if (PluginIconManager.isSvgIcon(entry.getValue())) { |
||||||
|
addIcon(new PluginSvgIconSource(entry.getKey(), entry.getValue())); |
||||||
|
} else if (PluginIconManager.isImageIcon(entry.getValue())) { |
||||||
|
addIcon(new PluginImageIconSource(entry.getKey(), entry.getValue())); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean equals(Object o) { |
||||||
|
if (this == o) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (o == null || getClass() != o.getClass()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
PluginIconSet that = (PluginIconSet) o; |
||||||
|
return Objects.equals(name, that.name); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() { |
||||||
|
return Objects.hashCode(name); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,129 @@ |
|||||||
|
package com.fine.theme.icon.plugin; |
||||||
|
|
||||||
|
import com.fine.theme.icon.DisabledIcon; |
||||||
|
import com.fine.theme.icon.IconManager; |
||||||
|
import com.fine.theme.icon.IconType; |
||||||
|
import com.fine.theme.icon.Identifiable; |
||||||
|
import com.fine.theme.icon.WhiteIcon; |
||||||
|
import com.fr.design.fun.impl.AbstractLazyIconProvider; |
||||||
|
import org.jetbrains.annotations.NotNull; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.awt.Graphics; |
||||||
|
import java.util.StringJoiner; |
||||||
|
|
||||||
|
import static com.fine.theme.utils.FineUIScale.scale; |
||||||
|
|
||||||
|
public class PluginLazyIcon implements Identifiable, DisabledIcon, WhiteIcon, Icon { |
||||||
|
@NotNull |
||||||
|
private final String id; |
||||||
|
|
||||||
|
private final Dimension dimension; |
||||||
|
|
||||||
|
private final IconType type; |
||||||
|
|
||||||
|
private final String source; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @param source {@link AbstractLazyIconProvider#source()} |
||||||
|
* @param id |
||||||
|
*/ |
||||||
|
public PluginLazyIcon(@NotNull final String source, @NotNull final String id) { |
||||||
|
this.id = id; |
||||||
|
this.dimension = IconManager.DEFAULT_DIMENSION; |
||||||
|
this.type = IconType.normal; |
||||||
|
this.source = source; |
||||||
|
} |
||||||
|
|
||||||
|
public PluginLazyIcon(@NotNull final String source, @NotNull final String id, int side) { |
||||||
|
this.id = id; |
||||||
|
this.dimension = new Dimension(side, side); |
||||||
|
this.type = IconType.normal; |
||||||
|
this.source = source; |
||||||
|
} |
||||||
|
|
||||||
|
public PluginLazyIcon(@NotNull final String source, @NotNull final String id, @NotNull Dimension dimension) { |
||||||
|
this.id = id; |
||||||
|
this.dimension = dimension; |
||||||
|
this.type = IconType.normal; |
||||||
|
this.source = source; |
||||||
|
} |
||||||
|
|
||||||
|
private PluginLazyIcon(@NotNull final String source, @NotNull final String id, @NotNull IconType type) { |
||||||
|
this.id = id; |
||||||
|
this.dimension = IconManager.DEFAULT_DIMENSION; |
||||||
|
this.type = type; |
||||||
|
this.source = source; |
||||||
|
} |
||||||
|
|
||||||
|
public PluginLazyIcon(@NotNull final String source, @NotNull final String id, @NotNull Dimension dimension, @NotNull IconType type) { |
||||||
|
this.id = id; |
||||||
|
this.dimension = dimension; |
||||||
|
this.type = type; |
||||||
|
this.source = source; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@NotNull |
||||||
|
@Override |
||||||
|
public String getId() { |
||||||
|
return id; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paintIcon(@NotNull final Component c, @NotNull final Graphics g, final int x, final int y) { |
||||||
|
getIcon().paintIcon(c, g, x, y); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getIconWidth() { |
||||||
|
return scale(dimension.width); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getIconHeight() { |
||||||
|
return scale(dimension.height); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@NotNull |
||||||
|
public <I extends Icon> I getIcon() { |
||||||
|
return PluginIconManager.getIcon(source, getId(), dimension, type); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建一份灰化图标 |
||||||
|
* |
||||||
|
* @return 灰化图标 |
||||||
|
*/ |
||||||
|
@NotNull |
||||||
|
@Override |
||||||
|
public Icon disabled() { |
||||||
|
return new PluginLazyIcon(source, getId(), dimension, IconType.disable); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建一份白化图标 |
||||||
|
* |
||||||
|
* @return 白化图标 |
||||||
|
*/ |
||||||
|
@NotNull |
||||||
|
@Override |
||||||
|
public Icon white() { |
||||||
|
return new PluginLazyIcon(source, getId(), dimension, IconType.white); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return new StringJoiner(", ", PluginLazyIcon.class.getSimpleName() + "[", "]") |
||||||
|
.add("source='" + source + "'") |
||||||
|
.add("id='" + id + "'") |
||||||
|
.add("size=" + "[w=" + scale(dimension.width) + ",h=" + scale(dimension.height) + "]") |
||||||
|
.add("type=" + type) |
||||||
|
.toString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,68 @@ |
|||||||
|
package com.fr.design.fun; |
||||||
|
|
||||||
|
import com.fr.stable.fun.mark.Mutable; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 插件图标适配接口 |
||||||
|
* |
||||||
|
* @author lemon |
||||||
|
* @since |
||||||
|
* Created on |
||||||
|
*/ |
||||||
|
public interface LazyIconProvider extends Mutable { |
||||||
|
String MARK_STRING = "LazyIconProvider"; |
||||||
|
|
||||||
|
int CURRENT_LEVEL = 1; |
||||||
|
|
||||||
|
/** |
||||||
|
* 自定义,icon 来源标识 |
||||||
|
* |
||||||
|
* @return 来源标识 |
||||||
|
*/ |
||||||
|
String source(); |
||||||
|
|
||||||
|
/** |
||||||
|
* json 文件路径 |
||||||
|
* |
||||||
|
* @return 图标注册 json 路径 |
||||||
|
*/ |
||||||
|
String jsonPath(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 图标所属主题分类 |
||||||
|
* |
||||||
|
* @return 主题类别 |
||||||
|
*/ |
||||||
|
THEME themeCategory(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 构建需要注册的图标 key: id, value: icon path |
||||||
|
* @return map |
||||||
|
*/ |
||||||
|
Map<String, String> iconId2Path(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 图标主题 |
||||||
|
*/ |
||||||
|
enum THEME { |
||||||
|
|
||||||
|
/** |
||||||
|
* light_icon |
||||||
|
*/ |
||||||
|
LIGHT_ICON("light_icon"), |
||||||
|
|
||||||
|
/** |
||||||
|
* dark_icon |
||||||
|
*/ |
||||||
|
DARK_ICON("dark_icon") |
||||||
|
; |
||||||
|
|
||||||
|
final String category; |
||||||
|
THEME(String category) { |
||||||
|
this.category = category; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
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.io.UnsupportedEncodingException; |
||||||
|
import java.net.URLDecoder; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 插件图标 LazyIcon 加载适配抽象类 |
||||||
|
* |
||||||
|
* @author lemon |
||||||
|
* @since |
||||||
|
* Created on |
||||||
|
*/ |
||||||
|
@API(level = LazyIconProvider.CURRENT_LEVEL) |
||||||
|
public class AbstractLazyIconProvider extends AbstractProvider implements LazyIconProvider { |
||||||
|
|
||||||
|
/** |
||||||
|
* 当前接口的API等级,用于判断是否需要升级插件 |
||||||
|
* @return API等级 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 区分插件 |
||||||
|
* |
||||||
|
* @return 插件 id |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public String source() { |
||||||
|
throw new RuntimeException("source is blank"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过 json 注册图标 |
||||||
|
* |
||||||
|
* @return 图标注册 json 路径 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public String jsonPath() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 图标主题 {@link THEME} |
||||||
|
* |
||||||
|
* @return 主题类别 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public THEME themeCategory() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 直接注册图标:key 是 icon id, value 是 icon path |
||||||
|
* |
||||||
|
* @return map |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public Map<String, String> iconId2Path() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue