commit
a0bf563e08
6
.gitignore
vendored
6
.gitignore
vendored
@ -11,6 +11,10 @@ test/
|
||||
### 此处忽略了json与xml后缀
|
||||
*.xml
|
||||
*.json
|
||||
|
||||
### 此处排除证书目录
|
||||
certificate/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
@ -47,4 +51,4 @@ logs/
|
||||
/en_language_pack.txt
|
||||
/jnotepadConfig.json
|
||||
/qodana.yaml
|
||||
.mvn/
|
||||
.mvn/
|
||||
|
||||
@ -20,7 +20,6 @@ module org.jcnc.jnotepad {
|
||||
requires org.commonmark;
|
||||
requires javafx.web;
|
||||
|
||||
|
||||
exports org.jcnc.jnotepad;
|
||||
exports org.jcnc.jnotepad.model.enums;
|
||||
exports org.jcnc.jnotepad.app.config;
|
||||
|
||||
@ -31,6 +31,8 @@ public class LunchApp extends Application {
|
||||
APPLICATION_MANAGER.setPrimaryStage(primaryStage);
|
||||
// 加载应用程序资源
|
||||
APPLICATION_MANAGER.loadAppResources();
|
||||
// 加载应用程序缓存
|
||||
APPLICATION_MANAGER.loadAppCache();
|
||||
// 初始化应用程序
|
||||
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.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.manager.Controller;
|
||||
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
||||
@ -76,7 +78,7 @@ public class ApplicationManager {
|
||||
}
|
||||
|
||||
public void initializeDefaultAction() {
|
||||
// 使用线程池加载关联文件并创建文本区域
|
||||
// 使用加载关联文件并创建文本区域
|
||||
List<String> rawParameters = application.getParameters().getRaw();
|
||||
Controller.getInstance().openAssociatedFileAndCreateTextArea(rawParameters);
|
||||
}
|
||||
@ -96,11 +98,16 @@ public class ApplicationManager {
|
||||
primaryStage.getIcons().add(UiUtil.getAppIcon());
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载缓存
|
||||
*/
|
||||
public void loadAppCache() {
|
||||
// 加载缓存
|
||||
CacheController.getInstance().loadCaches();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载资源
|
||||
*
|
||||
* @apiNote
|
||||
* @since 2023/9/20 18:29
|
||||
*/
|
||||
public void loadAppResources() {
|
||||
// 加载资源
|
||||
@ -115,12 +122,18 @@ public class ApplicationManager {
|
||||
* @apiNote 在停止程序之前会执行此操作
|
||||
*/
|
||||
public void stopApp() {
|
||||
PluginConfigController instance = PluginConfigController.getInstance();
|
||||
PluginConfigController pluginConfigController = PluginConfigController.getInstance();
|
||||
// 刷新插件配置文件
|
||||
instance.getConfig().setPlugins(PluginManager.getInstance().getPluginDescriptors());
|
||||
instance.writeConfig();
|
||||
pluginConfigController.getConfig().setPlugins(PluginManager.getInstance().getPluginDescriptors());
|
||||
pluginConfigController.writeConfig();
|
||||
// 保存配置文件
|
||||
AppConfigController.getInstance().writeConfig();
|
||||
// 销毁插件可能申请的资源
|
||||
PluginManager.getInstance().destroyPlugins();
|
||||
// 保存已打开的文件标签页
|
||||
CenterTabPaneManager.getInstance().saveOpenFileTabs();
|
||||
// 将缓存写入本地
|
||||
CacheController.getInstance().writeCaches();
|
||||
// 关闭线程池
|
||||
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();
|
||||
|
||||
/**
|
||||
* 创建缓存类
|
||||
*
|
||||
* @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 缓存集合
|
||||
*/
|
||||
|
||||
public abstract Map<String, Cache<?>> getCaches();
|
||||
public abstract Map<String, Cache> getCaches();
|
||||
|
||||
/**
|
||||
* 设置缓存集合
|
||||
*
|
||||
* @param caches 缓存集合
|
||||
*/
|
||||
public abstract void setCaches(Map<String, Cache<?>> caches);
|
||||
public abstract void setCaches(Map<String, Cache> caches);
|
||||
|
||||
/**
|
||||
* 添加缓存
|
||||
*
|
||||
* @param cache 缓存
|
||||
*/
|
||||
public void addCache(Cache<?> cache) {
|
||||
public void addCache(Cache cache) {
|
||||
String cacheKey = cache.getCacheKey();
|
||||
// 如果集合中已存在该缓存,则更新读写时间
|
||||
if (caches.containsKey(cacheKey)) {
|
||||
@ -57,18 +71,29 @@ public abstract class AbstractCacheManager {
|
||||
* @param cacheKey 缓存key
|
||||
* @return 缓存类
|
||||
*/
|
||||
public Cache<?> getCache(String cacheKey) {
|
||||
if (caches.isEmpty()) {
|
||||
public Cache getCache(String cacheKey) {
|
||||
if (caches == null || caches.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (caches.containsKey(cacheKey)) {
|
||||
Cache<?> cache = caches.get(cacheKey);
|
||||
Cache cache = caches.get(cacheKey);
|
||||
cache.setLastReadOrWriteTime(System.currentTimeMillis());
|
||||
return cache;
|
||||
}
|
||||
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 缓存类
|
||||
*/
|
||||
public Object getCacheData(String cacheKey) {
|
||||
Cache<?> cache = getCache(cacheKey);
|
||||
Cache cache = getCache(cacheKey);
|
||||
if (cache == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -22,12 +22,12 @@ public class ApplicationCacheManager extends AbstractCacheManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Cache<?>> getCaches() {
|
||||
public Map<String, Cache> getCaches() {
|
||||
return caches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCaches(Map<String, Cache<?>> caches) {
|
||||
public void setCaches(Map<String, Cache> caches) {
|
||||
this.caches = caches;
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +1,23 @@
|
||||
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.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.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
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 {
|
||||
|
||||
private static final ApplicationCacheManager APPLICATION_CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
|
||||
private static final CacheController INSTANCE = new CacheController();
|
||||
|
||||
private String cacheDir;
|
||||
|
||||
private CacheController() {
|
||||
cacheDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), ".jnotepad", "caches").toString();
|
||||
loadCaches();
|
||||
}
|
||||
|
||||
public static CacheController getInstance() {
|
||||
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) -> {
|
||||
// 判断当前命名空间对应目录是否创建
|
||||
@ -58,17 +172,61 @@ public class CacheController {
|
||||
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;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
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.module.LineNumberTextArea;
|
||||
import org.jcnc.jnotepad.util.EncodingDetector;
|
||||
@ -24,8 +24,6 @@ import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import static org.jcnc.jnotepad.common.manager.ThreadPoolManager.threadContSelfSubtracting;
|
||||
|
||||
/**
|
||||
* 打开文件的事件处理程序。
|
||||
* <p>
|
||||
@ -34,6 +32,8 @@ import static org.jcnc.jnotepad.common.manager.ThreadPoolManager.threadContSelfS
|
||||
* @author 许轲
|
||||
*/
|
||||
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
|
||||
public void handle(ActionEvent event) {
|
||||
// 获取缓存
|
||||
Cache cache = CACHE_MANAGER.getCache("folder", "openFile");
|
||||
// 显示文件选择对话框,并获取选中的文件
|
||||
File file = BasicFileChooserFactory.getInstance().createFileChooser(
|
||||
UiResourceBundle.getContent(TextConstants.OPEN),
|
||||
null,
|
||||
null,
|
||||
cache == null ? null : new File((String) cache.getCacheData()),
|
||||
new FileChooser.ExtensionFilter("All types", "*.*"))
|
||||
.showOpenDialog(UiUtil.getAppWindow());
|
||||
if (file == null) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建打开文件的任务。
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
ThreadPoolManager.getThreadPool().submit(createOpenFileTask(file));
|
||||
getText(file);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,25 +96,24 @@ public class OpenFile implements EventHandler<ActionEvent> {
|
||||
LineNumberTextArea textArea = createNewTextArea();
|
||||
// 检测文件编码
|
||||
Charset encoding = EncodingDetector.detectEncodingCharset(file);
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
|
||||
StringBuilder textBuilder = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (!textBuilder.isEmpty()) {
|
||||
textBuilder.append("\n");
|
||||
if (!stringBuilder.isEmpty()) {
|
||||
stringBuilder.append("\n");
|
||||
}
|
||||
textBuilder.append(line);
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
String text = textBuilder.toString();
|
||||
String text = stringBuilder.toString();
|
||||
LogUtil.getLogger(this.getClass()).info("已调用读取文件功能");
|
||||
Platform.runLater(() -> {
|
||||
textArea.appendText(text);
|
||||
CenterTab tab = createNewTab(file.getName(), textArea, encoding);
|
||||
// 设置当前标签页关联本地文件
|
||||
tab.setRelevance(true);
|
||||
tab.setUserData(file);
|
||||
CenterTabPaneManager.getInstance().addNewTab(tab);
|
||||
});
|
||||
|
||||
textArea.appendText(text);
|
||||
CenterTab tab = createNewTab(file.getName(), textArea, encoding);
|
||||
// 设置当前标签页关联本地文件
|
||||
tab.setRelevance(true);
|
||||
tab.setUserData(file);
|
||||
CenterTabPaneManager.getInstance().addNewTab(tab);
|
||||
} catch (IOException ignored) {
|
||||
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
|
||||
}
|
||||
|
||||
@ -139,6 +139,7 @@ public class RenameFile implements EventHandler<ActionEvent> {
|
||||
private void handleRenameRelevanceFile(CenterTab centerTab) {
|
||||
// 获取原始文件对象
|
||||
File file = (File) centerTab.getUserData();
|
||||
|
||||
// 获取应用窗口并绑定
|
||||
File newFile = BasicFileChooserFactory.getInstance()
|
||||
.createFileChooser(
|
||||
|
||||
@ -5,8 +5,11 @@ import javafx.event.EventHandler;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
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.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.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
@ -28,6 +31,7 @@ import static org.jcnc.jnotepad.controller.config.AppConfigController.CONFIG_NAM
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class SaveFile implements EventHandler<ActionEvent> {
|
||||
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
@ -51,7 +55,7 @@ public class SaveFile implements EventHandler<ActionEvent> {
|
||||
} else {
|
||||
logger.info("当前保存文件为关联打开文件,调用自动保存方法");
|
||||
// 调用tab保存方法
|
||||
selectedTab.save();
|
||||
selectedTab.saveSelectedFileTab();
|
||||
// 如果该文件是配置文件,则刷新快捷键
|
||||
if (CONFIG_NAME.equals(selectedTab.getText())) {
|
||||
// 重新加载语言包和快捷键
|
||||
@ -76,13 +80,20 @@ public class SaveFile implements EventHandler<ActionEvent> {
|
||||
if (selectedTab == null) {
|
||||
return;
|
||||
}
|
||||
Cache cache = CACHE_MANAGER.getCache("folder", "saveFile");
|
||||
File file = BasicFileChooserFactory.getInstance().createFileChooser(
|
||||
UiResourceBundle.getContent(TextConstants.SAVE_AS),
|
||||
selectedTab.getText(),
|
||||
null,
|
||||
cache == null ? null : new File((String) cache.getCacheData()),
|
||||
new FileChooser.ExtensionFilter("All types", "*.*"))
|
||||
.showSaveDialog(UiUtil.getAppWindow());
|
||||
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());
|
||||
selectedTab.save(file);
|
||||
// 将保存后的文件设置为关联文件
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
package org.jcnc.jnotepad.controller.manager;
|
||||
|
||||
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.OpenFile;
|
||||
import org.jcnc.jnotepad.model.entity.Cache;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
@ -13,6 +15,7 @@ import java.util.List;
|
||||
* @author 许轲
|
||||
*/
|
||||
public class Controller implements ControllerAble {
|
||||
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||
|
||||
private static final Controller INSTANCE = new Controller();
|
||||
|
||||
@ -35,10 +38,17 @@ public class Controller implements ControllerAble {
|
||||
*/
|
||||
@Override
|
||||
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)));
|
||||
|
||||
if (!rawParameters.isEmpty()) {
|
||||
String filePath = rawParameters.get(0);
|
||||
openAssociatedFile(filePath);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (fileTab.isEmpty()) {
|
||||
new NewFile().addNewFileTab();
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class Cache<T> {
|
||||
public class Cache {
|
||||
/**
|
||||
* 命名空间
|
||||
*/
|
||||
@ -22,12 +22,13 @@ public class Cache<T> {
|
||||
/**
|
||||
* 缓存名称
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 缓存数据
|
||||
*/
|
||||
private T cacheData;
|
||||
private Object cacheData;
|
||||
/**
|
||||
* 过期时间<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.group = group;
|
||||
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
|
||||
*/
|
||||
@JsonIgnore
|
||||
public String getCacheKey() {
|
||||
return this.getNamespace() + "." + this.getGroup() + "." + this.getName();
|
||||
return getCacheKey(namespace, group, name);
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
@ -83,11 +97,11 @@ public class Cache<T> {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public T getCacheData() {
|
||||
public Object getCacheData() {
|
||||
return cacheData;
|
||||
}
|
||||
|
||||
public void setCacheData(T cacheData) {
|
||||
public void setCacheData(Object 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) {
|
||||
for (PluginDescriptor configPluginDescriptor : configPluginDescriptors) {
|
||||
if ((configPluginDescriptor.getName() + configPluginDescriptor.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
||||
if (configPluginDescriptor.getId().equals(pluginDescriptor.getId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -110,7 +110,7 @@ public class PluginLoader {
|
||||
Iterator<PluginDescriptor> iterator = pluginDescriptors.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
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())) {
|
||||
return true;
|
||||
}
|
||||
@ -137,7 +137,7 @@ public class PluginLoader {
|
||||
* @since 2023/9/19 18:45
|
||||
*/
|
||||
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);
|
||||
pluginDescriptors.add(pluginDescriptor);
|
||||
return true;
|
||||
|
||||
@ -86,7 +86,7 @@ public class PluginManager {
|
||||
try {
|
||||
File pluginJar = new File(path.toString());
|
||||
PluginDescriptor temp = readPlugin(pluginJar);
|
||||
if ((temp.getName() + temp.getAuthor()).equals(pluginDescriptor.getName() + pluginDescriptor.getAuthor())) {
|
||||
if (temp.getId().equals(pluginDescriptor.getId())) {
|
||||
Files.delete(pluginJar.toPath());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
@ -12,18 +12,9 @@ import org.fxmisc.richtext.LineNumberFactory;
|
||||
import org.fxmisc.richtext.model.Paragraph;
|
||||
import org.fxmisc.richtext.model.StyleSpans;
|
||||
import org.fxmisc.richtext.model.StyleSpansBuilder;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager;
|
||||
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
|
||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
|
||||
import org.reactfx.Subscription;
|
||||
import org.reactfx.collection.ListModification;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -84,11 +75,6 @@ public class LineNumberTextArea extends CodeArea {
|
||||
+ "|(?<COMMENT>" + COMMENT_PATTERN + ")"
|
||||
);
|
||||
|
||||
/**
|
||||
* 用于记录日志的静态Logger对象
|
||||
*/
|
||||
private static final Logger logger = LogUtil.getLogger(LineNumberTextArea.class);
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* <p>
|
||||
@ -128,10 +114,7 @@ public class LineNumberTextArea extends CodeArea {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
initListeners();
|
||||
this.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/css/java_code_styles.css")).toString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -243,51 +226,4 @@ public class LineNumberTextArea extends CodeArea {
|
||||
System.out.println(((CodeArea) getOwnerNode()).getText());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化监听器方法
|
||||
*/
|
||||
private void initListeners() {
|
||||
// 监听主要文本区域的文本变化
|
||||
this.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
BottomStatusBoxManager.getInstance().updateWordCountStatusLabel();
|
||||
save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存方法
|
||||
*/
|
||||
public void save() {
|
||||
// 获取当前选定的中央标签页(CenterTab对象)
|
||||
CenterTab tab = CenterTabPaneManager.getInstance().getSelected();
|
||||
|
||||
// 如果没有选定标签页,返回,不执行保存操作
|
||||
if (tab == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 从标签页的用户数据中获取文件对象
|
||||
File file = (File) tab.getUserData();
|
||||
|
||||
// 获取主文本区域中的文本内容
|
||||
String newValue = this.getText();
|
||||
|
||||
// 如果文件对象为空,记录警告信息并返回,不执行保存操作
|
||||
if (file == null) {
|
||||
logger.warn("Tab上没有关联文件信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试使用BufferedWriter写入文件内容
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, tab.getCharset()))) {
|
||||
// 将新的文本内容写入文件
|
||||
writer.write(newValue);
|
||||
// 记录保存操作的日志信息
|
||||
LogUtil.getLogger(this.getClass()).info("正在自动保存---");
|
||||
} catch (IOException ignored) {
|
||||
// 如果发生IO异常,记录忽视的日志信息,但不中断程序执行
|
||||
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,8 +26,6 @@ import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||
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.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
@ -272,14 +270,11 @@ public class PluginManagementPane extends BorderPane {
|
||||
BooleanProperty booleanProperty = toggleSwitch.selectedProperty();
|
||||
state.textProperty().bind(Bindings.when(booleanProperty).then("禁用").otherwise("启用"));
|
||||
|
||||
uninstallItem.setOnAction(event -> PopUpUtil.warningAlert("卸载", "确定要卸载" + pluginDescriptor.getName() + "吗?", "此操作无法撤销!", new DialogButtonAction() {
|
||||
@Override
|
||||
public void handleAction(AppDialog dialog) {
|
||||
pluginManager.unloadPlugin(pluginDescriptor);
|
||||
state.setDisable(true);
|
||||
toggleSwitch.setDisable(true);
|
||||
dialog.close();
|
||||
}
|
||||
uninstallItem.setOnAction(event -> PopUpUtil.warningAlert("卸载", "确定要卸载" + pluginDescriptor.getName() + "吗?", "此操作无法撤销!", dialog -> {
|
||||
pluginManager.unloadPlugin(pluginDescriptor);
|
||||
state.setDisable(true);
|
||||
toggleSwitch.setDisable(true);
|
||||
dialog.close();
|
||||
}, null));
|
||||
state.getStyleClass().addAll(Styles.ACCENT);
|
||||
state.setPrefWidth(80);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package org.jcnc.jnotepad.util;
|
||||
|
||||
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.DefaultPrettyPrinter;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -35,7 +36,7 @@ public class JsonUtil {
|
||||
* 将对象转换为 JSON 字符串。
|
||||
*
|
||||
* @param o 要转换的对象
|
||||
* @return 对象的 JSON 表示,如果转换失败则抛出 AppException 异常
|
||||
* @return 对象的 JSON 表示
|
||||
* @throws AppException 如果转换失败
|
||||
*/
|
||||
public static String toJsonString(Object o) {
|
||||
@ -45,4 +46,36 @@ public class JsonUtil {
|
||||
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;
|
||||
|
||||
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.model.enums.CacheExpirationTime;
|
||||
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.top.menu.TopMenuBar;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 中心标签页窗格管理类
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class CenterTabPaneManager {
|
||||
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||
private static final CenterTabPaneManager INSTANCE = new CenterTabPaneManager();
|
||||
|
||||
private final CenterTabPane centerTabPane = CenterTabPane.getInstance();
|
||||
@ -88,4 +97,21 @@ public class CenterTabPaneManager {
|
||||
selectedTab.setAutoLine(AppConfigController.getInstance().getAutoLineConfig());
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,15 @@ import javafx.scene.control.Tab;
|
||||
import org.fxmisc.flowless.VirtualizedScrollPane;
|
||||
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||
import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager;
|
||||
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
@ -15,7 +22,7 @@ import java.nio.charset.Charset;
|
||||
* @author songdragon
|
||||
*/
|
||||
public class CenterTab extends Tab {
|
||||
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
private final LineNumberTextArea lineNumberTextArea;
|
||||
/**
|
||||
* 默认关闭自动换行
|
||||
@ -38,6 +45,7 @@ public class CenterTab extends Tab {
|
||||
public CenterTab(String tabTitle, LineNumberTextArea textArea, Charset charset) {
|
||||
super(tabTitle);
|
||||
lineNumberTextArea = textArea;
|
||||
initTextAreaListeners();
|
||||
this.setContent(new VirtualizedScrollPane<>(lineNumberTextArea));
|
||||
setAutoLine(AppConfigController.getInstance().getAutoLineConfig());
|
||||
this.charset = charset;
|
||||
@ -73,12 +81,50 @@ public class CenterTab extends Tab {
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件内容
|
||||
* 保存选中的文件标签页
|
||||
*/
|
||||
public void save() {
|
||||
this.lineNumberTextArea.save();
|
||||
public void saveSelectedFileTab() {
|
||||
// 获取当前选定的中央标签页(CenterTab对象)
|
||||
CenterTab tab = CenterTabPaneManager.getInstance().getSelected();
|
||||
|
||||
// 如果没有选定标签页,返回,不执行保存操作
|
||||
if (tab == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 从标签页的用户数据中获取文件对象
|
||||
File file = (File) tab.getUserData();
|
||||
// 获取主文本区域中的文本内容
|
||||
String newValue = tab.getLineNumberTextArea().getText();
|
||||
|
||||
// 如果文件对象为空,记录警告信息并返回,不执行保存操作
|
||||
if (file == null) {
|
||||
logger.warn("Tab上没有关联文件信息");
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试使用BufferedWriter写入文件内容
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, tab.getCharset()))) {
|
||||
// 将新的文本内容写入文件
|
||||
writer.write(newValue);
|
||||
// 记录保存操作的日志信息
|
||||
LogUtil.getLogger(this.getClass()).info("正在自动保存---");
|
||||
} catch (IOException ignored) {
|
||||
// 如果发生IO异常,记录忽视的日志信息,但不中断程序执行
|
||||
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化监听器方法
|
||||
*/
|
||||
private void initTextAreaListeners() {
|
||||
// 监听主要文本区域的文本变化
|
||||
lineNumberTextArea.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
BottomStatusBoxManager.getInstance().updateWordCountStatusLabel();
|
||||
saveSelectedFileTab();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 保存为指定文件
|
||||
*
|
||||
@ -89,6 +135,7 @@ public class CenterTab extends Tab {
|
||||
return;
|
||||
}
|
||||
this.setUserData(file);
|
||||
save();
|
||||
saveSelectedFileTab();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ import javafx.scene.control.TabPane;
|
||||
* @author songdragon
|
||||
*/
|
||||
public class CenterTabPane extends TabPane {
|
||||
|
||||
private static final CenterTabPane INSTANCE = new CenterTabPane();
|
||||
|
||||
private CenterTabPane() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user