🚩 实现缓存逻辑缓存逻辑
This commit is contained in:
parent
b02ab2ac99
commit
35551de78b
6
.gitignore
vendored
6
.gitignore
vendored
@ -11,6 +11,10 @@ test/
|
|||||||
### 此处忽略了json与xml后缀
|
### 此处忽略了json与xml后缀
|
||||||
*.xml
|
*.xml
|
||||||
*.json
|
*.json
|
||||||
|
|
||||||
|
### 此处排除证书目录
|
||||||
|
certificate/
|
||||||
|
|
||||||
### Eclipse ###
|
### Eclipse ###
|
||||||
.apt_generated
|
.apt_generated
|
||||||
.classpath
|
.classpath
|
||||||
@ -47,4 +51,4 @@ logs/
|
|||||||
/en_language_pack.txt
|
/en_language_pack.txt
|
||||||
/jnotepadConfig.json
|
/jnotepadConfig.json
|
||||||
/qodana.yaml
|
/qodana.yaml
|
||||||
.mvn/
|
.mvn/
|
||||||
|
|||||||
@ -20,7 +20,6 @@ module org.jcnc.jnotepad {
|
|||||||
requires org.commonmark;
|
requires org.commonmark;
|
||||||
requires javafx.web;
|
requires javafx.web;
|
||||||
|
|
||||||
|
|
||||||
exports org.jcnc.jnotepad;
|
exports org.jcnc.jnotepad;
|
||||||
exports org.jcnc.jnotepad.model.enums;
|
exports org.jcnc.jnotepad.model.enums;
|
||||||
exports org.jcnc.jnotepad.app.config;
|
exports org.jcnc.jnotepad.app.config;
|
||||||
|
|||||||
@ -31,6 +31,8 @@ public class LunchApp extends Application {
|
|||||||
APPLICATION_MANAGER.setPrimaryStage(primaryStage);
|
APPLICATION_MANAGER.setPrimaryStage(primaryStage);
|
||||||
// 加载应用程序资源
|
// 加载应用程序资源
|
||||||
APPLICATION_MANAGER.loadAppResources();
|
APPLICATION_MANAGER.loadAppResources();
|
||||||
|
// 加载应用程序缓存
|
||||||
|
APPLICATION_MANAGER.loadAppCache();
|
||||||
// 初始化应用程序
|
// 初始化应用程序
|
||||||
APPLICATION_MANAGER.initializeApp();
|
APPLICATION_MANAGER.initializeApp();
|
||||||
// 初始化默认操作
|
// 初始化默认操作
|
||||||
|
|||||||
@ -12,6 +12,8 @@ import org.jcnc.jnotepad.common.constants.AppConstants;
|
|||||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||||
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
||||||
import org.jcnc.jnotepad.controller.ResourceController;
|
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.config.PluginConfigController;
|
||||||
import org.jcnc.jnotepad.controller.manager.Controller;
|
import org.jcnc.jnotepad.controller.manager.Controller;
|
||||||
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
||||||
@ -76,7 +78,7 @@ public class ApplicationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initializeDefaultAction() {
|
public void initializeDefaultAction() {
|
||||||
// 使用线程池加载关联文件并创建文本区域
|
// 使用加载关联文件并创建文本区域
|
||||||
List<String> rawParameters = application.getParameters().getRaw();
|
List<String> rawParameters = application.getParameters().getRaw();
|
||||||
Controller.getInstance().openAssociatedFileAndCreateTextArea(rawParameters);
|
Controller.getInstance().openAssociatedFileAndCreateTextArea(rawParameters);
|
||||||
}
|
}
|
||||||
@ -96,11 +98,16 @@ public class ApplicationManager {
|
|||||||
primaryStage.getIcons().add(UiUtil.getAppIcon());
|
primaryStage.getIcons().add(UiUtil.getAppIcon());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载缓存
|
||||||
|
*/
|
||||||
|
public void loadAppCache() {
|
||||||
|
// 加载缓存
|
||||||
|
CacheController.getInstance().loadCaches();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载资源
|
* 加载资源
|
||||||
*
|
|
||||||
* @apiNote
|
|
||||||
* @since 2023/9/20 18:29
|
|
||||||
*/
|
*/
|
||||||
public void loadAppResources() {
|
public void loadAppResources() {
|
||||||
// 加载资源
|
// 加载资源
|
||||||
@ -115,12 +122,18 @@ public class ApplicationManager {
|
|||||||
* @apiNote 在停止程序之前会执行此操作
|
* @apiNote 在停止程序之前会执行此操作
|
||||||
*/
|
*/
|
||||||
public void stopApp() {
|
public void stopApp() {
|
||||||
PluginConfigController instance = PluginConfigController.getInstance();
|
PluginConfigController pluginConfigController = PluginConfigController.getInstance();
|
||||||
// 刷新插件配置文件
|
// 刷新插件配置文件
|
||||||
instance.getConfig().setPlugins(PluginManager.getInstance().getPluginDescriptors());
|
pluginConfigController.getConfig().setPlugins(PluginManager.getInstance().getPluginDescriptors());
|
||||||
instance.writeConfig();
|
pluginConfigController.writeConfig();
|
||||||
|
// 保存配置文件
|
||||||
|
AppConfigController.getInstance().writeConfig();
|
||||||
// 销毁插件可能申请的资源
|
// 销毁插件可能申请的资源
|
||||||
PluginManager.getInstance().destroyPlugins();
|
PluginManager.getInstance().destroyPlugins();
|
||||||
|
// 保存已打开的文件标签页
|
||||||
|
CenterTabPaneManager.getInstance().saveOpenFileTabs();
|
||||||
|
// 将缓存写入本地
|
||||||
|
CacheController.getInstance().writeCaches();
|
||||||
// 关闭线程池
|
// 关闭线程池
|
||||||
threadPool.shutdownNow();
|
threadPool.shutdownNow();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ public abstract class AbstractCacheManager {
|
|||||||
/**
|
/**
|
||||||
* 缓存集合
|
* 缓存集合
|
||||||
*/
|
*/
|
||||||
protected Map<String, Cache<?>> caches;
|
protected Map<String, Cache> caches;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取全局命名空间
|
* 获取全局命名空间
|
||||||
@ -22,27 +22,41 @@ public abstract class AbstractCacheManager {
|
|||||||
*/
|
*/
|
||||||
public abstract String getGlobalNamespace();
|
public abstract String getGlobalNamespace();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建缓存类
|
||||||
|
*
|
||||||
|
* @param group 缓存组
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @param cacheData 缓存数据
|
||||||
|
* @param expirationTime 过期时间
|
||||||
|
* @return 缓存类
|
||||||
|
* @apiNote 这个方法,只需通过自定义的缓存管理类调用此方法,无需每次指定相同地命名空间
|
||||||
|
*/
|
||||||
|
public Cache createCache(String group, String name, Object cacheData, Long expirationTime) {
|
||||||
|
return new Cache(getGlobalNamespace(), group, name, cacheData, expirationTime);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取缓存集合
|
* 获取缓存集合
|
||||||
*
|
*
|
||||||
* @return 缓存集合
|
* @return 缓存集合
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract Map<String, Cache<?>> getCaches();
|
public abstract Map<String, Cache> getCaches();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置缓存集合
|
* 设置缓存集合
|
||||||
*
|
*
|
||||||
* @param caches 缓存集合
|
* @param caches 缓存集合
|
||||||
*/
|
*/
|
||||||
public abstract void setCaches(Map<String, Cache<?>> caches);
|
public abstract void setCaches(Map<String, Cache> caches);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加缓存
|
* 添加缓存
|
||||||
*
|
*
|
||||||
* @param cache 缓存
|
* @param cache 缓存
|
||||||
*/
|
*/
|
||||||
public void addCache(Cache<?> cache) {
|
public void addCache(Cache cache) {
|
||||||
String cacheKey = cache.getCacheKey();
|
String cacheKey = cache.getCacheKey();
|
||||||
// 如果集合中已存在该缓存,则更新读写时间
|
// 如果集合中已存在该缓存,则更新读写时间
|
||||||
if (caches.containsKey(cacheKey)) {
|
if (caches.containsKey(cacheKey)) {
|
||||||
@ -57,18 +71,29 @@ public abstract class AbstractCacheManager {
|
|||||||
* @param cacheKey 缓存key
|
* @param cacheKey 缓存key
|
||||||
* @return 缓存类
|
* @return 缓存类
|
||||||
*/
|
*/
|
||||||
public Cache<?> getCache(String cacheKey) {
|
public Cache getCache(String cacheKey) {
|
||||||
if (caches.isEmpty()) {
|
if (caches == null || caches.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (caches.containsKey(cacheKey)) {
|
if (caches.containsKey(cacheKey)) {
|
||||||
Cache<?> cache = caches.get(cacheKey);
|
Cache cache = caches.get(cacheKey);
|
||||||
cache.setLastReadOrWriteTime(System.currentTimeMillis());
|
cache.setLastReadOrWriteTime(System.currentTimeMillis());
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存类
|
||||||
|
*
|
||||||
|
* @param group 组
|
||||||
|
* @param name 缓存名
|
||||||
|
* @return 缓存类
|
||||||
|
*/
|
||||||
|
public Cache getCache(String group, String name) {
|
||||||
|
return getCache(Cache.getCacheKey(getGlobalNamespace(), group, name));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取缓存数据
|
* 获取缓存数据
|
||||||
*
|
*
|
||||||
@ -76,7 +101,7 @@ public abstract class AbstractCacheManager {
|
|||||||
* @return 缓存类
|
* @return 缓存类
|
||||||
*/
|
*/
|
||||||
public Object getCacheData(String cacheKey) {
|
public Object getCacheData(String cacheKey) {
|
||||||
Cache<?> cache = getCache(cacheKey);
|
Cache cache = getCache(cacheKey);
|
||||||
if (cache == null) {
|
if (cache == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,12 +22,12 @@ public class ApplicationCacheManager extends AbstractCacheManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Cache<?>> getCaches() {
|
public Map<String, Cache> getCaches() {
|
||||||
return caches;
|
return caches;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCaches(Map<String, Cache<?>> caches) {
|
public void setCaches(Map<String, Cache> caches) {
|
||||||
this.caches = caches;
|
this.caches = caches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,23 @@
|
|||||||
package org.jcnc.jnotepad.controller.cache;
|
package org.jcnc.jnotepad.controller.cache;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||||
import org.jcnc.jnotepad.exception.AppException;
|
import org.jcnc.jnotepad.exception.AppException;
|
||||||
import org.jcnc.jnotepad.model.entity.Cache;
|
import org.jcnc.jnotepad.model.entity.Cache;
|
||||||
|
import org.jcnc.jnotepad.util.JsonUtil;
|
||||||
|
import org.jcnc.jnotepad.util.LogUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
|
import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
|
||||||
|
|
||||||
@ -17,28 +28,131 @@ import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
|
|||||||
*/
|
*/
|
||||||
public class CacheController {
|
public class CacheController {
|
||||||
|
|
||||||
|
private static final ApplicationCacheManager APPLICATION_CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||||
|
Logger logger = LogUtil.getLogger(this.getClass());
|
||||||
|
|
||||||
private static final CacheController INSTANCE = new CacheController();
|
private static final CacheController INSTANCE = new CacheController();
|
||||||
|
|
||||||
private String cacheDir;
|
private String cacheDir;
|
||||||
|
|
||||||
private CacheController() {
|
private CacheController() {
|
||||||
cacheDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), ".jnotepad", "caches").toString();
|
cacheDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), ".jnotepad", "caches").toString();
|
||||||
loadCaches();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CacheController getInstance() {
|
public static CacheController getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadCaches() {
|
public void loadCaches() {
|
||||||
|
// 如果本地没有缓存的话,就创建缓存
|
||||||
|
if (createCachesIfNotExists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查并获取缓存根目录
|
||||||
|
File cacheFileDir = createCacheRootIfNotExist();
|
||||||
|
// 获取缓存命名空间
|
||||||
|
String[] namespaces = cacheFileDir.list();
|
||||||
|
// 如果缓存根目录下为空,则创建缓存
|
||||||
|
if (Objects.requireNonNull(namespaces).length == 0) {
|
||||||
|
APPLICATION_CACHE_MANAGER.setCaches(new HashMap<>(16));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, Cache> caches = new HashMap<>(16);
|
||||||
|
for (String namespace : namespaces) {
|
||||||
|
// 获取命名空间对应的文件夹
|
||||||
|
File namespaceDir = new File(cacheFileDir, namespace);
|
||||||
|
// 获取缓存组对应的文件名称列表
|
||||||
|
String[] groupNames = namespaceDir.list();
|
||||||
|
// 如果命名空间文件夹下没有文件则删除该文件夹
|
||||||
|
if (cleanEmptyFileOrFolder(namespaceDir)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (String groupName : Objects.requireNonNull(groupNames)) {
|
||||||
|
// 获取缓存组对应的文件
|
||||||
|
File groupFile = new File(namespaceDir, groupName);
|
||||||
|
// 清理空文件
|
||||||
|
if (cleanEmptyFileOrFolder(groupFile)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 获取缓存
|
||||||
|
try {
|
||||||
|
String cacheJson = Files.readString(groupFile.toPath());
|
||||||
|
// 获取缓存集合
|
||||||
|
Map<String, Cache> cacheMap = JsonUtil.fromJsonString(cacheJson, new TypeReference<>() {
|
||||||
|
});
|
||||||
|
// 设置缓存
|
||||||
|
cacheMap.forEach((k, v) -> setUpCache(namespace, groupName, k, v, caches));
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("读取缓存文件出错!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 设置缓存
|
||||||
|
APPLICATION_CACHE_MANAGER.setCaches(caches);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeCaches(Map<String, Cache<?>> caches) {
|
/**
|
||||||
File cacheFileDir = new File(cacheDir);
|
* 设置缓存
|
||||||
if (!cacheFileDir.exists()) {
|
*
|
||||||
cacheFileDir.mkdirs();
|
* @param namespace 命名空间
|
||||||
|
* @param groupName 缓存组
|
||||||
|
* @param k 缓存名称
|
||||||
|
* @param v 缓存类
|
||||||
|
* @param caches 缓存集合
|
||||||
|
*/
|
||||||
|
private void setUpCache(String namespace, String groupName, String k, Cache v, Map<String, Cache> caches) {
|
||||||
|
// 判断缓存是否过期,没有过期才加载进内存
|
||||||
|
if (v.getLastReadOrWriteTime() + v.getExpirationTime() > System.currentTimeMillis() || v.getExpirationTime() < 0) {
|
||||||
|
v.setNamespace(namespace);
|
||||||
|
v.setGroup(groupName);
|
||||||
|
v.setName(k);
|
||||||
|
caches.put(v.getCacheKey(), v);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理空文件或空文件夹并返回结果
|
||||||
|
*
|
||||||
|
* @param fileOrFolder 文件或文件夹
|
||||||
|
* @return 是否清理
|
||||||
|
*/
|
||||||
|
private boolean cleanEmptyFileOrFolder(File fileOrFolder) {
|
||||||
|
try {
|
||||||
|
if (fileOrFolder.isFile() && fileOrFolder.length() == 0) {
|
||||||
|
Files.delete(fileOrFolder.toPath());
|
||||||
|
logger.info("删除缓存文件:{}", fileOrFolder);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileOrFolder.isDirectory() && Objects.requireNonNull(fileOrFolder.list()).length == 0) {
|
||||||
|
Files.delete(fileOrFolder.toPath());
|
||||||
|
logger.info("删除缓存文件夹:{}", fileOrFolder);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AppException(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写缓存(writeCache)
|
||||||
|
*/
|
||||||
|
public void writeCaches() {
|
||||||
|
writeCaches(APPLICATION_CACHE_MANAGER.getCaches());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写缓存
|
||||||
|
*
|
||||||
|
* @param caches 缓存集合
|
||||||
|
*/
|
||||||
|
public void writeCaches(Map<String, Cache> caches) {
|
||||||
|
// 检查并获取缓存根目录
|
||||||
|
File cacheFileDir = createCacheRootIfNotExist();
|
||||||
|
Map<File, Map<String, Cache>> fileMap = new HashMap<>(16);
|
||||||
// 生成缓存
|
// 生成缓存
|
||||||
caches.forEach((key, value) -> {
|
caches.forEach((key, value) -> {
|
||||||
// 判断当前命名空间对应目录是否创建
|
// 判断当前命名空间对应目录是否创建
|
||||||
@ -58,17 +172,61 @@ public class CacheController {
|
|||||||
throw new AppException(e);
|
throw new AppException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fileMap.computeIfAbsent(groupFile, k -> new HashMap<>(16));
|
||||||
|
// 设置需要写入的数据
|
||||||
|
fileMap.get(groupFile).put(value.getName(), value);
|
||||||
});
|
});
|
||||||
|
Set<File> fileSet = fileMap.keySet();
|
||||||
//
|
// 清空原来的缓存
|
||||||
|
fileSet.forEach(file -> {
|
||||||
|
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
|
||||||
|
fileOutputStream.write(new byte[0]);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AppException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 写入缓存
|
||||||
|
for (Map.Entry<File, Map<String, Cache>> entry : fileMap.entrySet()) {
|
||||||
|
try (FileWriter writer = new FileWriter(entry.getKey(), true)) {
|
||||||
|
writer.write(JsonUtil.toJsonString(entry.getValue()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AppException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 如果缓存
|
* 如果不存在,则创建缓存根目录
|
||||||
|
*
|
||||||
|
* @return 缓存根目录
|
||||||
*/
|
*/
|
||||||
private void createCachesIfNotExists() {
|
private File createCacheRootIfNotExist() {
|
||||||
|
File cacheFileDir = new File(cacheDir);
|
||||||
|
if (!cacheFileDir.exists()) {
|
||||||
|
cacheFileDir.mkdirs();
|
||||||
|
}
|
||||||
|
return cacheFileDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果本地没有缓存则创建缓存
|
||||||
|
*
|
||||||
|
* @return 是否创建成功
|
||||||
|
*/
|
||||||
|
private boolean createCachesIfNotExists() {
|
||||||
|
File cacheFileDir = createCacheRootIfNotExist();
|
||||||
|
if (Objects.requireNonNull(cacheFileDir.list()).length == 0) {
|
||||||
|
APPLICATION_CACHE_MANAGER.setCaches(new HashMap<>(16));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCacheDir() {
|
||||||
|
return cacheDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCacheDir(String cacheDir) {
|
||||||
|
this.cacheDir = cacheDir;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
package org.jcnc.jnotepad.controller.event.handler.menubar;
|
package org.jcnc.jnotepad.controller.event.handler.menubar;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.concurrent.Task;
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||||
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||||
|
import org.jcnc.jnotepad.model.entity.Cache;
|
||||||
|
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
|
||||||
import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory;
|
import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory;
|
||||||
import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
|
||||||
import org.jcnc.jnotepad.util.EncodingDetector;
|
import org.jcnc.jnotepad.util.EncodingDetector;
|
||||||
@ -24,8 +24,6 @@ import java.io.FileReader;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
import static org.jcnc.jnotepad.common.manager.ThreadPoolManager.threadContSelfSubtracting;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开文件的事件处理程序。
|
* 打开文件的事件处理程序。
|
||||||
* <p>
|
* <p>
|
||||||
@ -34,6 +32,8 @@ import static org.jcnc.jnotepad.common.manager.ThreadPoolManager.threadContSelfS
|
|||||||
* @author 许轲
|
* @author 许轲
|
||||||
*/
|
*/
|
||||||
public class OpenFile implements EventHandler<ActionEvent> {
|
public class OpenFile implements EventHandler<ActionEvent> {
|
||||||
|
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理打开文件事件。
|
* 处理打开文件事件。
|
||||||
*
|
*
|
||||||
@ -41,42 +41,28 @@ public class OpenFile implements EventHandler<ActionEvent> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void handle(ActionEvent event) {
|
public void handle(ActionEvent event) {
|
||||||
|
// 获取缓存
|
||||||
|
Cache cache = CACHE_MANAGER.getCache("folder", "openFile");
|
||||||
// 显示文件选择对话框,并获取选中的文件
|
// 显示文件选择对话框,并获取选中的文件
|
||||||
File file = BasicFileChooserFactory.getInstance().createFileChooser(
|
File file = BasicFileChooserFactory.getInstance().createFileChooser(
|
||||||
UiResourceBundle.getContent(TextConstants.OPEN),
|
UiResourceBundle.getContent(TextConstants.OPEN),
|
||||||
null,
|
null,
|
||||||
null,
|
cache == null ? null : new File((String) cache.getCacheData()),
|
||||||
new FileChooser.ExtensionFilter("All types", "*.*"))
|
new FileChooser.ExtensionFilter("All types", "*.*"))
|
||||||
.showOpenDialog(UiUtil.getAppWindow());
|
.showOpenDialog(UiUtil.getAppWindow());
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 设置缓存
|
||||||
|
if (cache == null) {
|
||||||
|
CACHE_MANAGER.addCache(CACHE_MANAGER.createCache("folder", "openFile", file.getParent(), CacheExpirationTime.NEVER_EXPIRES.getValue()));
|
||||||
|
} else {
|
||||||
|
cache.setCacheData(file.getParent());
|
||||||
|
CACHE_MANAGER.addCache(cache);
|
||||||
|
}
|
||||||
openFile(file);
|
openFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建打开文件的任务。
|
|
||||||
*
|
|
||||||
* @param file 文件对象
|
|
||||||
* @return 打开文件的任务
|
|
||||||
*/
|
|
||||||
public Task<Void> createOpenFileTask(File file) {
|
|
||||||
Task<Void> openFileTask = new Task<>() {
|
|
||||||
@Override
|
|
||||||
protected Void call() {
|
|
||||||
getText(file);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
// 设置任务成功完成时的处理逻辑
|
|
||||||
openFileTask.setOnSucceeded(e -> threadContSelfSubtracting());
|
|
||||||
|
|
||||||
// 设置任务失败时的处理逻辑
|
|
||||||
openFileTask.setOnFailed(e -> threadContSelfSubtracting());
|
|
||||||
return openFileTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开文件。
|
* 打开文件。
|
||||||
*
|
*
|
||||||
@ -98,7 +84,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ThreadPoolManager.getThreadPool().submit(createOpenFileTask(file));
|
getText(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,25 +96,24 @@ public class OpenFile implements EventHandler<ActionEvent> {
|
|||||||
LineNumberTextArea textArea = createNewTextArea();
|
LineNumberTextArea textArea = createNewTextArea();
|
||||||
// 检测文件编码
|
// 检测文件编码
|
||||||
Charset encoding = EncodingDetector.detectEncodingCharset(file);
|
Charset encoding = EncodingDetector.detectEncodingCharset(file);
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
|
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
|
||||||
StringBuilder textBuilder = new StringBuilder();
|
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
if (!textBuilder.isEmpty()) {
|
if (!stringBuilder.isEmpty()) {
|
||||||
textBuilder.append("\n");
|
stringBuilder.append("\n");
|
||||||
}
|
}
|
||||||
textBuilder.append(line);
|
stringBuilder.append(line);
|
||||||
}
|
}
|
||||||
String text = textBuilder.toString();
|
String text = stringBuilder.toString();
|
||||||
LogUtil.getLogger(this.getClass()).info("已调用读取文件功能");
|
LogUtil.getLogger(this.getClass()).info("已调用读取文件功能");
|
||||||
Platform.runLater(() -> {
|
|
||||||
textArea.appendText(text);
|
textArea.appendText(text);
|
||||||
CenterTab tab = createNewTab(file.getName(), textArea, encoding);
|
CenterTab tab = createNewTab(file.getName(), textArea, encoding);
|
||||||
// 设置当前标签页关联本地文件
|
// 设置当前标签页关联本地文件
|
||||||
tab.setRelevance(true);
|
tab.setRelevance(true);
|
||||||
tab.setUserData(file);
|
tab.setUserData(file);
|
||||||
CenterTabPaneManager.getInstance().addNewTab(tab);
|
CenterTabPaneManager.getInstance().addNewTab(tab);
|
||||||
});
|
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
|
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,6 +139,7 @@ public class RenameFile implements EventHandler<ActionEvent> {
|
|||||||
private void handleRenameRelevanceFile(CenterTab centerTab) {
|
private void handleRenameRelevanceFile(CenterTab centerTab) {
|
||||||
// 获取原始文件对象
|
// 获取原始文件对象
|
||||||
File file = (File) centerTab.getUserData();
|
File file = (File) centerTab.getUserData();
|
||||||
|
|
||||||
// 获取应用窗口并绑定
|
// 获取应用窗口并绑定
|
||||||
File newFile = BasicFileChooserFactory.getInstance()
|
File newFile = BasicFileChooserFactory.getInstance()
|
||||||
.createFileChooser(
|
.createFileChooser(
|
||||||
|
|||||||
@ -5,8 +5,11 @@ import javafx.event.EventHandler;
|
|||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||||
|
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||||
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
|
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
|
||||||
|
import org.jcnc.jnotepad.model.entity.Cache;
|
||||||
|
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
|
||||||
import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory;
|
import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory;
|
||||||
import org.jcnc.jnotepad.util.LogUtil;
|
import org.jcnc.jnotepad.util.LogUtil;
|
||||||
import org.jcnc.jnotepad.util.UiUtil;
|
import org.jcnc.jnotepad.util.UiUtil;
|
||||||
@ -28,6 +31,7 @@ import static org.jcnc.jnotepad.controller.config.AppConfigController.CONFIG_NAM
|
|||||||
* @author gewuyou
|
* @author gewuyou
|
||||||
*/
|
*/
|
||||||
public class SaveFile implements EventHandler<ActionEvent> {
|
public class SaveFile implements EventHandler<ActionEvent> {
|
||||||
|
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||||
Logger logger = LogUtil.getLogger(this.getClass());
|
Logger logger = LogUtil.getLogger(this.getClass());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,13 +80,20 @@ public class SaveFile implements EventHandler<ActionEvent> {
|
|||||||
if (selectedTab == null) {
|
if (selectedTab == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Cache cache = CACHE_MANAGER.getCache("folder", "saveFile");
|
||||||
File file = BasicFileChooserFactory.getInstance().createFileChooser(
|
File file = BasicFileChooserFactory.getInstance().createFileChooser(
|
||||||
UiResourceBundle.getContent(TextConstants.SAVE_AS),
|
UiResourceBundle.getContent(TextConstants.SAVE_AS),
|
||||||
selectedTab.getText(),
|
selectedTab.getText(),
|
||||||
null,
|
cache == null ? null : new File((String) cache.getCacheData()),
|
||||||
new FileChooser.ExtensionFilter("All types", "*.*"))
|
new FileChooser.ExtensionFilter("All types", "*.*"))
|
||||||
.showSaveDialog(UiUtil.getAppWindow());
|
.showSaveDialog(UiUtil.getAppWindow());
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
|
if (cache == null) {
|
||||||
|
CACHE_MANAGER.addCache(CACHE_MANAGER.createCache("folder", "saveFile", file.getParent(), CacheExpirationTime.NEVER_EXPIRES.getValue()));
|
||||||
|
} else {
|
||||||
|
cache.setCacheData(file.getParent());
|
||||||
|
CACHE_MANAGER.addCache(cache);
|
||||||
|
}
|
||||||
LogUtil.getLogger(currentClass).info("正在保存文件: {}", file.getName());
|
LogUtil.getLogger(currentClass).info("正在保存文件: {}", file.getName());
|
||||||
selectedTab.save(file);
|
selectedTab.save(file);
|
||||||
// 将保存后的文件设置为关联文件
|
// 将保存后的文件设置为关联文件
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
package org.jcnc.jnotepad.controller.manager;
|
package org.jcnc.jnotepad.controller.manager;
|
||||||
|
|
||||||
import org.jcnc.jnotepad.common.interfaces.ControllerAble;
|
import org.jcnc.jnotepad.common.interfaces.ControllerAble;
|
||||||
|
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||||
import org.jcnc.jnotepad.controller.event.handler.menubar.NewFile;
|
import org.jcnc.jnotepad.controller.event.handler.menubar.NewFile;
|
||||||
import org.jcnc.jnotepad.controller.event.handler.menubar.OpenFile;
|
import org.jcnc.jnotepad.controller.event.handler.menubar.OpenFile;
|
||||||
|
import org.jcnc.jnotepad.model.entity.Cache;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -13,6 +15,7 @@ import java.util.List;
|
|||||||
* @author 许轲
|
* @author 许轲
|
||||||
*/
|
*/
|
||||||
public class Controller implements ControllerAble {
|
public class Controller implements ControllerAble {
|
||||||
|
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||||
|
|
||||||
private static final Controller INSTANCE = new Controller();
|
private static final Controller INSTANCE = new Controller();
|
||||||
|
|
||||||
@ -35,10 +38,19 @@ public class Controller implements ControllerAble {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void openAssociatedFileAndCreateTextArea(List<String> rawParameters) {
|
public void openAssociatedFileAndCreateTextArea(List<String> rawParameters) {
|
||||||
|
// 获取上次打开的页面
|
||||||
|
Cache cache = CACHE_MANAGER.getCache("tabs", "centerTabs");
|
||||||
|
List<String> fileTab = (List<String>) cache.getCacheData();
|
||||||
|
// fileTab.forEach(filePath -> new OpenFile().openFile(new File(filePath)));
|
||||||
|
for (String filePath : fileTab) {
|
||||||
|
new OpenFile().openFile(new File(filePath));
|
||||||
|
}
|
||||||
if (!rawParameters.isEmpty()) {
|
if (!rawParameters.isEmpty()) {
|
||||||
String filePath = rawParameters.get(0);
|
String filePath = rawParameters.get(0);
|
||||||
openAssociatedFile(filePath);
|
openAssociatedFile(filePath);
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
|
if (fileTab.isEmpty()) {
|
||||||
new NewFile().addNewFileTab();
|
new NewFile().addNewFileTab();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
|||||||
*
|
*
|
||||||
* @author gewuyou
|
* @author gewuyou
|
||||||
*/
|
*/
|
||||||
public class Cache<T> {
|
public class Cache {
|
||||||
/**
|
/**
|
||||||
* 命名空间
|
* 命名空间
|
||||||
*/
|
*/
|
||||||
@ -22,12 +22,13 @@ public class Cache<T> {
|
|||||||
/**
|
/**
|
||||||
* 缓存名称
|
* 缓存名称
|
||||||
*/
|
*/
|
||||||
|
@JsonIgnore
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存数据
|
* 缓存数据
|
||||||
*/
|
*/
|
||||||
private T cacheData;
|
private Object cacheData;
|
||||||
/**
|
/**
|
||||||
* 过期时间<br/>如果过期时间为负数则永不过期
|
* 过期时间<br/>如果过期时间为负数则永不过期
|
||||||
*/
|
*/
|
||||||
@ -41,7 +42,7 @@ public class Cache<T> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cache(String namespace, String group, String name, T cacheData, Long expirationTime) {
|
public Cache(String namespace, String group, String name, Object cacheData, Long expirationTime) {
|
||||||
this.namespace = namespace;
|
this.namespace = namespace;
|
||||||
this.group = group;
|
this.group = group;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -51,12 +52,25 @@ public class Cache<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据缓存key
|
* 生成缓存key
|
||||||
|
*
|
||||||
|
* @param namespace 命名空间
|
||||||
|
* @param group 组
|
||||||
|
* @param name 缓存名称
|
||||||
|
* @return 缓存key
|
||||||
|
*/
|
||||||
|
public static String getCacheKey(String namespace, String group, String name) {
|
||||||
|
return namespace + "." + group + "." + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存key
|
||||||
*
|
*
|
||||||
* @return key
|
* @return key
|
||||||
*/
|
*/
|
||||||
|
@JsonIgnore
|
||||||
public String getCacheKey() {
|
public String getCacheKey() {
|
||||||
return this.getNamespace() + "." + this.getGroup() + "." + this.getName();
|
return getCacheKey(namespace, group, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNamespace() {
|
public String getNamespace() {
|
||||||
@ -83,11 +97,11 @@ public class Cache<T> {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T getCacheData() {
|
public Object getCacheData() {
|
||||||
return cacheData;
|
return cacheData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCacheData(T cacheData) {
|
public void setCacheData(Object cacheData) {
|
||||||
this.cacheData = cacheData;
|
this.cacheData = cacheData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,44 @@
|
|||||||
|
package org.jcnc.jnotepad.model.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存过期时间枚举
|
||||||
|
*
|
||||||
|
* @author gewuyou
|
||||||
|
*/
|
||||||
|
public enum CacheExpirationTime {
|
||||||
|
/**
|
||||||
|
* 一小时
|
||||||
|
*/
|
||||||
|
ONE_HOUR(60 * 60 * 1000L),
|
||||||
|
/**
|
||||||
|
* 一天
|
||||||
|
*/
|
||||||
|
ONE_DAY(24 * ONE_HOUR.value),
|
||||||
|
/**
|
||||||
|
* 一周
|
||||||
|
*/
|
||||||
|
ONE_WEEK(7 * ONE_DAY.value),
|
||||||
|
/**
|
||||||
|
* 一月
|
||||||
|
*/
|
||||||
|
ONE_MONTH(30 * ONE_DAY.value),
|
||||||
|
/**
|
||||||
|
* 一年
|
||||||
|
*/
|
||||||
|
ONE_YEAR(365 * ONE_DAY.value),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 永不过期
|
||||||
|
*/
|
||||||
|
NEVER_EXPIRES(-1L);
|
||||||
|
private final Long value;
|
||||||
|
|
||||||
|
CacheExpirationTime(Long value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -99,7 +99,7 @@ public class PluginLoader {
|
|||||||
*/
|
*/
|
||||||
private static boolean pluginDoesNotExist(PluginDescriptor pluginDescriptor, List<PluginDescriptor> configPluginDescriptors) {
|
private static boolean pluginDoesNotExist(PluginDescriptor pluginDescriptor, List<PluginDescriptor> configPluginDescriptors) {
|
||||||
for (PluginDescriptor configPluginDescriptor : configPluginDescriptors) {
|
for (PluginDescriptor configPluginDescriptor : configPluginDescriptors) {
|
||||||
if ((configPluginDescriptor.getName() + configPluginDescriptor.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
if (configPluginDescriptor.getId().equals(pluginDescriptor.getId())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ public class PluginLoader {
|
|||||||
Iterator<PluginDescriptor> iterator = pluginDescriptors.iterator();
|
Iterator<PluginDescriptor> iterator = pluginDescriptors.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
PluginDescriptor plugin = iterator.next();
|
PluginDescriptor plugin = iterator.next();
|
||||||
if ((plugin.getName() + plugin.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
if (plugin.getId().equals(pluginDescriptor.getId())) {
|
||||||
if (plugin.getVersion().equals(pluginDescriptor.getVersion())) {
|
if (plugin.getVersion().equals(pluginDescriptor.getVersion())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ public class PluginLoader {
|
|||||||
* @since 2023/9/19 18:45
|
* @since 2023/9/19 18:45
|
||||||
*/
|
*/
|
||||||
private static boolean disableDoNotLoad(PluginDescriptor pluginDescriptor, List<PluginDescriptor> pluginDescriptors, PluginDescriptor configPluginDescriptor) {
|
private static boolean disableDoNotLoad(PluginDescriptor pluginDescriptor, List<PluginDescriptor> pluginDescriptors, PluginDescriptor configPluginDescriptor) {
|
||||||
if ((configPluginDescriptor.getName() + configPluginDescriptor.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor()) && !configPluginDescriptor.isEnabled()) {
|
if (configPluginDescriptor.getId().equals(pluginDescriptor.getId()) && !configPluginDescriptor.isEnabled()) {
|
||||||
pluginDescriptor.setEnabled(false);
|
pluginDescriptor.setEnabled(false);
|
||||||
pluginDescriptors.add(pluginDescriptor);
|
pluginDescriptors.add(pluginDescriptor);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -85,7 +85,7 @@ public class PluginManager {
|
|||||||
try {
|
try {
|
||||||
File pluginJar = new File(path.toString());
|
File pluginJar = new File(path.toString());
|
||||||
PluginDescriptor temp = readPlugin(pluginJar);
|
PluginDescriptor temp = readPlugin(pluginJar);
|
||||||
if ((temp.getName() + temp.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
if (temp.getId().equals(pluginDescriptor.getId())) {
|
||||||
Files.delete(pluginJar.toPath());
|
Files.delete(pluginJar.toPath());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@ -26,8 +26,6 @@ import org.commonmark.parser.Parser;
|
|||||||
import org.commonmark.renderer.html.HtmlRenderer;
|
import org.commonmark.renderer.html.HtmlRenderer;
|
||||||
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||||
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
||||||
import org.jcnc.jnotepad.ui.dialog.AppDialog;
|
|
||||||
import org.jcnc.jnotepad.ui.dialog.interfaces.DialogButtonAction;
|
|
||||||
import org.jcnc.jnotepad.ui.module.CustomSetButton;
|
import org.jcnc.jnotepad.ui.module.CustomSetButton;
|
||||||
import org.jcnc.jnotepad.util.LogUtil;
|
import org.jcnc.jnotepad.util.LogUtil;
|
||||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||||
@ -272,14 +270,11 @@ public class PluginManagementPane extends BorderPane {
|
|||||||
BooleanProperty booleanProperty = toggleSwitch.selectedProperty();
|
BooleanProperty booleanProperty = toggleSwitch.selectedProperty();
|
||||||
state.textProperty().bind(Bindings.when(booleanProperty).then("禁用").otherwise("启用"));
|
state.textProperty().bind(Bindings.when(booleanProperty).then("禁用").otherwise("启用"));
|
||||||
|
|
||||||
uninstallItem.setOnAction(event -> PopUpUtil.warningAlert("卸载", "确定要卸载" + pluginDescriptor.getName() + "吗?", "此操作无法撤销!", new DialogButtonAction() {
|
uninstallItem.setOnAction(event -> PopUpUtil.warningAlert("卸载", "确定要卸载" + pluginDescriptor.getName() + "吗?", "此操作无法撤销!", dialog -> {
|
||||||
@Override
|
pluginManager.unloadPlugin(pluginDescriptor);
|
||||||
public void handleAction(AppDialog dialog) {
|
state.setDisable(true);
|
||||||
pluginManager.unloadPlugin(pluginDescriptor);
|
toggleSwitch.setDisable(true);
|
||||||
state.setDisable(true);
|
dialog.close();
|
||||||
toggleSwitch.setDisable(true);
|
|
||||||
dialog.close();
|
|
||||||
}
|
|
||||||
}, null));
|
}, null));
|
||||||
state.getStyleClass().addAll(Styles.ACCENT);
|
state.getStyleClass().addAll(Styles.ACCENT);
|
||||||
state.setPrefWidth(80);
|
state.setPrefWidth(80);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.jnotepad.util;
|
package org.jcnc.jnotepad.util;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
||||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@ -35,7 +36,7 @@ public class JsonUtil {
|
|||||||
* 将对象转换为 JSON 字符串。
|
* 将对象转换为 JSON 字符串。
|
||||||
*
|
*
|
||||||
* @param o 要转换的对象
|
* @param o 要转换的对象
|
||||||
* @return 对象的 JSON 表示,如果转换失败则抛出 AppException 异常
|
* @return 对象的 JSON 表示
|
||||||
* @throws AppException 如果转换失败
|
* @throws AppException 如果转换失败
|
||||||
*/
|
*/
|
||||||
public static String toJsonString(Object o) {
|
public static String toJsonString(Object o) {
|
||||||
@ -45,4 +46,36 @@ public class JsonUtil {
|
|||||||
throw new AppException(e);
|
throw new AppException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将json字符串解析成对象
|
||||||
|
*
|
||||||
|
* @param json json字符串
|
||||||
|
* @param clazz 对象类型
|
||||||
|
* @return 对象
|
||||||
|
* @throws AppException 如果解析失败
|
||||||
|
*/
|
||||||
|
public static <T> T fromJsonString(String json, Class<T> clazz) {
|
||||||
|
try {
|
||||||
|
return OBJECT_MAPPER.readValue(json, clazz);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new AppException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将json字符串解析成对象
|
||||||
|
*
|
||||||
|
* @param json json字符串
|
||||||
|
* @param valueTypeRef 值 类型 引用
|
||||||
|
* @return 对象
|
||||||
|
* @throws AppException 如果解析失败
|
||||||
|
*/
|
||||||
|
public static <T> T fromJsonString(String json, TypeReference<T> valueTypeRef) {
|
||||||
|
try {
|
||||||
|
return OBJECT_MAPPER.readValue(json, valueTypeRef);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new AppException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,25 @@
|
|||||||
package org.jcnc.jnotepad.views.manager;
|
package org.jcnc.jnotepad.views.manager;
|
||||||
|
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.scene.control.Tab;
|
||||||
|
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||||
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
|
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
|
||||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
|
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.center.main.center.tab.CenterTabPane;
|
||||||
import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar;
|
import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 中心标签页窗格管理类
|
* 中心标签页窗格管理类
|
||||||
*
|
*
|
||||||
* @author gewuyou
|
* @author gewuyou
|
||||||
*/
|
*/
|
||||||
public class CenterTabPaneManager {
|
public class CenterTabPaneManager {
|
||||||
|
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||||
private static final CenterTabPaneManager INSTANCE = new CenterTabPaneManager();
|
private static final CenterTabPaneManager INSTANCE = new CenterTabPaneManager();
|
||||||
|
|
||||||
private final CenterTabPane centerTabPane = CenterTabPane.getInstance();
|
private final CenterTabPane centerTabPane = CenterTabPane.getInstance();
|
||||||
@ -88,4 +97,18 @@ public class CenterTabPaneManager {
|
|||||||
selectedTab.setAutoLine(AppConfigController.getInstance().getAutoLineConfig());
|
selectedTab.setAutoLine(AppConfigController.getInstance().getAutoLineConfig());
|
||||||
bottomStatusBoxManager.updateWhenTabSelected();
|
bottomStatusBoxManager.updateWhenTabSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveOpenFileTabs() {
|
||||||
|
// 获取当前所有标签页
|
||||||
|
ObservableList<Tab> tabs = centerTabPane.getTabs();
|
||||||
|
List<String> filePaths = new ArrayList<>();
|
||||||
|
// 缓存当前打开关联的文件
|
||||||
|
tabs.forEach(tab -> {
|
||||||
|
File file = (File) tab.getUserData();
|
||||||
|
if (file != null) {
|
||||||
|
filePaths.add(file.getPath());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
CACHE_MANAGER.addCache(CACHE_MANAGER.createCache("tabs", "centerTabs", filePaths, CacheExpirationTime.NEVER_EXPIRES.getValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,4 +91,5 @@ public class CenterTab extends Tab {
|
|||||||
this.setUserData(file);
|
this.setUserData(file);
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import javafx.scene.control.TabPane;
|
|||||||
* @author songdragon
|
* @author songdragon
|
||||||
*/
|
*/
|
||||||
public class CenterTabPane extends TabPane {
|
public class CenterTabPane extends TabPane {
|
||||||
|
|
||||||
private static final CenterTabPane INSTANCE = new CenterTabPane();
|
private static final CenterTabPane INSTANCE = new CenterTabPane();
|
||||||
|
|
||||||
private CenterTabPane() {
|
private CenterTabPane() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user