初步增加插件系统

This commit is contained in:
许轲 2023-09-07 02:35:43 +08:00
parent 5cd4cb85c1
commit 0c27ea4323
9 changed files with 164 additions and 89 deletions

View File

@ -1,9 +0,0 @@
package org.jcnc.jnotepad.plgin;
/**
* @author luke
*/
public interface Plugin extends PluginCategory {
String getDisplayName();
void execute();
}

View File

@ -1,8 +0,0 @@
package org.jcnc.jnotepad.plgin;
/**
* @author luke
*/
public interface PluginCategory {
String getCategoryName();
}

View File

@ -1,55 +0,0 @@
package org.jcnc.jnotepad.plgin;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author luke
*/
public class PluginManager {
private final List<Plugin> plugins;
private final Map<String, List<String>> categories;
public PluginManager() {
plugins = new ArrayList<>();
categories = new HashMap<>();
}
public void loadPlugins(String pluginFilePath) {
try {
File file = new File(pluginFilePath);
if (file.exists() && file.isFile()) {
// 创建URLClassLoader以加载Jar文件中的类
URLClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()});
Class<?> pluginClass = classLoader.loadClass("org.jcnc.jnotepad.plgin.ButtonPlugin");
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);
} else {
System.err.println("Plugin file not found: " + pluginFilePath);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void executePlugins() {
for (Plugin plugin : plugins) {
plugin.execute();
}
}
public Map<String, List<String>> getLoadedPluginsByCategory() {
return categories;
}
}

View File

@ -1,9 +1,12 @@
package org.jcnc.jnotepad.plgin;
package org.jcnc.jnotepad.plugin;
/**
* 新按钮插件
*
* @author luke
*/
public class ButtonPlugin implements Plugin {
@Override
public String getCategoryName() {
return "新按钮插件";
@ -19,4 +22,4 @@ public class ButtonPlugin implements Plugin {
// 在这里实现新按钮插件的逻辑
System.out.println("新按钮插件执行了!");
}
}
}

View File

@ -0,0 +1,23 @@
package org.jcnc.jnotepad.plugin;
/**
* 插件接口
* <p>
* 描述插件的基本功能
*
* @author luke
*/
public interface Plugin extends PluginCategory {
/**
* 获取插件的显示名称
*
* @return 插件的显示名称
*/
String getDisplayName();
/**
* 执行插件的逻辑
*/
void execute();
}

View File

@ -0,0 +1,18 @@
package org.jcnc.jnotepad.plugin;
/**
* 插件类别接口
* <p>
* 描述插件的类别信息
*
* @author luke
*/
public interface PluginCategory {
/**
* 获取插件类别的名称
*
* @return 插件类别的名称
*/
String getCategoryName();
}

View File

@ -1,6 +1,5 @@
package org.jcnc.jnotepad.plgin;
package org.jcnc.jnotepad.plugin;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
@ -13,10 +12,19 @@ import java.util.List;
import java.util.Map;
/**
* 插件演示类
* <p>
* 用于演示插件加载和执行的界面
*
* @author luke
*/
public class PluginDemo {
public class PluginDemo {
/**
* 启动插件演示界面
*
* @param primaryStage JavaFX的主舞台
*/
public void start(Stage primaryStage) {
PluginManager pluginManager = new PluginManager();
@ -25,17 +33,7 @@ public class PluginDemo {
new FileChooser.ExtensionFilter("JAR Files", "*.jar")
);
Button loadButton = new Button("加载插件");
loadButton.setOnAction(event -> {
File selectedFile = fileChooser.showOpenDialog(primaryStage);
if (selectedFile != null) {
String pluginFilePath = selectedFile.getAbsolutePath();
pluginManager.loadPlugins(pluginFilePath);
// 更新插件信息显示
displayPluginInfo(primaryStage, pluginManager);
}
});
Button loadButton = createLoadButton(primaryStage, fileChooser, pluginManager);
Button executeButton = new Button("执行插件");
executeButton.setOnAction(event -> pluginManager.executePlugins());
@ -47,6 +45,38 @@ 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();
pluginManager.loadPlugins(pluginFilePath);
// 更新插件信息显示
displayPluginInfo(primaryStage, pluginManager);
}
} catch (Exception ignored) {
}
});
return loadButton;
}
/**
* 显示已加载插件的信息
*
* @param primaryStage JavaFX的主舞台
* @param pluginManager 插件管理器
*/
private void displayPluginInfo(Stage primaryStage, PluginManager pluginManager) {
Map<String, List<String>> loadedPluginsByCategory = pluginManager.getLoadedPluginsByCategory();
VBox infoBox = new VBox();

View File

@ -0,0 +1,73 @@
package org.jcnc.jnotepad.plugin;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 插件管理器
* <p>
* 该类用于管理插件的加载和执行
* 插件可以通过加载外部JAR文件中的类来扩展应用程序的功能
*
* @author luke
*/
public class PluginManager {
private final List<Plugin> plugins;
private final Map<String, List<String>> categories;
/**
* 构造方法初始化插件列表和类别映射
*/
public PluginManager() {
plugins = new ArrayList<>();
categories = new HashMap<>();
}
/**
* 加载插件
*
* @param pluginFilePath 插件文件的路径
* @throws Exception 如果加载插件时发生异常
*/
public void loadPlugins(String pluginFilePath) throws Exception {
File file = new File(pluginFilePath);
if (file.exists() && file.isFile()) {
// 创建URLClassLoader以加载Jar文件中的类
URLClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()});
Class<?> pluginClass = classLoader.loadClass("org.jcnc.jnotepad.plugin.ButtonPlugin");
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);
} else {
System.err.println("Plugin file not found: " + pluginFilePath);
}
}
/**
* 执行加载的插件
*/
public void executePlugins() {
for (Plugin plugin : plugins) {
plugin.execute();
}
}
/**
* 获取按类别分类的已加载插件
*
* @return 插件类别映射
*/
public Map<String, List<String>> getLoadedPluginsByCategory() {
return categories;
}
}

View File

@ -10,7 +10,7 @@ import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.controller.event.handler.menubar.*;
import org.jcnc.jnotepad.controller.event.handler.tool.SetBtn;
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
import org.jcnc.jnotepad.plgin.PluginDemo;
import org.jcnc.jnotepad.plugin.PluginDemo;
import org.jcnc.jnotepad.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.root.center.main.center.tab.CenterTabPane;
import org.jcnc.jnotepad.root.left.sidebar.tools.SidebarToolBar;