Merge remote-tracking branch '我的仓库/release-v1.1.13' into release-v1.1.13

This commit is contained in:
许轲 2023-10-05 18:58:14 +08:00
commit 52c8f13355
16 changed files with 238 additions and 71 deletions

View File

@ -125,9 +125,13 @@ POM文件中的全部依赖项
- Windows 平台
![Windows](screenshot/windows-1.png)
- MacOS 平台
- MacOS 平台 (待更新,原因:没有设备)
![MacOS](screenshot/Mac0S-1.png)
- Linux 平台
![Linux](screenshot/Linux-1.png)
# 参与贡献
1. 加入JCNC社区

BIN
screenshot/Linux-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

View File

@ -27,7 +27,7 @@ public class LunchApp extends Application {
@Override
public void start(Stage primaryStage) {
// 获取当前启动位置
// 获取当前启动位置a
String currentWorkingDirectory = System.getProperty("user.dir");
LogUtil.getLogger(this.getClass()).info("当前启动位置:{}", currentWorkingDirectory);
@ -47,6 +47,6 @@ public class LunchApp extends Application {
@Override
public void stop() {
APPLICATION_MANAGER.stopApp();
APPLICATION_MANAGER.operationBeforeStopping();
}
}
}

View File

@ -22,7 +22,9 @@ import java.nio.file.Paths;
*/
public abstract class BaseConfigController<T> implements ConfigController<T> {
public static final String ROOT_CONFIG_DIR = "config";
protected final String rootConfigDir = "config";
protected final String systemConfigDir = "system";
protected T config;
Logger logger = LogUtil.getLogger(this.getClass());

View File

@ -1,8 +1,15 @@
package org.jcnc.jnotepad.app.config;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.File;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
/**
* 应用程序配置文件
@ -14,12 +21,51 @@ public class AppConfig {
* 程序根路径
*/
private String rootPath;
/**
* 排除的文件夹
*/
@JsonIgnore
private final Set<File> ignoreFolder;
/**
* 排除的文件
*/
@JsonIgnore
private final Set<File> ignoreFile;
/**
* 上次的程序根路径
*/
@JsonIgnore
private String lastRootPath;
public AppConfig() {
ignoreFolder = Set.of(
new File(Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, "system").toString()),
new File(Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, "logs").toString())
);
ignoreFile = Collections.emptySet();
}
public String getRootPath() {
return Optional.of(rootPath).orElse(System.getProperty(DEFAULT_PROPERTY));
return Optional.ofNullable(rootPath).orElse(System.getProperty(DEFAULT_PROPERTY));
}
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}
public String getLastRootPath() {
return lastRootPath;
}
public void setLastRootPath(String lastRootPath) {
this.lastRootPath = lastRootPath;
}
public Set<File> getIgnoreFolder() {
return ignoreFolder;
}
public Set<File> getIgnoreFile() {
return ignoreFile;
}
}

View File

