diff --git a/src/main/java/org/jcnc/jnotepad/LunchApp.java b/src/main/java/org/jcnc/jnotepad/LunchApp.java index ec1cd1d..ddb45f8 100644 --- a/src/main/java/org/jcnc/jnotepad/LunchApp.java +++ b/src/main/java/org/jcnc/jnotepad/LunchApp.java @@ -10,8 +10,11 @@ import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.common.constants.AppConstants; import org.jcnc.jnotepad.common.constants.TextConstants; import org.jcnc.jnotepad.common.manager.ThreadPoolManager; +import org.jcnc.jnotepad.controller.ResourceController; +import org.jcnc.jnotepad.controller.config.AppConfigController; import org.jcnc.jnotepad.controller.i18n.LocalizationController; import org.jcnc.jnotepad.controller.manager.Controller; +import org.jcnc.jnotepad.plugin.PluginManager; import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.views.manager.ViewManager; @@ -64,6 +67,7 @@ public class LunchApp extends Application { @Override public void start(Stage primaryStage) { SCENE.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/css/styles.css")).toExternalForm()); + // 初始化UI组件 initUiComponents(); UiResourceBundle.bindStringProperty(primaryStage.titleProperty(), TextConstants.TITLE); @@ -83,7 +87,8 @@ public class LunchApp extends Application { // 2. 加载组件 ViewManager viewManager = ViewManager.getInstance(SCENE); viewManager.initScreen(SCENE); - + // 3. 加载资源 + ResourceController.getInstance().loadResources(); // 使用线程池加载关联文件并创建文本区域 List rawParameters = getParameters().getRaw(); Controller.getInstance().openAssociatedFileAndCreateTextArea(rawParameters); @@ -91,6 +96,10 @@ public class LunchApp extends Application { @Override public void stop() { + AppConfigController instance = AppConfigController.getInstance(); + // 刷新插件配置文件 + instance.getAppConfig().setPlugins(PluginManager.getInstance().getPluginInfos()); + instance.writeAppConfig(); // 关闭线程池 threadPool.shutdownNow(); } diff --git a/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java b/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java index 010f312..5f85ab2 100644 --- a/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java +++ b/src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java @@ -1,6 +1,7 @@ package org.jcnc.jnotepad.app.config; import com.fasterxml.jackson.annotation.JsonIgnore; +import org.jcnc.jnotepad.model.entity.PluginInfo; import org.jcnc.jnotepad.model.entity.ShortcutKey; import java.util.ArrayList; @@ -24,6 +25,8 @@ public class AppConfig { private boolean textWrap; private List shortcutKey; + private List plugins; + /** * 生成默认应用配置对象。 * @@ -43,11 +46,19 @@ public class AppConfig { shortcutKeys.add(createShortcutKey("openConfigItem", ALT_S)); shortcutKeys.add(createShortcutKey("addItem", "")); shortcutKeys.add(createShortcutKey("countItem", "")); - myData.setShortcutKey(shortcutKeys); + myData.setPlugins(new ArrayList<>()); return myData; } + public List getPlugins() { + return plugins; + } + + public void setPlugins(List plugins) { + this.plugins = plugins; + } + /** * 创建 ShortcutKey 对象。 * diff --git a/src/main/java/org/jcnc/jnotepad/controller/ResourceController.java b/src/main/java/org/jcnc/jnotepad/controller/ResourceController.java new file mode 100644 index 0000000..95749c6 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/controller/ResourceController.java @@ -0,0 +1,70 @@ +package org.jcnc.jnotepad.controller; + +import org.jcnc.jnotepad.controller.config.AppConfigController; +import org.jcnc.jnotepad.exception.AppException; +import org.jcnc.jnotepad.plugin.PluginLoader; +import org.jcnc.jnotepad.util.LogUtil; +import org.slf4j.Logger; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; + +/** + * 资源控制器:用于加载程序所需的资源 + * + * @author gewuyou + */ +public class ResourceController { + private static final ResourceController INSTANCE = new ResourceController(); + Logger logger = LogUtil.getLogger(this.getClass()); + + private ResourceController() { + } + + + public static ResourceController getInstance() { + return INSTANCE; + } + + public void loadResources() { + loadPlugins(); + } + + /** + * 装载插件 + * + * @since 2023/9/15 21:39 + */ + public void loadPlugins() { + // 扫描并装载插件 + scanLoadPlugins(AppConfigController.getInstance().getPlungsPath()); + } + + + /** + * 扫描插件 + * + * @param pluginsPath 插件路径 + * @apiNote 扫描所有插件,更新配置文件中的插件信息 + * @since 2023/9/16 0:21 + */ + + private void scanLoadPlugins(Path pluginsPath) { + if (!Files.isDirectory(pluginsPath)) { + try { + Files.createDirectory(pluginsPath); + } catch (IOException e) { + throw new AppException("这不是一个有效的路径!"); + } + } + // 获取插件加载器 + PluginLoader pluginLoader = PluginLoader.getInstance(); + try (Stream pathStream = Files.walk(pluginsPath)) { + pathStream.filter(path -> path.toString().endsWith(".jar")).forEach(path -> pluginLoader.loadPluginByPath(path.toString())); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } +} diff --git a/src/main/java/org/jcnc/jnotepad/controller/config/AppConfigController.java b/src/main/java/org/jcnc/jnotepad/controller/config/AppConfigController.java index e33b7a7..8e3f061 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/config/AppConfigController.java +++ b/src/main/java/org/jcnc/jnotepad/controller/config/AppConfigController.java @@ -32,10 +32,13 @@ public class AppConfigController { private static final Logger logger = LogUtil.getLogger(AppConfigController.class); private static final AppConfigController INSTANCE = new AppConfigController(); private AppConfig appConfig; - private String dir; + private static final String DEFAULT_PROPERTY = "user.home"; + private String appConfigDir; + private String pluginsDir; private AppConfigController() { - setDir(Paths.get(System.getProperty("user.home"), ".jnotepad").toString()); + setAppConfigDir(Paths.get(System.getProperty(DEFAULT_PROPERTY), ".jnotepad").toString()); + setPluginsDir(Paths.get(System.getProperty(DEFAULT_PROPERTY), ".jnotepad", "plugins").toString()); loadConfig(); } @@ -54,7 +57,6 @@ public class AppConfigController { public void loadConfig() { createConfigIfNotExists(); Path configPath = getConfigPath(); - try { logger.info("正在加载配置文件..."); // 存在则加载 @@ -82,7 +84,7 @@ public class AppConfigController { private void writeAppConfig(AppConfig appConfig) { try (BufferedWriter writer = new BufferedWriter(new FileWriter(getConfigPath().toString()))) { if (appConfig == null) { - appConfig = createShortcutKeyJson(); + appConfig = createConfigJson(); } writer.write(JsonUtil.toJsonString(appConfig)); } catch (Exception e) { @@ -99,7 +101,7 @@ public class AppConfigController { if (configPath.toFile().exists()) { return; } - File directory = new File(dir); + File directory = new File(appConfigDir); if (!directory.exists()) { directory.mkdirs(); } @@ -112,10 +114,14 @@ public class AppConfigController { * @return 配置文件的路径 */ public Path getConfigPath() { - return Paths.get(getDir(), CONFIG_NAME); + return Paths.get(getAppConfigDir(), CONFIG_NAME); } - private AppConfig createShortcutKeyJson() { + public Path getPlungsPath() { + return Paths.get(getPluginsDir()); + } + + private AppConfig createConfigJson() { return AppConfig.generateDefaultAppConfig(); } @@ -169,15 +175,23 @@ public class AppConfigController { * * @return 所在目录 */ - public String getDir() { - return dir; + public String getAppConfigDir() { + return appConfigDir; } - public void setDir(String dir) { - this.dir = dir; + public void setAppConfigDir(String appConfigDir) { + this.appConfigDir = appConfigDir; } - private AppConfig getAppConfig() { + public String getPluginsDir() { + return pluginsDir; + } + + public void setPluginsDir(String pluginsDir) { + this.pluginsDir = pluginsDir; + } + + public AppConfig getAppConfig() { return appConfig; } } diff --git a/src/main/java/org/jcnc/jnotepad/model/entity/PluginInfo.java b/src/main/java/org/jcnc/jnotepad/model/entity/PluginInfo.java index 42f1b6b..eb40f42 100644 --- a/src/main/java/org/jcnc/jnotepad/model/entity/PluginInfo.java +++ b/src/main/java/org/jcnc/jnotepad/model/entity/PluginInfo.java @@ -1,5 +1,8 @@ package org.jcnc.jnotepad.model.entity; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.jcnc.jnotepad.plugin.interfaces.Plugin; + /** * 插件信息 * @@ -18,11 +21,24 @@ public class PluginInfo { * 启用状态 */ private boolean enabled; + /** + * 作者名称 + */ + private String author; + /** + * 类别 + */ + private String category; /** * 主类名称 */ private String mainClass; + /** + * 插件类 + */ + @JsonIgnore + private Plugin plugin; public String getName() { return name; @@ -55,4 +71,28 @@ public class PluginInfo { public void setMainClass(String mainClass) { this.mainClass = mainClass; } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public Plugin getPlugin() { + return plugin; + } + + public void setPlugin(Plugin plugin) { + this.plugin = plugin; + } } diff --git a/src/main/java/org/jcnc/jnotepad/plugin/PluginLoader.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginLoader.java index 9bf5f37..eab9154 100644 --- a/src/main/java/org/jcnc/jnotepad/plugin/PluginLoader.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginLoader.java @@ -1,5 +1,6 @@ package org.jcnc.jnotepad.plugin; +import org.jcnc.jnotepad.controller.config.AppConfigController; import org.jcnc.jnotepad.exception.AppException; import org.jcnc.jnotepad.model.entity.PluginInfo; import org.jcnc.jnotepad.plugin.interfaces.Plugin; @@ -12,6 +13,7 @@ import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.jar.JarFile; @@ -31,7 +33,7 @@ public class PluginLoader { * * @param pluginJar jar 包 */ - private static PluginInfo readPlugin(File pluginJar) throws IOException { + public static PluginInfo readPlugin(File pluginJar) throws IOException { InputStream is; StringBuilder sb; try (JarFile jarFile = new JarFile(pluginJar)) { @@ -53,24 +55,103 @@ public class PluginLoader { return INSTANCE; } + /** + * 检查插件 + * + * @param configPluginInfos 配置文件插件信息 + * @param pluginInfo 插件信息类 + * @param pluginInfos 插件信息集合 + * @return boolean 是否检查通过 + * @apiNote + * @since 2023/9/16 14:04 + */ + private static boolean checkPlugin(List configPluginInfos, PluginInfo pluginInfo, List pluginInfos) { + // 如果应用程序配置文件为空则默认插件被禁用 + if (configPluginInfos.isEmpty()) { + return disabledByDefault(configPluginInfos, pluginInfo, pluginInfos); + } + // 如果应用程序配置文件中该插件禁用则不加载 + for (PluginInfo configPluginInfo : configPluginInfos) { + if (disableDoNotLoad(pluginInfo, pluginInfos, configPluginInfo)) { + return true; + } + } + // 判断该插件是否已经加载 + return loaded(pluginInfo, pluginInfos); + } + + private static boolean loaded(PluginInfo pluginInfo, List pluginInfos) { + Iterator iterator = pluginInfos.iterator(); + while (iterator.hasNext()) { + PluginInfo plugin = iterator.next(); + if ((plugin.getName() + plugin.getAuthor()).equals(pluginInfo.getName() + pluginInfo.getAuthor())) { + if (plugin.getVersion().equals(pluginInfo.getVersion())) { + return true; + } + // 如果当前插件版本更低则更新 + if (plugin.getVersion().compareTo(pluginInfo.getVersion()) < 0) { + // 删除当前的插件 + iterator.remove(); + } else { + throw new AppException("当前加载的插件版本低于本地版本!"); + } + } + } + return false; + } + + private static boolean disableDoNotLoad(PluginInfo pluginInfo, List pluginInfos, PluginInfo configPluginInfo) { + if ((configPluginInfo.getName() + configPluginInfo.getAuthor()).equals(pluginInfo.getName() + pluginInfo.getAuthor()) && !configPluginInfo.isEnabled()) { + pluginInfo.setEnabled(false); + pluginInfos.add(pluginInfo); + return true; + } + return false; + } + + private static boolean disabledByDefault(List configPluginInfos, PluginInfo pluginInfo, List pluginInfos) { + pluginInfo.setEnabled(false); + pluginInfos.add(pluginInfo); + configPluginInfos.add(pluginInfo); + AppConfigController.getInstance().writeAppConfig(); + return true; + } + /** * 加载插件 * * @param pluginFilePath 插件文件的路径 */ - public void loadPlugins(String pluginFilePath) { - PluginManager pluginManager = PluginManager.getInstance(); - List plugins = pluginManager.getPlugins(); - Map> categories = pluginManager.getLoadedPluginsByCategory(); - Map pluginInfos = pluginManager.getPluginInfos(); + public void loadPluginByPath(String pluginFilePath) { File file = new File(pluginFilePath); - if (file.exists() && file.isFile()) { + loadPluginByFile(file, AppConfigController.getInstance().getAppConfig().getPlugins()); + } + + /** + * 根据文件加载插件 + * + * @param pluginJar 插件jar包 + * @param configPluginInfos 配置文件插件信息集合 + * @apiNote + * @since 2023/9/16 14:05 + */ + public void loadPluginByFile(File pluginJar, List configPluginInfos) { + PluginManager pluginManager = PluginManager.getInstance(); + Map> categories = pluginManager.getLoadedPluginsByCategory(); + List pluginInfos = pluginManager.getPluginInfos(); + if (pluginJar.exists() && pluginJar.isFile()) { try { - PluginInfo pluginInfo = readPlugin(file); - pluginInfos.put(pluginInfo.getName(), pluginInfo); + PluginInfo pluginInfo = readPlugin(pluginJar); + // 检查插件状态 + if (checkPlugin(configPluginInfos, pluginInfo, pluginInfos)) { + return; + } + pluginInfo.setEnabled(true); + pluginInfos.add(pluginInfo); // 创建URLClassLoader以加载Jar文件中的类 Class pluginClass; - try (URLClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()})) { + try (URLClassLoader classLoader = new URLClassLoader(new URL[]{pluginJar.toURI().toURL()})) { + logger.info("{}", pluginInfo.getMainClass()); pluginClass = classLoader.loadClass(pluginInfo.getMainClass()); } if (pluginClass == null) { @@ -78,11 +159,8 @@ public class PluginLoader { } Plugin plugin; plugin = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); - plugins.add(plugin); - // 添加插件到类别中 - String categoryName = plugin.getCategoryName(); - String displayName = plugin.getDisplayName(); - categories.computeIfAbsent(categoryName, k -> new ArrayList<>()).add(displayName); + pluginInfo.setPlugin(plugin); + categories.computeIfAbsent(pluginInfo.getCategory(), k -> new ArrayList<>()).add(pluginInfo.getName()); } catch (IOException | InvocationTargetException | InstantiationException | IllegalAccessException e) { throw new AppException(e); } catch (ClassNotFoundException e) { @@ -92,7 +170,7 @@ public class PluginLoader { } } else { - LogUtil.getLogger(this.getClass()).info("PluginInfo file not found: {}", pluginFilePath); + LogUtil.getLogger(this.getClass()).info("PluginInfo file not found"); } } } diff --git a/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java index 380276a..0ff5fe6 100644 --- a/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java @@ -1,14 +1,22 @@ package org.jcnc.jnotepad.plugin; +import org.jcnc.jnotepad.common.manager.ThreadPoolManager; +import org.jcnc.jnotepad.controller.config.AppConfigController; import org.jcnc.jnotepad.model.entity.PluginInfo; -import org.jcnc.jnotepad.plugin.interfaces.Plugin; import org.jcnc.jnotepad.util.LogUtil; import org.slf4j.Logger; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Stream; + +import static org.jcnc.jnotepad.plugin.PluginLoader.readPlugin; /** * 插件管理器 @@ -21,10 +29,6 @@ import java.util.Map; public class PluginManager { private static final PluginManager INSTANCE = new PluginManager(); Logger logger = LogUtil.getLogger(this.getClass()); - /** - * 插件集合 - */ - private final List plugins = new ArrayList<>(); /** * 插件类别 */ @@ -32,8 +36,7 @@ public class PluginManager { /** * 插件信息 */ - - private final Map pluginInfos = new HashMap<>(); + private final List pluginInfos = new ArrayList<>(); private PluginManager() { @@ -47,30 +50,89 @@ public class PluginManager { /** * 卸载插件 * - * @param pluginClassName 插件类名 + * @param pluginInfo 插件信息类 * @since 2023/9/11 12:28 */ - public void unloadPlugin(String pluginClassName) { - //todo Unload the plugin and remove it from the list + public void unloadPlugin(PluginInfo pluginInfo) { + // 删除集合中的插件信息 + pluginInfos.remove(pluginInfo); + AppConfigController instance = AppConfigController.getInstance(); + instance.getAppConfig().getPlugins().remove(pluginInfo); + // 刷新配置 + instance.writeAppConfig(); + // 删除本地插件jar包 + Path plungsPath = instance.getPlungsPath(); + try (Stream pathStream = Files.walk(plungsPath)) { + pathStream.filter(path -> path.toString().endsWith(".jar")).forEach(path -> { + try { + File pluginJar = new File(path.toString()); + PluginInfo temp = readPlugin(pluginJar); + if ((temp.getName() + temp.getAuthor()).equals(pluginInfo.getName() + pluginInfo.getAuthor())) { + Files.delete(pluginJar.toPath()); + } + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + }); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + ThreadPoolManager.threadContSelfSubtracting(); } /** * 禁用插件 * - * @param pluginClassName 禁用某个插件 + * @param pluginInfo 需要禁用的某个插件的插件类 * @apiNote * @since 2023/9/11 12:34 */ - public void disablePlugIn(String pluginClassName) { - //todo Disable the plugin + public void disablePlugIn(PluginInfo pluginInfo) { + pluginInfo.setEnabled(false); + pluginInfo.setPlugin(null); + ThreadPoolManager.getThreadPool().submit(() -> { + AppConfigController instance = AppConfigController.getInstance(); + instance.getAppConfig().getPlugins().forEach(plugin -> { + if ((pluginInfo.getName() + pluginInfo.getAuthor()).equals(plugin.getName() + plugin.getAuthor())) { + plugin.setEnabled(false); + } + }); + instance.writeAppConfig(); + ThreadPoolManager.threadContSelfSubtracting(); + }); + } + + /** + * 初始化所有启用的插件 + */ + public void initializePlugins() { + for (PluginInfo pluginInfo : pluginInfos) { + if (pluginInfo.isEnabled()) { + pluginInfo.getPlugin().initialize(); + } + } + } + + /** + * 执行插件 + * + * @param pluginInfo 需要执行的插件的信息类 + * @apiNote + * @since 2023/9/16 14:58 + */ + public void executePlugin(PluginInfo pluginInfo) { + pluginInfo.getPlugin().execute(); } /** * 执行加载的插件 + * todo 待移除 */ public void executePlugins() { - for (Plugin plugin : plugins) { - plugin.execute(); + for (PluginInfo pluginInfo : pluginInfos) { + if (pluginInfo.isEnabled()) { + pluginInfo.getPlugin().execute(); + } } } @@ -83,11 +145,7 @@ public class PluginManager { return categories; } - public List getPlugins() { - return plugins; - } - - public Map getPluginInfos() { + public List getPluginInfos() { return pluginInfos; } } diff --git a/src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginManagerInterface.java similarity index 91% rename from src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java rename to src/main/java/org/jcnc/jnotepad/plugin/PluginManagerInterface.java index 8ce4d98..c8c945e 100644 --- a/src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginManagerInterface.java @@ -17,13 +17,14 @@ import java.util.List; import java.util.Map; /** - * 插件演示类 + * 插件管理界面 *

* 用于演示插件加载和执行的界面。 * - * @author luke + * @author luke gewuyou */ -public class PluginDemo { +public class PluginManagerInterface { + private static final PluginManagerInterface INSTANCE = new PluginManagerInterface(); Logger logger = LogUtil.getLogger(this.getClass()); /** @@ -53,34 +54,8 @@ public class PluginDemo { primaryStage.show(); } - /** - * 创建加载插件的按钮 - * - * @param primaryStage JavaFX的主舞台 - * @param fileChooser 文件选择器 - * @param pluginManager 插件管理器 - * @return 加载插件的按钮 - */ - private Button createLoadButton(Stage primaryStage, FileChooser fileChooser, PluginManager pluginManager) { - Button loadButton = new Button("加载插件"); - loadButton.setOnAction(event -> { - try { - File selectedFile = fileChooser.showOpenDialog(primaryStage); - if (selectedFile != null) { - String pluginFilePath = selectedFile.getAbsolutePath(); - PluginLoader.getInstance().loadPlugins(pluginFilePath); - - // 更新插件信息显示 - displayPluginInfo(primaryStage, pluginManager); - } else { - PopUpUtil.infoAlert(null, null, "未找到插件!", null, null); - logger.info("未找到插件!"); - } - } catch (Exception e) { - logger.error("加载插件失败!", e); - } - }); - return loadButton; + public static PluginManagerInterface getInstance() { + return INSTANCE; } /** @@ -109,4 +84,34 @@ public class PluginDemo { infoStage.initOwner(primaryStage); infoStage.show(); } + + /** + * 创建加载插件的按钮 + * + * @param primaryStage JavaFX的主舞台 + * @param fileChooser 文件选择器 + * @param pluginManager 插件管理器 + * @return 加载插件的按钮 + */ + private Button createLoadButton(Stage primaryStage, FileChooser fileChooser, PluginManager pluginManager) { + Button loadButton = new Button("加载插件"); + loadButton.setOnAction(event -> { + try { + File selectedFile = fileChooser.showOpenDialog(primaryStage); + if (selectedFile != null) { + String pluginFilePath = selectedFile.getAbsolutePath(); + PluginLoader.getInstance().loadPluginByPath(pluginFilePath); + + // 更新插件信息显示 + displayPluginInfo(primaryStage, pluginManager); + } else { + PopUpUtil.infoAlert(null, null, "未找到插件!", null, null); + logger.info("未找到插件!"); + } + } catch (Exception e) { + logger.error("加载插件失败!", e); + } + }); + return loadButton; + } } diff --git a/src/main/java/org/jcnc/jnotepad/plugin/interfaces/Plugin.java b/src/main/java/org/jcnc/jnotepad/plugin/interfaces/Plugin.java index c686453..905e7fa 100644 --- a/src/main/java/org/jcnc/jnotepad/plugin/interfaces/Plugin.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/interfaces/Plugin.java @@ -8,18 +8,9 @@ import java.util.Map; *

* 描述插件的基本功能。 * - * @author luke + * @author luke gewuyou */ -public interface Plugin extends PluginCategory { - - /** - * 获取插件的显示名称 - * - * @return 插件的显示名称 - */ - String getDisplayName(); - - +public interface Plugin { /** * 初始化插件 */ diff --git a/src/main/java/org/jcnc/jnotepad/plugin/interfaces/PluginCategory.java b/src/main/java/org/jcnc/jnotepad/plugin/interfaces/PluginCategory.java deleted file mode 100644 index ff37651..0000000 --- a/src/main/java/org/jcnc/jnotepad/plugin/interfaces/PluginCategory.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.jcnc.jnotepad.plugin.interfaces; - -/** - * 插件类别接口 - *

- * 描述插件的类别信息。 - * - * @author luke - */ -public interface PluginCategory { - - /** - * 获取插件类别的名称 - * - * @return 插件类别的名称 - */ - String getCategoryName(); -} diff --git a/src/main/java/org/jcnc/jnotepad/ui/setstage/SetStage.java b/src/main/java/org/jcnc/jnotepad/ui/setstage/SetStage.java index 206c816..82388bd 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/setstage/SetStage.java +++ b/src/main/java/org/jcnc/jnotepad/ui/setstage/SetStage.java @@ -12,6 +12,7 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.Stage; +import org.jcnc.jnotepad.plugin.PluginManagerInterface; import org.jcnc.jnotepad.ui.module.CustomSetButton; import org.jcnc.jnotepad.ui.module.SettingsComponent; import org.jcnc.jnotepad.util.UiUtil; @@ -31,6 +32,7 @@ public class SetStage extends Stage { public static final String GENERAL_SETTING_2 = "常规设置项2"; public static final String APPEARANCE_SETTING_1 = "外观设置项1"; public static final String APPEARANCE_SETTING_2 = "外观设置项2"; + public static final String PLUGINS = "插件"; public static final String SECURITY_SETTING_1 = "安全设置项1"; public static final String SECURITY_SETTING_2 = "安全设置项2"; @@ -92,7 +94,6 @@ public class SetStage extends Stage { applicationButton.getStyleClass().addAll(Styles.SMALL); bottomBox.getChildren().addAll(confirmButton, cancelButton, applicationButton); - BorderPane root = new BorderPane(); root.setCenter(splitPane); root.setBottom(bottomBox); @@ -136,6 +137,9 @@ public class SetStage extends Stage { TreeItem securityItem1 = new TreeItem<>("安全设置项1"); TreeItem securityItem2 = new TreeItem<>("安全设置项2"); + + TreeItem pluginsItem = new TreeItem<>(PLUGINS); + securityItem.getChildren().add(securityItem1); securityItem.getChildren().add(securityItem2); @@ -147,6 +151,7 @@ public class SetStage extends Stage { root.getChildren().add(appearanceItem); root.getChildren().add(securityItem); root.getChildren().add(developerItem); + root.getChildren().add(pluginsItem); TreeView treeView = new TreeView<>(root); treeView.setShowRoot(false); @@ -170,10 +175,21 @@ public class SetStage extends Stage { case SECURITY_SETTING_1 -> createSecuritySettingsLayout1(); case SECURITY_SETTING_2 -> createSecuritySettingsLayout2(); case DEVELOPER_DEBUG_PAGE -> createDevelopersDebugPageLayouts(); + case PLUGINS -> createPluginsLayout(); default -> null; }; } + private Node createPluginsLayout() { + VBox generalLayout = new VBox(10); + generalLayout.setPadding(new Insets(25)); + PluginManagerInterface pluginManagerInterface = new PluginManagerInterface(); + Stage stage = new Stage(); + stage.getIcons().add(UiUtil.getAppIcon()); + pluginManagerInterface.start(stage); + return generalLayout; + } + private Node createDevelopersDebugPageLayouts() { VBox generalLayout = new VBox(10); generalLayout.setPadding(new Insets(25)); diff --git a/src/main/java/org/jcnc/jnotepad/views/root/top/menu/TopMenuBar.java b/src/main/java/org/jcnc/jnotepad/views/root/top/menu/TopMenuBar.java index caa2ced..b581e4d 100644 --- a/src/main/java/org/jcnc/jnotepad/views/root/top/menu/TopMenuBar.java +++ b/src/main/java/org/jcnc/jnotepad/views/root/top/menu/TopMenuBar.java @@ -10,8 +10,9 @@ import org.jcnc.jnotepad.controller.event.handler.menubar.*; import org.jcnc.jnotepad.controller.event.handler.util.SetBtn; import org.jcnc.jnotepad.controller.i18n.LocalizationController; import org.jcnc.jnotepad.model.entity.ShortcutKey; -import org.jcnc.jnotepad.plugin.PluginDemo; +import org.jcnc.jnotepad.plugin.PluginManagerInterface; import org.jcnc.jnotepad.util.LogUtil; +import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane; import org.jcnc.jnotepad.views.root.left.sidebar.tools.SidebarToolBar; @@ -267,8 +268,10 @@ public class TopMenuBar extends MenuBar { addItem = new MenuItem(); addItem.setOnAction(event -> { - PluginDemo pluginDemo = new PluginDemo(); - pluginDemo.start(new Stage()); + PluginManagerInterface pluginManagerInterface = PluginManagerInterface.getInstance(); + Stage stage = new Stage(); + stage.getIcons().add(UiUtil.getAppIcon()); + pluginManagerInterface.start(stage); }); UiResourceBundle.bindStringProperty(addItem.textProperty(), ADD_PLUGIN); itemMap.put("addItem", addItem);