diff --git a/src/main/java/org/jcnc/jnotepad/LunchApp.java b/src/main/java/org/jcnc/jnotepad/LunchApp.java index 78cb750c382243f395c2e9d0355f60c0cb2d4be1..aaba292f2125e850c1da477af2038e4be4d7a2fa 100644 --- a/src/main/java/org/jcnc/jnotepad/LunchApp.java +++ b/src/main/java/org/jcnc/jnotepad/LunchApp.java @@ -11,7 +11,6 @@ import org.jcnc.jnotepad.constants.AppConstants; import org.jcnc.jnotepad.constants.TextConstants; import org.jcnc.jnotepad.controller.i18n.LocalizationController; import org.jcnc.jnotepad.manager.ThreadPoolManager; -import org.jcnc.jnotepad.tool.PopUpUtil; import org.jcnc.jnotepad.tool.SingletonUtil; import org.jcnc.jnotepad.tool.UiUtil; import org.jcnc.jnotepad.view.manager.ViewManager; @@ -73,7 +72,6 @@ public class LunchApp extends Application { primaryStage.setWidth(SCENE.getWidth()); primaryStage.setHeight(SCENE.getHeight()); primaryStage.getIcons().add(UiUtil.getAppIcon()); - // PopUpUtil.errorAlert("错误", "读写错误", "配置文件读写错误!", null, null); primaryStage.show(); } diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/OpenFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/OpenFile.java index 4a60a91a2424255ac185aeb9ee8946b72c363bdc..cb6038f0c97a439f76099fdf442b751a947b53f2 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/OpenFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/OpenFile.java @@ -14,7 +14,7 @@ import org.jcnc.jnotepad.root.center.main.center.tab.CenterTabPane; import org.jcnc.jnotepad.tool.EncodingDetector; import org.jcnc.jnotepad.tool.LogUtil; import org.jcnc.jnotepad.tool.UiUtil; -import org.jcnc.jnotepad.ui.dialog.factory.impl.TextFileChooserFactory; +import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory; import org.jcnc.jnotepad.ui.module.LineNumberTextArea; import java.io.BufferedReader; @@ -41,7 +41,7 @@ public class OpenFile implements EventHandler { @Override public void handle(ActionEvent event) { // 显示文件选择对话框,并获取选中的文件 - File file = TextFileChooserFactory.getInstance().createFileChooser( + File file = BasicFileChooserFactory.getInstance().createFileChooser( UiResourceBundle.getContent(TextConstants.OPEN), null, null, diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/RenameFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/RenameFile.java index d749f93c039bf9b6cfc4878c4109c26dce88bcb4..74dbd918bb41cc9c461a6811a413e4630ab2a675 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/RenameFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/RenameFile.java @@ -11,7 +11,7 @@ import org.jcnc.jnotepad.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.root.center.main.center.tab.CenterTabPane; import org.jcnc.jnotepad.tool.LogUtil; import org.jcnc.jnotepad.tool.UiUtil; -import org.jcnc.jnotepad.ui.dialog.factory.impl.TextFileChooserFactory; +import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory; import org.slf4j.Logger; import java.io.File; @@ -92,7 +92,7 @@ public class RenameFile implements EventHandler { // 获取原始文件对象 File file = (File) centerTab.getUserData(); // 获取应用窗口并绑定 - File newFile = TextFileChooserFactory.getInstance() + File newFile = BasicFileChooserFactory.getInstance() .createFileChooser( UiResourceBundle.getContent(TextConstants.RENAME), centerTab.getText(), diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/SaveFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/SaveFile.java index 9220de5fac66f5fa63944d28a71b9bc1334214e6..1d45ca2ca276e8cf309dafc45e4baa2f65233732 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/SaveFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/menubar/SaveFile.java @@ -12,7 +12,7 @@ import org.jcnc.jnotepad.root.top.menu.TopMenuBar; import org.jcnc.jnotepad.tool.LogUtil; import org.jcnc.jnotepad.tool.SingletonUtil; import org.jcnc.jnotepad.tool.UiUtil; -import org.jcnc.jnotepad.ui.dialog.factory.impl.TextFileChooserFactory; +import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory; import org.slf4j.Logger; import java.io.File; @@ -76,7 +76,7 @@ public class SaveFile implements EventHandler { if (selectedTab == null) { return; } - File file = TextFileChooserFactory.getInstance().createFileChooser( + File file = BasicFileChooserFactory.getInstance().createFileChooser( UiResourceBundle.getContent(TextConstants.SAVE_AS), selectedTab.getText(), null, diff --git a/src/main/java/org/jcnc/jnotepad/plugin/ButtonPlugin.java b/src/main/java/org/jcnc/jnotepad/plugin/ButtonPlugin.java index be080c9e8e301aaf0ba7ba032b406282cdec87af..4a0da50d0b310cc523ba18e7c387aaac2e70be2b 100644 --- a/src/main/java/org/jcnc/jnotepad/plugin/ButtonPlugin.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/ButtonPlugin.java @@ -1,5 +1,7 @@ package org.jcnc.jnotepad.plugin; +import org.jcnc.jnotepad.tool.LogUtil; + /** * 新按钮插件 * @@ -20,6 +22,6 @@ public class ButtonPlugin implements Plugin { @Override public void execute() { // 在这里实现新按钮插件的逻辑 - System.out.println("新按钮插件执行了!"); + LogUtil.getLogger(this.getClass()).info("新按钮插件执行了!"); } } \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java index 865887c6e0b5e6ace18a05d92b67ef6ca3f6e2c9..4a364d9d1affd4f596ec66a5f001b91e1bdf0363 100644 --- a/src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginDemo.java @@ -6,6 +6,9 @@ import javafx.scene.control.Label; import javafx.scene.layout.VBox; import javafx.stage.FileChooser; import javafx.stage.Stage; +import org.jcnc.jnotepad.tool.LogUtil; +import org.jcnc.jnotepad.tool.UiUtil; +import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory; import java.io.File; import java.util.List; @@ -28,11 +31,12 @@ public class PluginDemo { public void start(Stage primaryStage) { PluginManager pluginManager = new PluginManager(); - FileChooser fileChooser = new FileChooser(); - fileChooser.getExtensionFilters().addAll( + FileChooser fileChooser = BasicFileChooserFactory.getInstance().createFileChooser( + "选择插件", + null, + null, new FileChooser.ExtensionFilter("JAR Files", "*.jar") ); - Button loadButton = createLoadButton(primaryStage, fileChooser, pluginManager); Button executeButton = new Button("执行插件"); @@ -40,6 +44,7 @@ public class PluginDemo { VBox root = new VBox(10, loadButton, executeButton); Scene scene = new Scene(root, 300, 200); + primaryStage.getIcons().add(UiUtil.getAppIcon()); primaryStage.setScene(scene); primaryStage.setTitle("插件演示"); primaryStage.show(); @@ -66,6 +71,7 @@ public class PluginDemo { displayPluginInfo(primaryStage, pluginManager); } } catch (Exception ignored) { + LogUtil.getLogger(this.getClass()).info("未加载插件!"); } }); return loadButton; @@ -81,17 +87,15 @@ public class PluginDemo { Map> loadedPluginsByCategory = pluginManager.getLoadedPluginsByCategory(); VBox infoBox = new VBox(); - for (String category : loadedPluginsByCategory.keySet()) { - Label categoryLabel = new Label("类别: " + category); + loadedPluginsByCategory.forEach((key, pluginNames) -> { + Label categoryLabel = new Label("类别: " + key); VBox categoryInfoBox = new VBox(); - List pluginNames = loadedPluginsByCategory.get(category); for (String pluginName : pluginNames) { Label pluginLabel = new Label("插件名称: " + pluginName); categoryInfoBox.getChildren().add(pluginLabel); } infoBox.getChildren().addAll(categoryLabel, categoryInfoBox); - } - + }); Scene infoScene = new Scene(infoBox, 400, 300); Stage infoStage = new Stage(); infoStage.setScene(infoScene); diff --git a/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java b/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java index 57aa64a848d6caca29b0cb19726881c749ebf154..a1caa36a57191adac518df1ab38c30ceb5baa1cb 100644 --- a/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java +++ b/src/main/java/org/jcnc/jnotepad/plugin/PluginManager.java @@ -1,6 +1,11 @@ package org.jcnc.jnotepad.plugin; +import org.jcnc.jnotepad.tool.LogUtil; +import org.slf4j.Logger; + import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; @@ -17,6 +22,7 @@ import java.util.Map; * @author luke */ public class PluginManager { + Logger logger = LogUtil.getLogger(this.getClass()); private final List plugins; private final Map> categories; @@ -32,16 +38,34 @@ public class PluginManager { * 加载插件 * * @param pluginFilePath 插件文件的路径 - * @throws Exception 如果加载插件时发生异常 */ - public void loadPlugins(String pluginFilePath) throws Exception { + public void loadPlugins(String pluginFilePath) { 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(); + Class pluginClass = null; + try (URLClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()})) { + pluginClass = classLoader.loadClass("org.jcnc.jnotepad.plugin.ButtonPlugin"); + } catch (ClassNotFoundException e) { + logger.error("无法找到对应的插件类!", e); + } catch (MalformedURLException e) { + logger.error("无法创建URL格式错误!", e); + } catch (IOException e) { + logger.error("IO异常!", e); + } + if (pluginClass == null) { + return; + } + Plugin plugin = null; + try { + plugin = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + logger.error("发生异常!", e); + } + if (plugin == null) { + return; + } plugins.add(plugin); // 添加插件到类别中 @@ -49,7 +73,7 @@ public class PluginManager { String displayName = plugin.getDisplayName(); categories.computeIfAbsent(categoryName, k -> new ArrayList<>()).add(displayName); } else { - System.err.println("Plugin file not found: " + pluginFilePath); + LogUtil.getLogger(this.getClass()).info("Plugin file not found: {}", pluginFilePath); } } diff --git a/src/main/java/org/jcnc/jnotepad/ui/dialog/factory/FileChooserFactory.java b/src/main/java/org/jcnc/jnotepad/ui/dialog/factory/FileChooserFactory.java index 5cb0f6dec1e2960e694d89274951a0c67339ba8f..46457a732f8fab35c19487ce9a72ea797eb8cfde 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/dialog/factory/FileChooserFactory.java +++ b/src/main/java/org/jcnc/jnotepad/ui/dialog/factory/FileChooserFactory.java @@ -25,9 +25,9 @@ public interface FileChooserFactory { * @param title 对话框标题 * @param filename 默认选中的文件名 * @param directory 初始目录 - * @param extensionFilter 文件类型过滤器 + * @param extensionFilters 文件类型过滤器 * @return javafx.stage.FileChooser 详细文件选择对话框对象 * @apiNote 该方法用于创建一个带有标题、默认文件名、初始目录和文件类型过滤器的详细文件选择对话框。 */ - FileChooser createFileChooser(String title, String filename, File directory, FileChooser.ExtensionFilter extensionFilter); + FileChooser createFileChooser(String title, String filename, File directory, FileChooser.ExtensionFilter... extensionFilters); } diff --git a/src/main/java/org/jcnc/jnotepad/ui/dialog/factory/impl/TextFileChooserFactory.java b/src/main/java/org/jcnc/jnotepad/ui/dialog/factory/impl/BasicFileChooserFactory.java similarity index 44% rename from src/main/java/org/jcnc/jnotepad/ui/dialog/factory/impl/TextFileChooserFactory.java rename to src/main/java/org/jcnc/jnotepad/ui/dialog/factory/impl/BasicFileChooserFactory.java index 82f16dec07db88f47702565b60a6f95d909b442a..7ba296ad41085eca78b99def2e658c86d17094e4 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/dialog/factory/impl/TextFileChooserFactory.java +++ b/src/main/java/org/jcnc/jnotepad/ui/dialog/factory/impl/BasicFileChooserFactory.java @@ -4,22 +4,23 @@ import javafx.stage.FileChooser; import org.jcnc.jnotepad.ui.dialog.factory.FileChooserFactory; import java.io.File; +import java.util.List; /** - * 文本文件选择对话框 + * 基本文件选择对话框 * * @author gewuyou * @see FileChooserFactory */ -public class TextFileChooserFactory implements FileChooserFactory { +public class BasicFileChooserFactory implements FileChooserFactory { - private static final TextFileChooserFactory INSTANCE = new TextFileChooserFactory(); + private static final BasicFileChooserFactory INSTANCE = new BasicFileChooserFactory(); - private TextFileChooserFactory() { + private BasicFileChooserFactory() { } - public static TextFileChooserFactory getInstance() { + public static BasicFileChooserFactory getInstance() { return INSTANCE; } @@ -36,15 +37,15 @@ public class TextFileChooserFactory implements FileChooserFactory { /** * 创建详细的文件选择对话框 * - * @param title 对话框名字 - * @param filename 选中的文件名 - * @param directory 初始目录 - * @param extensionFilter 文件类型数组 + * @param title 对话框名字 + * @param filename 选中的文件名 + * @param directory 初始目录 + * @param extensionFilters 文件类型过滤器 * @return javafx.stage.FileChooser * @apiNote */ @Override - public FileChooser createFileChooser(String title, String filename, File directory, FileChooser.ExtensionFilter extensionFilter) { + public FileChooser createFileChooser(String title, String filename, File directory, FileChooser.ExtensionFilter... extensionFilters) { FileChooser fileChooser = createFileChooser(); // 设置窗口名称 fileChooser.setTitle(title); @@ -56,8 +57,24 @@ public class TextFileChooserFactory implements FileChooserFactory { // 设置打开的目录 fileChooser.setInitialDirectory(directory); } - // 设置文件类型 - fileChooser.getExtensionFilters().add(extensionFilter); + for (FileChooser.ExtensionFilter extensionFilter : extensionFilters) { + // 设置文件类型 + fileChooser.getExtensionFilters().add(extensionFilter); + } return fileChooser; } + + /** + * 创建详细的文件选择对话框 + * + * @param title 对话框名字 + * @param filename 选中的文件名 + * @param directory 初始目录 + * @param extensionFilters 文件类型过滤器集合 + * @return javafx.stage.FileChooser + * @apiNote + */ + public FileChooser createFileChooser(String title, String filename, File directory, List extensionFilters) { + return createFileChooser(title, filename, directory, extensionFilters.toArray(new FileChooser.ExtensionFilter[0])); + } } diff --git a/src/main/java/org/jcnc/jnotepad/ui/module/SettingsComponent.java b/src/main/java/org/jcnc/jnotepad/ui/module/SettingsComponent.java index 6d822781e10cc7bbe54aa4adc45d76f9e9814ff9..1edb1ba2268159eea3876f955c0cf3a4ffc7e9ee 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/module/SettingsComponent.java +++ b/src/main/java/org/jcnc/jnotepad/ui/module/SettingsComponent.java @@ -2,8 +2,8 @@ package org.jcnc.jnotepad.ui.module; import javafx.event.ActionEvent; import javafx.event.EventHandler; -import javafx.scene.control.Label; import javafx.scene.control.Button; +import javafx.scene.control.Label; import javafx.scene.layout.VBox; /** diff --git a/src/main/java/org/jcnc/jnotepad/ui/setstage/DeveloperDebugStage.java b/src/main/java/org/jcnc/jnotepad/ui/setstage/DeveloperDebugStage.java index 3280ca183c64ad514bba6f0943f658d38eab6ad2..b119b29bbebdbf2d475ea6c0ee5aad22f5743a4d 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/setstage/DeveloperDebugStage.java +++ b/src/main/java/org/jcnc/jnotepad/ui/setstage/DeveloperDebugStage.java @@ -1,6 +1,5 @@ package org.jcnc.jnotepad.ui.setstage; -import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button;