!103 ♻️ 重构插件类加载逻辑 修复 导入插件错误 ➕ 添加工具栏插件支持
Merge pull request !103 from 格物方能致知/develop
This commit is contained in:
commit
6398b2f7fe
@ -71,7 +71,6 @@ JNotepad使用Java语言编写,并基于JavaFX框架开发,具有良好的
|
|||||||
|
|
||||||
[docs-url]: https://gitee.com/jcnc-org/docs
|
[docs-url]: https://gitee.com/jcnc-org/docs
|
||||||
|
|
||||||
|
|
||||||
- [下载][gitee-download]
|
- [下载][gitee-download]
|
||||||
|
|
||||||
2. Linux/MacOS 平台,查看入门指南
|
2. Linux/MacOS 平台,查看入门指南
|
||||||
@ -111,13 +110,12 @@ JNotepad使用Java语言编写,并基于JavaFX框架开发,具有良好的
|
|||||||
|
|
||||||
- `插件 > 增加插件`:(管理插件系统,待完善)。
|
- `插件 > 增加插件`:(管理插件系统,待完善)。
|
||||||
|
|
||||||
|
|
||||||
## 依赖项
|
## 依赖项
|
||||||
|
|
||||||
POM文件中的全部依赖项:
|
POM文件中的全部依赖项:
|
||||||
|
|
||||||
| 组ID | 工件ID | 版本 | 功能描述 |
|
| 组ID | 工件ID | 版本 | 功能描述 |
|
||||||
|--------------------------------|------------------------------|--------|------------------------------------------------|
|
|----------------------------|----------------------------|--------|--------------------------------------------------------------|
|
||||||
| org.kordamp.ikonli | ikonli-javafx | 12.3.1 | 提供JavaFX应用程序中的图标集成。 |
|
| org.kordamp.ikonli | ikonli-javafx | 12.3.1 | 提供JavaFX应用程序中的图标集成。 |
|
||||||
| org.kordamp.ikonli | ikonli-antdesignicons-pack | 12.3.1 | 包含Ant Design图标集的Ikonli图标包。 |
|
| org.kordamp.ikonli | ikonli-antdesignicons-pack | 12.3.1 | 包含Ant Design图标集的Ikonli图标包。 |
|
||||||
| io.github.mkpaz | atlantafx-base | 2.0.1 | 提供Atlantafx库的基本功能。 |
|
| io.github.mkpaz | atlantafx-base | 2.0.1 | 提供Atlantafx库的基本功能。 |
|
||||||
@ -129,7 +127,6 @@ POM文件中的全部依赖项:
|
|||||||
| ch.qos.logback | logback-classic | 1.4.11 | Logback的经典模块,提供日志记录功能。 |
|
| ch.qos.logback | logback-classic | 1.4.11 | Logback的经典模块,提供日志记录功能。 |
|
||||||
| com.ibm.icu | icu4j | 73.2 | ICU(International Components for Unicode)库,用于处理Unicode字符和文本。 |
|
| com.ibm.icu | icu4j | 73.2 | ICU(International Components for Unicode)库,用于处理Unicode字符和文本。 |
|
||||||
|
|
||||||
|
|
||||||
## 软件运行截图
|
## 软件运行截图
|
||||||
|
|
||||||
- Windows 平台
|
- Windows 平台
|
||||||
|
|||||||
@ -40,4 +40,5 @@ jar uf libs/icu4j-73.2.jar -C libs/tmpOut/com.ibm.icu module-info.class
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
1. [java_jlink_automatic_module_cannot_be_used_with_jlink](https://tacosteemers.com/articles/java_jlink_automatic_module_cannot_be_used_with_jlink.html)
|
1. [java_jlink_automatic_module_cannot_be_used_with_jlink](https://tacosteemers.com/articles/java_jlink_automatic_module_cannot_be_used_with_jlink.html)
|
||||||
@ -31,11 +31,13 @@ module org.jcnc.jnotepad {
|
|||||||
exports org.jcnc.jnotepad.common.interfaces;
|
exports org.jcnc.jnotepad.common.interfaces;
|
||||||
opens org.jcnc.jnotepad.app.config;
|
opens org.jcnc.jnotepad.app.config;
|
||||||
exports org.jcnc.jnotepad.plugin.interfaces;
|
exports org.jcnc.jnotepad.plugin.interfaces;
|
||||||
|
exports org.jcnc.jnotepad.views.root.bottom.function;
|
||||||
|
exports org.jcnc.jnotepad.views.root.bottom.function.interfaces;
|
||||||
exports org.jcnc.jnotepad.ui.dialog;
|
exports org.jcnc.jnotepad.ui.dialog;
|
||||||
exports org.jcnc.jnotepad.ui.dialog.interfaces;
|
exports org.jcnc.jnotepad.ui.dialog.interfaces;
|
||||||
|
exports org.jcnc.jnotepad.ui.module;
|
||||||
exports org.jcnc.jnotepad.model.entity;
|
exports org.jcnc.jnotepad.model.entity;
|
||||||
exports org.jcnc.jnotepad.views.root.bottom;
|
exports org.jcnc.jnotepad.views.root.bottom;
|
||||||
exports org.jcnc.jnotepad.views.root.bottom.status;
|
exports org.jcnc.jnotepad.views.root.bottom.status;
|
||||||
exports org.jcnc.jnotepad.views.root.bottom.cmd;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -83,12 +83,14 @@ public class LunchApp extends Application {
|
|||||||
|
|
||||||
// 1. 加载语言
|
// 1. 加载语言
|
||||||
LocalizationController.initLocal();
|
LocalizationController.initLocal();
|
||||||
|
// 2. 加载资源
|
||||||
// 2. 加载组件
|
ResourceController.getInstance().loadResources();
|
||||||
|
// 3. 初始化插件
|
||||||
|
PluginManager.getInstance().initializePlugins();
|
||||||
|
// 3. 加载组件
|
||||||
ViewManager viewManager = ViewManager.getInstance(SCENE);
|
ViewManager viewManager = ViewManager.getInstance(SCENE);
|
||||||
viewManager.initScreen(SCENE);
|
viewManager.initScreen(SCENE);
|
||||||
// 3. 加载资源
|
|
||||||
ResourceController.getInstance().loadResources();
|
|
||||||
// 使用线程池加载关联文件并创建文本区域
|
// 使用线程池加载关联文件并创建文本区域
|
||||||
List<String> rawParameters = getParameters().getRaw();
|
List<String> rawParameters = getParameters().getRaw();
|
||||||
Controller.getInstance().openAssociatedFileAndCreateTextArea(rawParameters);
|
Controller.getInstance().openAssociatedFileAndCreateTextArea(rawParameters);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package org.jcnc.jnotepad.app.config;
|
package org.jcnc.jnotepad.app.config;
|
||||||
|
|
||||||
import org.jcnc.jnotepad.model.entity.PluginInfo;
|
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -11,7 +11,7 @@ import java.util.List;
|
|||||||
* @author gewuyou
|
* @author gewuyou
|
||||||
*/
|
*/
|
||||||
public class PluginConfig {
|
public class PluginConfig {
|
||||||
private List<PluginInfo> plugins;
|
private List<PluginDescriptor> plugins;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成默认的插件配置文件
|
* 生成默认的插件配置文件
|
||||||
@ -26,11 +26,11 @@ public class PluginConfig {
|
|||||||
return pluginConfig;
|
return pluginConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PluginInfo> getPlugins() {
|
public List<PluginDescriptor> getPlugins() {
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlugins(List<PluginInfo> plugins) {
|
public void setPlugins(List<PluginDescriptor> plugins) {
|
||||||
this.plugins = plugins;
|
this.plugins = plugins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import org.jcnc.jnotepad.plugin.interfaces.Plugin;
|
|||||||
*
|
*
|
||||||
* @author gewuyou
|
* @author gewuyou
|
||||||
*/
|
*/
|
||||||
public class PluginInfo {
|
public class PluginDescriptor {
|
||||||
/**
|
/**
|
||||||
* 插件名称
|
* 插件名称
|
||||||
*/
|
*/
|
||||||
@ -2,7 +2,7 @@ package org.jcnc.jnotepad.plugin;
|
|||||||
|
|
||||||
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
||||||
import org.jcnc.jnotepad.exception.AppException;
|
import org.jcnc.jnotepad.exception.AppException;
|
||||||
import org.jcnc.jnotepad.model.entity.PluginInfo;
|
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||||
import org.jcnc.jnotepad.plugin.interfaces.Plugin;
|
import org.jcnc.jnotepad.plugin.interfaces.Plugin;
|
||||||
import org.jcnc.jnotepad.util.JsonUtil;
|
import org.jcnc.jnotepad.util.JsonUtil;
|
||||||
import org.jcnc.jnotepad.util.LogUtil;
|
import org.jcnc.jnotepad.util.LogUtil;
|
||||||
@ -12,10 +12,8 @@ import java.io.*;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Iterator;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
@ -29,11 +27,11 @@ public class PluginLoader {
|
|||||||
Logger logger = LogUtil.getLogger(this.getClass());
|
Logger logger = LogUtil.getLogger(this.getClass());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从插件jar包中读取 json 文件到 PluginInfo 类
|
* 从插件jar包中读取 json 文件到 PluginDescriptor 类
|
||||||
*
|
*
|
||||||
* @param pluginJar jar 包
|
* @param pluginJar jar 包
|
||||||
*/
|
*/
|
||||||
public static PluginInfo readPlugin(File pluginJar) throws IOException {
|
public static PluginDescriptor readPlugin(File pluginJar) throws IOException {
|
||||||
InputStream is;
|
InputStream is;
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
try (JarFile jarFile = new JarFile(pluginJar)) {
|
try (JarFile jarFile = new JarFile(pluginJar)) {
|
||||||
@ -48,7 +46,7 @@ public class PluginLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return JsonUtil.OBJECT_MAPPER.readValue(sb.toString(), PluginInfo.class);
|
return JsonUtil.OBJECT_MAPPER.readValue(sb.toString(), PluginDescriptor.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PluginLoader getInstance() {
|
public static PluginLoader getInstance() {
|
||||||
@ -58,38 +56,38 @@ public class PluginLoader {
|
|||||||
/**
|
/**
|
||||||
* 检查插件
|
* 检查插件
|
||||||
*
|
*
|
||||||
* @param configPluginInfos 配置文件插件信息
|
* @param configPluginDescriptors 配置文件插件信息
|
||||||
* @param pluginInfo 插件信息类
|
* @param pluginDescriptor 插件信息类
|
||||||
* @param pluginInfos 插件信息集合
|
* @param pluginDescriptors 插件信息集合
|
||||||
* @return boolean 是否检查通过
|
* @return boolean 是否检查通过
|
||||||
* @apiNote
|
* @apiNote
|
||||||
* @since 2023/9/16 14:04
|
* @since 2023/9/16 14:04
|
||||||
*/
|
*/
|
||||||
private static boolean checkPlugin(List<PluginInfo> configPluginInfos, PluginInfo pluginInfo, List<PluginInfo> pluginInfos) {
|
private static boolean checkPlugin(List<PluginDescriptor> configPluginDescriptors, PluginDescriptor pluginDescriptor, List<PluginDescriptor> pluginDescriptors) {
|
||||||
// 如果应用程序配置文件为空则默认插件被禁用
|
// 如果应用程序配置文件为空则默认插件被禁用
|
||||||
if (configPluginInfos.isEmpty()) {
|
if (configPluginDescriptors.isEmpty()) {
|
||||||
return disabledByDefault(configPluginInfos, pluginInfo, pluginInfos);
|
return disabledByDefault(configPluginDescriptors, pluginDescriptor, pluginDescriptors);
|
||||||
}
|
}
|
||||||
// 如果应用程序配置文件中该插件禁用则不加载
|
// 如果应用程序配置文件中该插件禁用则不加载
|
||||||
for (PluginInfo configPluginInfo : configPluginInfos) {
|
for (PluginDescriptor configPluginDescriptor : configPluginDescriptors) {
|
||||||
if (disableDoNotLoad(pluginInfo, pluginInfos, configPluginInfo)) {
|
if (disableDoNotLoad(pluginDescriptor, pluginDescriptors, configPluginDescriptor)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 判断该插件是否已经加载
|
// 判断该插件是否已经加载
|
||||||
return loaded(pluginInfo, pluginInfos);
|
return loaded(pluginDescriptor, pluginDescriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean loaded(PluginInfo pluginInfo, List<PluginInfo> pluginInfos) {
|
private static boolean loaded(PluginDescriptor pluginDescriptor, List<PluginDescriptor> pluginDescriptors) {
|
||||||
Iterator<PluginInfo> iterator = pluginInfos.iterator();
|
Iterator<PluginDescriptor> iterator = pluginDescriptors.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
PluginInfo plugin = iterator.next();
|
PluginDescriptor plugin = iterator.next();
|
||||||
if ((plugin.getName() + plugin.getAuthor()).equals(pluginInfo.getName() + pluginInfo.getAuthor())) {
|
if ((plugin.getName() + plugin.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
||||||
if (plugin.getVersion().equals(pluginInfo.getVersion())) {
|
if (plugin.getVersion().equals(pluginDescriptor.getVersion())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// 如果当前插件版本更低则更新
|
// 如果当前插件版本更低则更新
|
||||||
if (plugin.getVersion().compareTo(pluginInfo.getVersion()) < 0) {
|
if (plugin.getVersion().compareTo(pluginDescriptor.getVersion()) < 0) {
|
||||||
// 删除当前的插件
|
// 删除当前的插件
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
} else {
|
} else {
|
||||||
@ -100,19 +98,19 @@ public class PluginLoader {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean disableDoNotLoad(PluginInfo pluginInfo, List<PluginInfo> pluginInfos, PluginInfo configPluginInfo) {
|
private static boolean disableDoNotLoad(PluginDescriptor pluginDescriptor, List<PluginDescriptor> pluginDescriptors, PluginDescriptor configPluginDescriptor) {
|
||||||
if ((configPluginInfo.getName() + configPluginInfo.getAuthor()).equals(pluginInfo.getName() + pluginInfo.getAuthor()) && !configPluginInfo.isEnabled()) {
|
if ((configPluginDescriptor.getName() + configPluginDescriptor.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor()) && !configPluginDescriptor.isEnabled()) {
|
||||||
pluginInfo.setEnabled(false);
|
pluginDescriptor.setEnabled(false);
|
||||||
pluginInfos.add(pluginInfo);
|
pluginDescriptors.add(pluginDescriptor);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean disabledByDefault(List<PluginInfo> configPluginInfos, PluginInfo pluginInfo, List<PluginInfo> pluginInfos) {
|
private static boolean disabledByDefault(List<PluginDescriptor> configPluginDescriptors, PluginDescriptor pluginDescriptor, List<PluginDescriptor> pluginDescriptors) {
|
||||||
pluginInfo.setEnabled(false);
|
pluginDescriptor.setEnabled(false);
|
||||||
pluginInfos.add(pluginInfo);
|
pluginDescriptors.add(pluginDescriptor);
|
||||||
configPluginInfos.add(pluginInfo);
|
configPluginDescriptors.add(pluginDescriptor);
|
||||||
PluginConfigController.getInstance().writeConfig();
|
PluginConfigController.getInstance().writeConfig();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -131,36 +129,32 @@ public class PluginLoader {
|
|||||||
* 根据文件加载插件
|
* 根据文件加载插件
|
||||||
*
|
*
|
||||||
* @param pluginJar 插件jar包
|
* @param pluginJar 插件jar包
|
||||||
* @param configPluginInfos 配置文件插件信息集合
|
* @param configPluginDescriptors 配置文件插件信息集合
|
||||||
* @apiNote
|
* @apiNote
|
||||||
* @since 2023/9/16 14:05
|
* @since 2023/9/16 14:05
|
||||||
*/
|
*/
|
||||||
public void loadPluginByFile(File pluginJar, List<PluginInfo> configPluginInfos) {
|
public void loadPluginByFile(File pluginJar, List<PluginDescriptor> configPluginDescriptors) {
|
||||||
PluginManager pluginManager = PluginManager.getInstance();
|
PluginManager pluginManager = PluginManager.getInstance();
|
||||||
Map<String, List<String>> categories = pluginManager.getLoadedPluginsByCategory();
|
Map<String, List<String>> categories = pluginManager.getLoadedPluginsByCategory();
|
||||||
List<PluginInfo> pluginInfos = pluginManager.getPluginInfos();
|
List<PluginDescriptor> pluginDescriptors = pluginManager.getPluginInfos();
|
||||||
if (pluginJar.exists() && pluginJar.isFile()) {
|
if (pluginJar.exists() && pluginJar.isFile()) {
|
||||||
try {
|
try {
|
||||||
PluginInfo pluginInfo = readPlugin(pluginJar);
|
PluginDescriptor pluginDescriptor = readPlugin(pluginJar);
|
||||||
// 检查插件状态
|
// 检查插件状态
|
||||||
if (checkPlugin(configPluginInfos, pluginInfo, pluginInfos)) {
|
if (checkPlugin(configPluginDescriptors, pluginDescriptor, pluginDescriptors)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pluginInfo.setEnabled(true);
|
pluginDescriptor.setEnabled(true);
|
||||||
pluginInfos.add(pluginInfo);
|
pluginDescriptors.add(pluginDescriptor);
|
||||||
// 创建URLClassLoader以加载Jar文件中的类
|
// 创建URLClassLoader以加载Jar文件中的类
|
||||||
Class<?> pluginClass;
|
Class<?> pluginClass = loaderJarFileClass(pluginJar, pluginDescriptor);
|
||||||
try (URLClassLoader classLoader = new URLClassLoader(new URL[]{pluginJar.toURI().toURL()})) {
|
|
||||||
logger.info("{}", pluginInfo.getMainClass());
|
|
||||||
pluginClass = classLoader.loadClass(pluginInfo.getMainClass());
|
|
||||||
}
|
|
||||||
if (pluginClass == null) {
|
if (pluginClass == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Plugin plugin;
|
Plugin plugin;
|
||||||
plugin = (Plugin) pluginClass.getDeclaredConstructor().newInstance();
|
plugin = (Plugin) pluginClass.getDeclaredConstructor().newInstance();
|
||||||
pluginInfo.setPlugin(plugin);
|
pluginDescriptor.setPlugin(plugin);
|
||||||
categories.computeIfAbsent(pluginInfo.getCategory(), k -> new ArrayList<>()).add(pluginInfo.getName());
|
categories.computeIfAbsent(pluginDescriptor.getCategory(), k -> new ArrayList<>()).add(pluginDescriptor.getName());
|
||||||
} catch (IOException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
} catch (IOException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
||||||
throw new AppException(e);
|
throw new AppException(e);
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
@ -170,7 +164,39 @@ public class PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
LogUtil.getLogger(this.getClass()).info("PluginInfo file not found");
|
LogUtil.getLogger(this.getClass()).info("PluginDescriptor file not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载类中的class文件并返回插件主类
|
||||||
|
*
|
||||||
|
* @param pluginJar 插件jar包
|
||||||
|
* @param pluginDescriptor 插件描述
|
||||||
|
* @return java.lang.Class<?> 插件主类
|
||||||
|
* @apiNote
|
||||||
|
* @since 2023/9/19 14:00
|
||||||
|
*/
|
||||||
|
private Class<?> loaderJarFileClass(File pluginJar, PluginDescriptor pluginDescriptor) throws IOException, ClassNotFoundException {
|
||||||
|
Class<?> pluginClass;
|
||||||
|
try (
|
||||||
|
URLClassLoader classLoader = new URLClassLoader(new URL[]{pluginJar.toURI().toURL()});
|
||||||
|
JarFile jar = new JarFile(pluginJar)
|
||||||
|
) {
|
||||||
|
logger.info("{}", pluginDescriptor.getMainClass());
|
||||||
|
// 加载插件所需的依赖类
|
||||||
|
Enumeration<JarEntry> entries = jar.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
JarEntry entry = entries.nextElement();
|
||||||
|
if (entry.getName().endsWith(".class")) {
|
||||||
|
String className = entry.getName().replace("/", ".").replace(".class", "");
|
||||||
|
if (!pluginDescriptor.getMainClass().equals(className) && !"module-info".equals(className)) {
|
||||||
|
classLoader.loadClass(className);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pluginClass = classLoader.loadClass(pluginDescriptor.getMainClass());
|
||||||
|
}
|
||||||
|
return pluginClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package org.jcnc.jnotepad.plugin;
|
|||||||
|
|
||||||
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
||||||
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
||||||
import org.jcnc.jnotepad.model.entity.PluginInfo;
|
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||||
import org.jcnc.jnotepad.util.LogUtil;
|
import org.jcnc.jnotepad.util.LogUtil;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
@ -28,7 +28,6 @@ import static org.jcnc.jnotepad.plugin.PluginLoader.readPlugin;
|
|||||||
*/
|
*/
|
||||||
public class PluginManager {
|
public class PluginManager {
|
||||||
private static final PluginManager INSTANCE = new PluginManager();
|
private static final PluginManager INSTANCE = new PluginManager();
|
||||||
Logger logger = LogUtil.getLogger(this.getClass());
|
|
||||||
/**
|
/**
|
||||||
* 插件类别
|
* 插件类别
|
||||||
*/
|
*/
|
||||||
@ -36,7 +35,8 @@ public class PluginManager {
|
|||||||
/**
|
/**
|
||||||
* 插件信息
|
* 插件信息
|
||||||
*/
|
*/
|
||||||
private final List<PluginInfo> pluginInfos = new ArrayList<>();
|
private final List<PluginDescriptor> pluginDescriptors = new ArrayList<>();
|
||||||
|
Logger logger = LogUtil.getLogger(this.getClass());
|
||||||
|
|
||||||
private PluginManager() {
|
private PluginManager() {
|
||||||
|
|
||||||
@ -50,14 +50,14 @@ public class PluginManager {
|
|||||||
/**
|
/**
|
||||||
* 卸载插件
|
* 卸载插件
|
||||||
*
|
*
|
||||||
* @param pluginInfo 插件信息类
|
* @param pluginDescriptor 插件信息类
|
||||||
* @since 2023/9/11 12:28
|
* @since 2023/9/11 12:28
|
||||||
*/
|
*/
|
||||||
public void unloadPlugin(PluginInfo pluginInfo) {
|
public void unloadPlugin(PluginDescriptor pluginDescriptor) {
|
||||||
// 删除集合中的插件信息
|
// 删除集合中的插件信息
|
||||||
pluginInfos.remove(pluginInfo);
|
pluginDescriptors.remove(pluginDescriptor);
|
||||||
PluginConfigController instance = PluginConfigController.getInstance();
|
PluginConfigController instance = PluginConfigController.getInstance();
|
||||||
instance.getConfig().getPlugins().remove(pluginInfo);
|
instance.getConfig().getPlugins().remove(pluginDescriptor);
|
||||||
// 刷新配置
|
// 刷新配置
|
||||||
instance.writeConfig();
|
instance.writeConfig();
|
||||||
// 删除本地插件jar包
|
// 删除本地插件jar包
|
||||||
@ -66,8 +66,8 @@ public class PluginManager {
|
|||||||
pathStream.filter(path -> path.toString().endsWith(".jar")).forEach(path -> {
|
pathStream.filter(path -> path.toString().endsWith(".jar")).forEach(path -> {
|
||||||
try {
|
try {
|
||||||
File pluginJar = new File(path.toString());
|
File pluginJar = new File(path.toString());
|
||||||
PluginInfo temp = readPlugin(pluginJar);
|
PluginDescriptor temp = readPlugin(pluginJar);
|
||||||
if ((temp.getName() + temp.getAuthor()).equals(pluginInfo.getName() + pluginInfo.getAuthor())) {
|
if ((temp.getName() + temp.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
||||||
Files.delete(pluginJar.toPath());
|
Files.delete(pluginJar.toPath());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -83,17 +83,17 @@ public class PluginManager {
|
|||||||
/**
|
/**
|
||||||
* 禁用插件
|
* 禁用插件
|
||||||
*
|
*
|
||||||
* @param pluginInfo 需要禁用的某个插件的插件类
|
* @param pluginDescriptor 需要禁用的某个插件的插件类
|
||||||
* @apiNote
|
* @apiNote
|
||||||
* @since 2023/9/11 12:34
|
* @since 2023/9/11 12:34
|
||||||
*/
|
*/
|
||||||
public void disablePlugIn(PluginInfo pluginInfo) {
|
public void disablePlugIn(PluginDescriptor pluginDescriptor) {
|
||||||
pluginInfo.setEnabled(false);
|
pluginDescriptor.setEnabled(false);
|
||||||
pluginInfo.setPlugin(null);
|
pluginDescriptor.setPlugin(null);
|
||||||
ThreadPoolManager.getThreadPool().submit(() -> {
|
ThreadPoolManager.getThreadPool().submit(() -> {
|
||||||
PluginConfigController instance = PluginConfigController.getInstance();
|
PluginConfigController instance = PluginConfigController.getInstance();
|
||||||
instance.getConfig().getPlugins().forEach(plugin -> {
|
instance.getConfig().getPlugins().forEach(plugin -> {
|
||||||
if ((pluginInfo.getName() + pluginInfo.getAuthor()).equals(plugin.getName() + plugin.getAuthor())) {
|
if ((pluginDescriptor.getName() + pluginDescriptor.getAuthor()).equals(plugin.getName() + plugin.getAuthor())) {
|
||||||
plugin.setEnabled(false);
|
plugin.setEnabled(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -106,9 +106,9 @@ public class PluginManager {
|
|||||||
* 初始化所有启用的插件
|
* 初始化所有启用的插件
|
||||||
*/
|
*/
|
||||||
public void initializePlugins() {
|
public void initializePlugins() {
|
||||||
for (PluginInfo pluginInfo : pluginInfos) {
|
for (PluginDescriptor pluginDescriptor : pluginDescriptors) {
|
||||||
if (pluginInfo.isEnabled()) {
|
if (pluginDescriptor.isEnabled()) {
|
||||||
pluginInfo.getPlugin().initialize();
|
pluginDescriptor.getPlugin().initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,12 +116,12 @@ public class PluginManager {
|
|||||||
/**
|
/**
|
||||||
* 执行插件
|
* 执行插件
|
||||||
*
|
*
|
||||||
* @param pluginInfo 需要执行的插件的信息类
|
* @param pluginDescriptor 需要执行的插件的信息类
|
||||||
* @apiNote
|
* @apiNote
|
||||||
* @since 2023/9/16 14:58
|
* @since 2023/9/16 14:58
|
||||||
*/
|
*/
|
||||||
public void executePlugin(PluginInfo pluginInfo) {
|
public void executePlugin(PluginDescriptor pluginDescriptor) {
|
||||||
pluginInfo.getPlugin().execute();
|
pluginDescriptor.getPlugin().execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,9 +129,9 @@ public class PluginManager {
|
|||||||
* todo 待移除
|
* todo 待移除
|
||||||
*/
|
*/
|
||||||
public void executePlugins() {
|
public void executePlugins() {
|
||||||
for (PluginInfo pluginInfo : pluginInfos) {
|
for (PluginDescriptor pluginDescriptor : pluginDescriptors) {
|
||||||
if (pluginInfo.isEnabled()) {
|
if (pluginDescriptor.isEnabled()) {
|
||||||
pluginInfo.getPlugin().execute();
|
pluginDescriptor.getPlugin().execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ public class PluginManager {
|
|||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PluginInfo> getPluginInfos() {
|
public List<PluginDescriptor> getPluginInfos() {
|
||||||
return pluginInfos;
|
return pluginDescriptors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,10 @@ public class PluginManagerInterface {
|
|||||||
private static final PluginManagerInterface INSTANCE = new PluginManagerInterface();
|
private static final PluginManagerInterface INSTANCE = new PluginManagerInterface();
|
||||||
Logger logger = LogUtil.getLogger(this.getClass());
|
Logger logger = LogUtil.getLogger(this.getClass());
|
||||||
|
|
||||||
|
public static PluginManagerInterface getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动插件演示界面
|
* 启动插件演示界面
|
||||||
*
|
*
|
||||||
@ -54,10 +58,6 @@ public class PluginManagerInterface {
|
|||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PluginManagerInterface getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示已加载插件的信息
|
* 显示已加载插件的信息
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
package org.jcnc.jnotepad.plugin.interfaces;
|
package org.jcnc.jnotepad.plugin.interfaces;
|
||||||
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件接口
|
* 插件接口
|
||||||
* <p>
|
* <p>
|
||||||
@ -11,6 +9,7 @@ import java.util.Map;
|
|||||||
* @author luke gewuyou
|
* @author luke gewuyou
|
||||||
*/
|
*/
|
||||||
public interface Plugin {
|
public interface Plugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化插件
|
* 初始化插件
|
||||||
*/
|
*/
|
||||||
@ -22,17 +21,7 @@ public interface Plugin {
|
|||||||
void execute();
|
void execute();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取插件的配置参数
|
* 销毁资源
|
||||||
*
|
|
||||||
* @return 插件的配置参数
|
|
||||||
*/
|
*/
|
||||||
Map<String, Object> getConfig();
|
void destroyed();
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置插件的配置参数
|
|
||||||
*
|
|
||||||
* @param config 插件的配置参数
|
|
||||||
*/
|
|
||||||
void setConfig(Map<String, Object> config);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,112 +86,11 @@ public class AppDialogBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置应用图标
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setAppIcon(Image appIcon) {
|
|
||||||
this.appIcon = appIcon;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AppDialog build() {
|
public AppDialog build() {
|
||||||
appDialog = new AppDialog(this);
|
appDialog = new AppDialog(this);
|
||||||
return appDialog;
|
return appDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置对话框标题
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置对话框头部文本
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setHeaderText(String headerText) {
|
|
||||||
this.headerText = headerText;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置自定义文本
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setCustomText(String customText) {
|
|
||||||
this.customText = customText;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置对话框宽度
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setWidth(double width) {
|
|
||||||
this.width = width;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置对话框高度
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setHeight(double height) {
|
|
||||||
this.height = height;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置对话框左侧图标
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setIcon(FontIcon icon) {
|
|
||||||
this.icon = icon;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置左按钮操作
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setLeftBtnAction(DialogButtonAction leftBtnAction) {
|
|
||||||
if (leftBtnAction != null) {
|
|
||||||
this.leftBtnAction = leftBtnAction;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置右按钮操作
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setRightBtnAction(DialogButtonAction rightBtnAction) {
|
|
||||||
if (rightBtnAction != null) {
|
|
||||||
this.rightBtnAction = rightBtnAction;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置左按钮文本
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setLeftBtnText(String leftBtnText) {
|
|
||||||
this.leftBtnText = leftBtnText;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置右按钮文本
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setRightBtnText(String rightBtnText) {
|
|
||||||
this.rightBtnText = rightBtnText;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置图标边距
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setIconCoxPaddingInsets(Insets iconCoxPaddingInsets) {
|
|
||||||
this.iconCoxPaddingInsets = iconCoxPaddingInsets;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置水平盒子边距
|
* 设置水平盒子边距
|
||||||
*/
|
*/
|
||||||
@ -200,14 +99,6 @@ public class AppDialogBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置是否可调整大小
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setResizable(boolean resizable) {
|
|
||||||
isResizable = resizable;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置水平盒子间距
|
* 设置水平盒子间距
|
||||||
*/
|
*/
|
||||||
@ -216,14 +107,6 @@ public class AppDialogBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置垂直盒子位置
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setVboxPos(Pos vboxPos) {
|
|
||||||
this.vboxPos = vboxPos;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置水平盒子位置
|
* 设置水平盒子位置
|
||||||
*/
|
*/
|
||||||
@ -232,62 +115,154 @@ public class AppDialogBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置模态性
|
|
||||||
*/
|
|
||||||
public AppDialogBuilder setModality(Modality modality) {
|
|
||||||
this.modality = modality;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Image getAppIcon() {
|
public Image getAppIcon() {
|
||||||
return appIcon;
|
return appIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置应用图标
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setAppIcon(Image appIcon) {
|
||||||
|
this.appIcon = appIcon;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置对话框标题
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getHeaderText() {
|
public String getHeaderText() {
|
||||||
return headerText;
|
return headerText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置对话框头部文本
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setHeaderText(String headerText) {
|
||||||
|
this.headerText = headerText;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCustomText() {
|
public String getCustomText() {
|
||||||
return customText;
|
return customText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置自定义文本
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setCustomText(String customText) {
|
||||||
|
this.customText = customText;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public double getWidth() {
|
public double getWidth() {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置对话框宽度
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setWidth(double width) {
|
||||||
|
this.width = width;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public double getHeight() {
|
public double getHeight() {
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置对话框高度
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setHeight(double height) {
|
||||||
|
this.height = height;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public FontIcon getIcon() {
|
public FontIcon getIcon() {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置对话框左侧图标
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setIcon(FontIcon icon) {
|
||||||
|
this.icon = icon;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DialogButtonAction getLeftBtnAction() {
|
public DialogButtonAction getLeftBtnAction() {
|
||||||
return leftBtnAction;
|
return leftBtnAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置左按钮操作
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setLeftBtnAction(DialogButtonAction leftBtnAction) {
|
||||||
|
if (leftBtnAction != null) {
|
||||||
|
this.leftBtnAction = leftBtnAction;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DialogButtonAction getRightBtnAction() {
|
public DialogButtonAction getRightBtnAction() {
|
||||||
return rightBtnAction;
|
return rightBtnAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置右按钮操作
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setRightBtnAction(DialogButtonAction rightBtnAction) {
|
||||||
|
if (rightBtnAction != null) {
|
||||||
|
this.rightBtnAction = rightBtnAction;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getLeftBtnText() {
|
public String getLeftBtnText() {
|
||||||
return leftBtnText;
|
return leftBtnText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置左按钮文本
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setLeftBtnText(String leftBtnText) {
|
||||||
|
this.leftBtnText = leftBtnText;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getRightBtnText() {
|
public String getRightBtnText() {
|
||||||
return rightBtnText;
|
return rightBtnText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置右按钮文本
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setRightBtnText(String rightBtnText) {
|
||||||
|
this.rightBtnText = rightBtnText;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Insets getIconCoxPaddingInsets() {
|
public Insets getIconCoxPaddingInsets() {
|
||||||
return iconCoxPaddingInsets;
|
return iconCoxPaddingInsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置图标边距
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setIconCoxPaddingInsets(Insets iconCoxPaddingInsets) {
|
||||||
|
this.iconCoxPaddingInsets = iconCoxPaddingInsets;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Insets gethBoxPaddingInsets() {
|
public Insets gethBoxPaddingInsets() {
|
||||||
return hBoxPaddingInsets;
|
return hBoxPaddingInsets;
|
||||||
}
|
}
|
||||||
@ -296,6 +271,14 @@ public class AppDialogBuilder {
|
|||||||
return isResizable;
|
return isResizable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置是否可调整大小
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setResizable(boolean resizable) {
|
||||||
|
isResizable = resizable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public double getHBoxSpacing() {
|
public double getHBoxSpacing() {
|
||||||
return hBoxSpacing;
|
return hBoxSpacing;
|
||||||
}
|
}
|
||||||
@ -304,6 +287,14 @@ public class AppDialogBuilder {
|
|||||||
return vboxPos;
|
return vboxPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置垂直盒子位置
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setVboxPos(Pos vboxPos) {
|
||||||
|
this.vboxPos = vboxPos;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Pos getHboxPos() {
|
public Pos getHboxPos() {
|
||||||
return hboxPos;
|
return hboxPos;
|
||||||
}
|
}
|
||||||
@ -311,4 +302,12 @@ public class AppDialogBuilder {
|
|||||||
public Modality getModality() {
|
public Modality getModality() {
|
||||||
return modality;
|
return modality;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置模态性
|
||||||
|
*/
|
||||||
|
public AppDialogBuilder setModality(Modality modality) {
|
||||||
|
this.modality = modality;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,9 +44,6 @@ public class UiUtil {
|
|||||||
|
|
||||||
private static final FontIcon SUCCESS_ICON = FontIcon.of(CHECK_CIRCLE);
|
private static final FontIcon SUCCESS_ICON = FontIcon.of(CHECK_CIRCLE);
|
||||||
|
|
||||||
private UiUtil() {
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// 暂时设置颜色
|
// 暂时设置颜色
|
||||||
ERROR_ICON.getStyleClass().addAll(Styles.DANGER);
|
ERROR_ICON.getStyleClass().addAll(Styles.DANGER);
|
||||||
@ -56,6 +53,9 @@ public class UiUtil {
|
|||||||
SUCCESS_ICON.getStyleClass().addAll(Styles.SUCCESS);
|
SUCCESS_ICON.getStyleClass().addAll(Styles.SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private UiUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取应用程序图标。
|
* 获取应用程序图标。
|
||||||
*
|
*
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import javafx.scene.layout.BorderPane;
|
|||||||
import org.jcnc.jnotepad.exception.AppException;
|
import org.jcnc.jnotepad.exception.AppException;
|
||||||
import org.jcnc.jnotepad.views.root.RootBorderPane;
|
import org.jcnc.jnotepad.views.root.RootBorderPane;
|
||||||
|
|
||||||
|
import static org.jcnc.jnotepad.views.root.bottom.RootBottomSideBarVerticalBox.initSidebarVerticalBox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视图管理器类,用于管理记事本应用程序的视图组件。
|
* 视图管理器类,用于管理记事本应用程序的视图组件。
|
||||||
*
|
*
|
||||||
@ -72,5 +74,6 @@ public class ViewManager {
|
|||||||
root.setCenter(RootBorderPane.getInstance());
|
root.setCenter(RootBorderPane.getInstance());
|
||||||
|
|
||||||
scene.setRoot(root);
|
scene.setRoot(root);
|
||||||
|
initSidebarVerticalBox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package org.jcnc.jnotepad.views.root.bottom;
|
|||||||
|
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import org.jcnc.jnotepad.ui.module.AbstractVerticalBox;
|
import org.jcnc.jnotepad.ui.module.AbstractVerticalBox;
|
||||||
import org.jcnc.jnotepad.views.root.bottom.cmd.CmdStatusBox;
|
import org.jcnc.jnotepad.views.root.bottom.function.FunctionBox;
|
||||||
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox;
|
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,7 +14,10 @@ import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox;
|
|||||||
*/
|
*/
|
||||||
public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
|
public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
|
||||||
|
|
||||||
VBox bottomSideBarVerticalBox;
|
/**
|
||||||
|
* VBox实例
|
||||||
|
*/
|
||||||
|
private static final VBox V_BOX_INSTANCE = new VBox();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 RootBottomSideBarVerticalBox 的唯一实例。
|
* 获取 RootBottomSideBarVerticalBox 的唯一实例。
|
||||||
@ -25,20 +28,30 @@ public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
|
|||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initSidebarVerticalBox() {
|
public RootBottomSideBarVerticalBox() {
|
||||||
bottomSideBarVerticalBox = new VBox();
|
|
||||||
|
|
||||||
bottomSideBarVerticalBox.getChildren().addAll(CmdStatusBox.getInstance(), BottomStatusBox.getInstance());
|
}
|
||||||
|
|
||||||
|
|
||||||
getChildren().addAll(bottomSideBarVerticalBox);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取vbox实例
|
||||||
|
*
|
||||||
|
* @return VBox
|
||||||
|
*/
|
||||||
|
public static VBox getVboxInstance() {
|
||||||
|
return V_BOX_INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox();
|
private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox();
|
||||||
|
|
||||||
public RootBottomSideBarVerticalBox() {
|
public static void initSidebarVerticalBox() {
|
||||||
initSidebarVerticalBox();
|
FunctionBox functionBox = FunctionBox.getInstance();
|
||||||
|
if (!FunctionBox.getMenuBar().getMenus().isEmpty()) {
|
||||||
|
functionBox.getChildren().add(FunctionBox.getMenuBar());
|
||||||
|
V_BOX_INSTANCE.getChildren().addAll(functionBox);
|
||||||
|
}
|
||||||
|
V_BOX_INSTANCE.getChildren().addAll(BottomStatusBox.getInstance());
|
||||||
|
INSTANCE.getChildren().addAll(V_BOX_INSTANCE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,118 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.views.root.bottom.cmd;
|
|
||||||
|
|
||||||
import javafx.geometry.Insets;
|
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.Menu;
|
|
||||||
import javafx.scene.control.MenuBar;
|
|
||||||
import javafx.scene.layout.BorderPane;
|
|
||||||
import javafx.scene.layout.HBox;
|
|
||||||
import javafx.scene.layout.Priority;
|
|
||||||
import javafx.stage.Stage;
|
|
||||||
import org.jcnc.jnotepad.ui.module.TerminalEmulatorComponent;
|
|
||||||
import org.jcnc.jnotepad.util.UiUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CmdStatusBox 类表示应用程序的命令状态框。
|
|
||||||
* <p>
|
|
||||||
* 该框包括一个菜单栏,用于运行、终端和构建命令。用户可以点击终端菜单项以切换终端的显示状态。
|
|
||||||
* 终端显示时,将创建一个新的窗口以显示终端模拟器组件。
|
|
||||||
*
|
|
||||||
* @author luke
|
|
||||||
*/
|
|
||||||
public class CmdStatusBox extends HBox {
|
|
||||||
|
|
||||||
Stage terminalStage = new Stage();
|
|
||||||
|
|
||||||
private static final CmdStatusBox CMD_STATUS_BOX = new CmdStatusBox();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用于跟踪终端的显示状态
|
|
||||||
*/
|
|
||||||
private boolean terminalVisible = false;
|
|
||||||
|
|
||||||
private CmdStatusBox() {
|
|
||||||
initStatusBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 CmdStatusBox 的实例。
|
|
||||||
*
|
|
||||||
* @return CmdStatusBox 的实例
|
|
||||||
*/
|
|
||||||
public static CmdStatusBox getInstance() {
|
|
||||||
return CMD_STATUS_BOX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化命令状态框。
|
|
||||||
*/
|
|
||||||
public void initStatusBox() {
|
|
||||||
var menuBar = new MenuBar();
|
|
||||||
HBox.setHgrow(menuBar, Priority.ALWAYS);
|
|
||||||
menuBar.setPadding(new Insets(-3, 0, -3, 35));
|
|
||||||
|
|
||||||
var runMenu = new Menu();
|
|
||||||
var cmdMenu = new Menu();
|
|
||||||
var buildMenu = new Menu();
|
|
||||||
|
|
||||||
var runLabel = new Label("运行");
|
|
||||||
var cmdLabel = new Label("终端");
|
|
||||||
var buildLabel = new Label("构建");
|
|
||||||
|
|
||||||
runMenu.setGraphic(runLabel);
|
|
||||||
cmdMenu.setGraphic(cmdLabel);
|
|
||||||
buildMenu.setGraphic(buildLabel);
|
|
||||||
|
|
||||||
cmdLabel.setOnMouseClicked(mouseEvent -> {
|
|
||||||
toggleTerminal(); // 切换终端的显示/隐藏状态
|
|
||||||
});
|
|
||||||
|
|
||||||
menuBar.getMenus().addAll(runMenu, cmdMenu, buildMenu);
|
|
||||||
this.getChildren().add(menuBar);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换终端的显示/隐藏状态。
|
|
||||||
*/
|
|
||||||
private void toggleTerminal() {
|
|
||||||
if (terminalVisible) {
|
|
||||||
// 隐藏终端
|
|
||||||
terminalVisible = false;
|
|
||||||
hideTerminal();
|
|
||||||
} else {
|
|
||||||
// 显示终端
|
|
||||||
terminalVisible = true;
|
|
||||||
showTerminal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 隐藏终端窗口。
|
|
||||||
*/
|
|
||||||
private void hideTerminal() {
|
|
||||||
terminalStage.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示终端窗口。
|
|
||||||
*/
|
|
||||||
private void showTerminal() {
|
|
||||||
// 创建一个新的舞台(窗口)
|
|
||||||
terminalStage.setTitle("终端");
|
|
||||||
terminalStage.getIcons().add(UiUtil.getAppIcon());
|
|
||||||
|
|
||||||
// 创建一个根节点(布局)
|
|
||||||
BorderPane root = new BorderPane();
|
|
||||||
Scene scene = new Scene(root, UiUtil.getAppWindow().getWidth() - 50, UiUtil.getAppWindow().getHeight() / 3);
|
|
||||||
|
|
||||||
// 创建TerminalEmulatorComponent并添加到根节点
|
|
||||||
TerminalEmulatorComponent terminal = new TerminalEmulatorComponent();
|
|
||||||
|
|
||||||
root.setCenter(terminal);
|
|
||||||
terminalStage.setScene(scene);
|
|
||||||
|
|
||||||
// 显示窗口
|
|
||||||
terminalStage.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package org.jcnc.jnotepad.views.root.bottom.function;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.control.MenuBar;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能栏
|
||||||
|
*
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
public class FunctionBox extends HBox {
|
||||||
|
private static final FunctionBox INSTANCE = new FunctionBox();
|
||||||
|
|
||||||
|
private static final MenuBar MENU_BAR = new MenuBar();
|
||||||
|
|
||||||
|
static {
|
||||||
|
HBox.setHgrow(MENU_BAR, Priority.ALWAYS);
|
||||||
|
MENU_BAR.setPadding(new Insets(-3, 0, -3, 35));
|
||||||
|
}
|
||||||
|
|
||||||
|
private FunctionBox() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FunctionBox getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MenuBar getMenuBar() {
|
||||||
|
return MENU_BAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package org.jcnc.jnotepad.views.root.bottom.function.interfaces;
|
||||||
|
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.Menu;
|
||||||
|
import javafx.scene.control.MenuBar;
|
||||||
|
import org.jcnc.jnotepad.views.root.bottom.function.FunctionBox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子功能栏抽象类(用于构建一个基本的子功能栏)
|
||||||
|
*
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
public abstract class AbstractFunctionChildrenBox {
|
||||||
|
protected final FunctionBox functionBox;
|
||||||
|
|
||||||
|
protected final MenuBar menuBar;
|
||||||
|
|
||||||
|
protected final Label label = new Label(getFunctionName());
|
||||||
|
|
||||||
|
protected Menu menu = new Menu();
|
||||||
|
|
||||||
|
protected AbstractFunctionChildrenBox() {
|
||||||
|
functionBox = FunctionBox.getInstance();
|
||||||
|
menuBar = FunctionBox.getMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
menu.setGraphic(label);
|
||||||
|
menuBar.getMenus().add(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取功能按钮名称
|
||||||
|
*
|
||||||
|
* @return 功能按钮名称
|
||||||
|
*/
|
||||||
|
protected abstract String getFunctionName();
|
||||||
|
}
|
||||||
@ -5,7 +5,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* tab修改标签样式 */
|
/* tab修改标签样式 */
|
||||||
.tab-title-editable {
|
.tab-title-editable {
|
||||||
-fx-fx-border-width: 0;
|
-fx-fx-border-width: 0;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user