renekton
2 months ago
71 changed files with 893 additions and 369 deletions
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
|
||||||
|
} |
@ -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 ""; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,167 @@ |
|||||||
|
package com.fr.file; |
||||||
|
|
||||||
|
import com.fr.decision.webservice.bean.entry.FileNodeBean; |
||||||
|
import com.fr.file.filetree.FileNode; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.CoreConstants; |
||||||
|
import com.fr.stable.StableUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.project.ProjectConstants; |
||||||
|
import com.fr.workspace.server.repository.tabledata.TableDataRepository; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* CA证书文件相关 |
||||||
|
* |
||||||
|
* @author Destiny.Lin |
||||||
|
* @since 11.0 |
||||||
|
* Created on 2024/9/8 |
||||||
|
*/ |
||||||
|
public class FileCAFILE extends FileNodeFILE{ |
||||||
|
public static final String ROOT = ProjectConstants.CERTIFICATES_DIRECTORY; |
||||||
|
private List<FileCAFILE> children = new ArrayList<>(); |
||||||
|
private boolean builded = false; |
||||||
|
private String id = StringUtils.EMPTY; |
||||||
|
|
||||||
|
public FileCAFILE(FileNode node) { |
||||||
|
super(node); |
||||||
|
} |
||||||
|
|
||||||
|
public FileCAFILE(FileNode node, boolean builded, String id) { |
||||||
|
super(node); |
||||||
|
this.builded = builded; |
||||||
|
this.id = id; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 添加子 |
||||||
|
*/ |
||||||
|
private void addChild(FileCAFILE file) { |
||||||
|
children.add(file); |
||||||
|
} |
||||||
|
|
||||||
|
public List<FileCAFILE> getChildren() { |
||||||
|
return children; |
||||||
|
} |
||||||
|
|
||||||
|
public void setChildren(List<FileCAFILE> children) { |
||||||
|
this.children = children; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isBuilded() { |
||||||
|
return builded; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBuilded(boolean builded) { |
||||||
|
this.builded = builded; |
||||||
|
} |
||||||
|
|
||||||
|
public String getId() { |
||||||
|
return id; |
||||||
|
} |
||||||
|
|
||||||
|
public void setId(String id) { |
||||||
|
this.id = id; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public FILE[] listFiles() { |
||||||
|
|
||||||
|
if (ComparatorUtils.equals(node, null)) { |
||||||
|
node = new FileNode(CoreConstants.SEPARATOR, true); |
||||||
|
} |
||||||
|
if (!node.isDirectory()) { |
||||||
|
return new FILE[]{this}; |
||||||
|
} |
||||||
|
try { |
||||||
|
FileCAFILE root = null; |
||||||
|
if (!this.builded) { |
||||||
|
root = buildTree(); |
||||||
|
FileCAFILE dataFILE = root.getFileCAFILE(this.id); |
||||||
|
this.setChildren(dataFILE.getChildren()); |
||||||
|
this.builded = true; |
||||||
|
} |
||||||
|
return this.getChildren().toArray(new FILE[0]); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
return new FILE[0]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private List<FileNodeBean> getBeans() { |
||||||
|
try { |
||||||
|
return TableDataRepository.getInstance().getCertificatesFile(StringUtils.EMPTY); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 递归获取指定id的文件 |
||||||
|
*/ |
||||||
|
public FileCAFILE getFileCAFILE(String id) { |
||||||
|
if (StringUtils.equals(this.id, id) || StringUtils.equals(StableUtils.pathJoin(this.id, StringUtils.EMPTY), id)) { |
||||||
|
return this; |
||||||
|
} |
||||||
|
for (FileCAFILE file : getChildren()) { |
||||||
|
return file.getFileCAFILE(id); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private FileCAFILE buildTree() { |
||||||
|
List<FileNodeBean> beans = getBeans(); |
||||||
|
Map<String, FileCAFILE> tree = new HashMap<>(); |
||||||
|
FileCAFILE root = null; |
||||||
|
// id , 父
|
||||||
|
for (FileNodeBean bean : beans) { |
||||||
|
FileNode fileNode = new FileNode(); |
||||||
|
fileNode.setEnvPath(bean.getPath()); |
||||||
|
fileNode.setDirectory(bean.getIsParent()); |
||||||
|
tree.putIfAbsent(bean.getId(), new FileCAFILE(fileNode, true, bean.getId())); |
||||||
|
if (StringUtils.isEmpty(bean.getpId())) { |
||||||
|
root = tree.get(bean.getId()); |
||||||
|
} else { |
||||||
|
tree.putIfAbsent(bean.getpId(), createParent(bean.getpId(), beans)); |
||||||
|
FileCAFILE file = tree.get(bean.getpId()); |
||||||
|
if (file != null) { |
||||||
|
file.addChild(tree.get(bean.getId())); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
for (Map.Entry<String, FileCAFILE> entry : tree.entrySet()) { |
||||||
|
if (entry.getKey().endsWith(ROOT)) { |
||||||
|
root = entry.getValue(); |
||||||
|
root.setId(StableUtils.pathJoin(ProjectConstants.RESOURCES_NAME, ProjectConstants.CERTIFICATES_DIRECTORY)); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
return root; |
||||||
|
} |
||||||
|
|
||||||
|
private FileCAFILE createParent(String s, List<FileNodeBean> beans) { |
||||||
|
for (FileNodeBean bean : beans) { |
||||||
|
if (StringUtils.equals(bean.getId(), s)) { |
||||||
|
FileNode fileNode = new FileNode(); |
||||||
|
fileNode.setEnvPath(bean.getPath()); |
||||||
|
fileNode.setDirectory(bean.getIsParent()); |
||||||
|
return new FileCAFILE(fileNode, true, bean.getId()); |
||||||
|
} |
||||||
|
} |
||||||
|
FileNode fileNode = new FileNode(); |
||||||
|
fileNode.setEnvPath(s); |
||||||
|
fileNode.setDirectory(true); |
||||||
|
return new FileCAFILE(fileNode, true, ROOT); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String prefix() { |
||||||
|
return FILEFactory.FILE_CA_PREFIX; |
||||||
|
} |
||||||
|
|
||||||
|
} |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.0 KiB |
Loading…
Reference in new issue