@ -8,24 +8,35 @@ import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.jcnc.jnotepad.LunchApp;
import org.jcnc.jnotepad.app.config.AppConfig;
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.cache.CacheController;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.controller.config.PluginConfigController;
import org.jcnc.jnotepad.controller.exception.AppException;
import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.plugin.manager.PluginManager;
import org.jcnc.jnotepad.util.FileUtil;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
/**
* 应用程序管理类<br/>
@ -130,11 +141,42 @@ public class ApplicationManager {
}
/**
* 停止程序
* 迁移程序根文件夹
*/
public void migrateFileRootFolder() {
AppConfig config = AppConfigController.getInstance().getConfig();
String lastRootPath = config.getLastRootPath();
if (lastRootPath == null) {
return;
}
// 获取源文件夹
File sourceFolder = new File(lastRootPath, PROGRAM_FILE_DIRECTORY);
// 获取目标文件夹
File targetFolder = new File(config.getRootPath(), PROGRAM_FILE_DIRECTORY);
// 设置忽略文件夹
Set<File> ignoredFolders = config.getIgnoreFolder();
// 设置忽略文件
Set<File> ignoredFiles = config.getIgnoreFile();
// 移动文件夹
FileUtil.migrateFolder(sourceFolder, targetFolder, ignoredFolders, ignoredFiles);
// 删除.jnotepad
if (!sourceFolder.equals(new File(Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY).toString()))) {
try {
Files.delete(sourceFolder.toPath());
} catch (IOException e) {
throw new AppException(e);
}
}
// 保存新配置
AppConfigController.getInstance().writeConfig();
}
/**
* 停止前操作
*
* @apiNote 在停止程序之前会执行此操作
*/
public void stopApp() {
public void operationBeforeStopping() {
PluginConfigController pluginConfigController = PluginConfigController.getInstance();
// 刷新插件配置文件
pluginConfigController.getConfig().setPlugins(PluginManager.getInstance().getPluginDescriptors());
@ -146,6 +188,8 @@ public class ApplicationManager {
CenterTabPaneManager.getInstance().saveOpenFileTabs();
// 将缓存写入本地
CacheController.getInstance().writeCaches();
// 迁移文件夹
migrateFileRootFolder();
// 关闭线程池
threadPool.shutdownNow();
}
@ -205,12 +249,11 @@ public class ApplicationManager {
// 构建新进程来重新启动应用程序
ProcessBuilder builder = new ProcessBuilder(javaCommand, "-cp", System.getProperty("java.class.path"), mainClass);
builder.start();
// 关闭当前应用程序
System.exit(0);
// fixme 使用这个System.exit(0);在开发环境点击重启程序停止前操作不生效
stop();
} catch (IOException e) {
LogUtil.getLogger("正在重启当前应用程序".getClass());
}
}
@ -239,7 +282,7 @@ public class ApplicationManager {
this.primaryStage = primaryStage;
}
public void stopApplication() {
public void stop() {
Platform.exit();
}
}

View File

@ -44,6 +44,10 @@ public class AppConstants {
* 默认属性
*/
public static final String DEFAULT_PROPERTY = "user.home";
/**
* 程序文件目录
*/
public static final String PROGRAM_FILE_DIRECTORY = ".jnotepad";
/**

View File

@ -1,7 +1,5 @@
package org.jcnc.jnotepad.component.module.interfaces;
import java.util.List;
/**
* 控制器接口类
*
@ -9,14 +7,14 @@ import java.util.List;
*
* @author 许轲
*/
public interface ControllerAble {
public interface ControllerAble<T> {
/**
* 打开关联文件并创建 TextArea
*
* @param rawParameters 原始参数列表
*/
void openAssociatedFileAndCreateTextArea(List<String> rawParameters);
void openAssociatedFileAndCreateTextArea(T rawParameters);
/**
* 打开关联文件

View File

@ -266,6 +266,9 @@ public class SetStage extends Stage {
cache.setCacheData(file.getParent());
cacheManager.addCache(cache);
}
// 设置上次的根路径
config.setLastRootPath(config.getRootPath());
// 设置当前根路径
config.setRootPath(file.getAbsolutePath());
PopUpUtil.questionAlert("更改", "设置程序文件根路径", "设置成功,请重启程序以应用路径更改!", appDialog -> {
appDialog.close();

View File

@ -1,25 +1,15 @@
package org.jcnc.jnotepad.controller;
import org.jcnc.jnotepad.controller.config.PluginConfigController;
import org.jcnc.jnotepad.controller.exception.AppException;
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
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() {
}
@ -33,42 +23,6 @@ public class ResourceController {
// 1. 加载语言
LocalizationController.initLocal();
// 2. 加载插件
loadPlugins();
}
/**
* 装载插件
*
* @since 2023/9/15 21:39
*/
public void loadPlugins() {
// 扫描并装载插件
scanLoadPlugins(PluginConfigController.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);
}
PluginLoader.getInstance().loadPlugins();
}
}

View File

@ -6,6 +6,7 @@ import org.jcnc.jnotepad.app.config.AppConfig;
import java.nio.file.Paths;
import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
/**
* 应用程序配置文件控制器
@ -23,12 +24,12 @@ public class AppConfigController extends BaseConfigController<AppConfig> {
/**
* 配置文件名
*/
public static final String CONFIG_NAME = "appConfig.json";
public static final String CONFIG_NAME = "JNotepadConfig.json";
private final String configDir;
public AppConfigController() {
configDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), ".jnotepad", ROOT_CONFIG_DIR).toString();
configDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, systemConfigDir).toString();
loadConfig();
}

View File

