!96 初步实现插件功能

Merge pull request !96 from 格物方能致知/develop
This commit is contained in:
Luke 2023-09-16 15:20:35 +00:00 committed by Gitee
commit 850e5b509f
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
12 changed files with 391 additions and 114 deletions

View File

@ -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<String> 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();
}

View File

@ -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> shortcutKey;
private List<PluginInfo> 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<PluginInfo> getPlugins() {
return plugins;
}
public void setPlugins(List<PluginInfo> plugins) {
this.plugins = plugins;
}
/**
* 创建 ShortcutKey 对象
*

View File

@ -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<Path> 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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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<PluginInfo> configPluginInfos, PluginInfo pluginInfo, List<PluginInfo> 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<PluginInfo> pluginInfos) {
Iterator<PluginInfo> 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<PluginInfo> 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<PluginInfo> configPluginInfos, PluginInfo pluginInfo, List<PluginInfo> 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<Plugin> plugins = pluginManager.getPlugins();
Map<String, List<String>> categories = pluginManager.getLoadedPluginsByCategory();
Map<String, PluginInfo> 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<PluginInfo> configPluginInfos) {
PluginManager pluginManager = PluginManager.getInstance();
Map<String, List<String>> categories = pluginManager.getLoadedPluginsByCategory();
List<PluginInfo> 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");
}
}
}

View File

@ -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<Plugin> plugins = new ArrayList<>();
/**
* 插件类别
*/
@ -32,8 +36,7 @@ public class PluginManager {
/**
* 插件信息
*/
private final Map<String, PluginInfo> pluginInfos = new HashMap<>();
private final List<PluginInfo> 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<Path> 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<Plugin> getPlugins() {
return plugins;
}
public Map<String, PluginInfo> getPluginInfos() {
public List<PluginInfo> getPluginInfos() {
return pluginInfos;
}
}

View File

@ -17,13 +17,14 @@ import java.util.List;
import java.util.Map;
/**
* 插件演示类
* 插件管理界面
* <p>
* 用于演示插件加载和执行的界面
*
* @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;
}
}

View File

@ -8,18 +8,9 @@ import java.util.Map;
* <p>
* 描述插件的基本功能
*
* @author luke
* @author luke gewuyou
*/
public interface Plugin extends PluginCategory {
/**
* 获取插件的显示名称
*
* @return 插件的显示名称
*/
String getDisplayName();
public interface Plugin {
/**
* 初始化插件
*/

View File

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

View File

@ -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<String> securityItem1 = new TreeItem<>("安全设置项1");
TreeItem<String> securityItem2 = new TreeItem<>("安全设置项2");
TreeItem<String> 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<String> 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));

View File

@ -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);