@ -7,6 +7,8 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
/**
* 插件控制器
*
@ -24,8 +26,8 @@ public class PluginConfigController extends BaseConfigController<PluginConfig> {
private PluginConfigController() {
String rootPath = AppConfigController.getInstance().getConfig().getRootPath();
configDir = Paths.get(rootPath, ".jnotepad", ROOT_CONFIG_DIR).toString();
setPluginsDir(Paths.get(rootPath, ".jnotepad", "plugins").toString());
configDir = Paths.get(rootPath, PROGRAM_FILE_DIRECTORY, rootConfigDir).toString();
setPluginsDir(Paths.get(rootPath, PROGRAM_FILE_DIRECTORY, "plugins").toString());
loadConfig();
}

View File

@ -8,6 +8,7 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
import static org.jcnc.jnotepad.common.constants.TextConstants.CHINESE;
/**
@ -31,7 +32,7 @@ public class UserConfigController extends BaseConfigController<UserConfig> {
private String configDir;
private UserConfigController() {
configDir = Paths.get(AppConfigController.getInstance().getConfig().getRootPath(), ".jnotepad", ROOT_CONFIG_DIR).toString();
configDir = Paths.get(AppConfigController.getInstance().getConfig().getRootPath(), PROGRAM_FILE_DIRECTORY, rootConfigDir).toString();
loadConfig();
}

View File

@ -15,7 +15,7 @@ import java.util.Optional;
*
* @author 许轲
*/
public class Controller implements ControllerAble {
public class Controller implements ControllerAble<List<String>> {
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
private static final Controller INSTANCE = new Controller();

View File

@ -14,10 +14,13 @@ import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
/**
@ -244,4 +247,39 @@ public class PluginLoader {
logger.info("已加载插件:{}", pluginDescriptor.getName());
return pluginClass;
}
/**
* 装载插件
*
* @since 2023/9/15 21:39
*/
public void loadPlugins() {
// 扫描并装载插件
scanLoadPlugins(PluginConfigController.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

@ -15,6 +15,7 @@ import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Set;
import static org.kordamp.ikonli.antdesignicons.AntDesignIconsFilled.*;
@ -170,7 +171,7 @@ public class FileUtil {
* @since 2023/10/5 12:18
*/
private static void migrateFolder(File sourceFolder, File targetFolder) {
public static void migrateFolder(File sourceFolder, File targetFolder) {
// 创建目标文件夹
targetFolder.mkdirs();
@ -197,4 +198,74 @@ public class FileUtil {
}
}
/**
* 迁移文件夹
*
* @param sourceFolder 源文件夹
* @param targetFolder 目标文件夹
* @param ignoredFolders 忽略的文件夹集合
* @param ignoredFiles 忽略的文件集合
* @since 2023/10/5 13:58
*/
public static void migrateFolder(File sourceFolder, File targetFolder, Set<File> ignoredFolders, Set<File> ignoredFiles) {
// 创建目标文件夹
targetFolder.mkdir();
// 获取源文件夹中的所有文件和文件夹
File[] files = sourceFolder.listFiles();
if (files != null) {
// 遍历源文件夹中的每个文件和文件夹
for (File file : files) {
// 如果是文件夹且不是忽略的文件夹递归调用自身进行迁移
if (file.isDirectory() && !ignoredFolders.contains(file)) {
migrateFolder(targetFolder, ignoredFolders, ignoredFiles, file);
continue;
}
// 如果是文件且不是忽略的文件将文件复制到目标文件夹中
if (!file.isDirectory() && !ignoredFiles.contains(file)) {
migrateFile(targetFolder, file);
}
}
}
}
/**
* 迁移文件
*
* @param targetFolder 目标文件夹
* @param file 文件
*/
public static void migrateFile(File targetFolder, File file) {
Path sourceFilePath = file.toPath();
Path targetFilePath = new File(targetFolder, file.getName()).toPath();
try {
Files.copy(sourceFilePath, targetFilePath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new AppException(e);
}
// 删除源文件
try {
Files.delete(file.toPath());
} catch (IOException e) {
throw new AppException(e);
}
}
/**
* 迁移文件夹
*
* @param targetFolder 目标文件夹
* @param ignoredFolders 忽略的文件夹集合
* @param ignoredFiles 忽略的文件集合
* @param file 文件
*/
private static void migrateFolder(File targetFolder, Set<File> ignoredFolders, Set<File> ignoredFiles, File file) {
migrateFolder(file, new File(targetFolder, file.getName()), ignoredFolders, ignoredFiles);
// 调用完毕删除当前目录
try {
Files.deleteIfExists(file.toPath());
} catch (IOException e) {
throw new AppException(e);
}
}
}