🚩 添加监测已打开的文件状态功能逻辑

This commit is contained in:
gewuyou 2023-10-02 20:29:12 +08:00
parent 89a0ce87b9
commit 239d69ddc3
32 changed files with 299 additions and 105 deletions

View File

@ -30,7 +30,7 @@ module org.jcnc.jnotepad {
exports org.jcnc.jnotepad.controller.i18n;
exports org.jcnc.jnotepad.controller.event.handler.setting;
exports org.jcnc.jnotepad.controller.event.handler.menubar;
exports org.jcnc.jnotepad.util;
exports org.jcnc.jnotepad.common.util;
exports org.jcnc.jnotepad.common.interfaces;
opens org.jcnc.jnotepad.app.config;
exports org.jcnc.jnotepad.plugin.interfaces;

View File

@ -11,13 +11,13 @@ 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.common.util.UiUtil;
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;
import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.*;
import java.util.List;

View File

@ -1,7 +1,7 @@
package org.jcnc.jnotepad.app.util;
import org.jcnc.jnotepad.LunchApp;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
import java.io.IOException;

View File

@ -42,14 +42,18 @@ public abstract class AbstractCacheManager {
* @return 缓存集合
*/
public abstract Map<String, Cache> getCaches();
public Map<String, Cache> getCaches() {
return caches;
}
/**
* 设置缓存集合
*
* @param caches 缓存集合
*/
public abstract void setCaches(Map<String, Cache> caches);
public void setCaches(Map<String, Cache> caches) {
this.caches = caches;
}
/**
* 添加缓存
@ -97,11 +101,12 @@ public abstract class AbstractCacheManager {
/**
* 获取缓存数据
*
* @param cacheKey 缓存key
* @param group
* @param name 缓存名
* @return 缓存类
*/
public Object getCacheData(String cacheKey) {
Cache cache = getCache(cacheKey);
public Object getCacheData(String group, String name) {
Cache cache = getCache(group, name);
if (cache == null) {
return null;
}

View File

@ -1,9 +1,5 @@
package org.jcnc.jnotepad.common.manager;
import org.jcnc.jnotepad.model.entity.Cache;
import java.util.Map;
/**
* 应用程序缓存管理类
*
@ -21,16 +17,6 @@ public class ApplicationCacheManager extends AbstractCacheManager {
return INSTANCE;
}
@Override
public Map<String, Cache> getCaches() {
return caches;
}
@Override
public void setCaches(Map<String, Cache> caches) {
this.caches = caches;
}
@Override
public String getGlobalNamespace() {
return "jcnc";

View File

@ -1,6 +1,6 @@
package org.jcnc.jnotepad.common.manager;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.slf4j.Logger;
import java.util.concurrent.*;

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.util;
package org.jcnc.jnotepad.common.util;
import com.ibm.icu.text.CharsetDetector;
import com.ibm.icu.text.CharsetMatch;

View File

@ -0,0 +1,129 @@
package org.jcnc.jnotepad.common.util;
import org.jcnc.jnotepad.controller.event.handler.menubar.OpenFile;
import org.jcnc.jnotepad.exception.AppException;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 文件工具
*
* @author gewuyou
*/
public class FileUtil {
private static final MessageDigest MESSAGE_DIGEST_SHA_256;
private static final int BUFFER_SIZE = 8192;
static {
try {
MESSAGE_DIGEST_SHA_256 = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new AppException(e);
}
}
private FileUtil() {
}
/**
* 将字节数组转换为String类型哈希值
*
* @param bytes 字节数组
* @return 哈希值
*/
private static String bytes2HashCode(byte[] bytes) {
StringBuilder hashString = new StringBuilder();
for (byte b : bytes) {
hashString.append(String.format("%02x", b));
}
return hashString.toString();
}
/**
* 获取本地文件Sha256哈希值字符串
*
* @param file 本地文件
* @return 本地文件Sha256哈希值
*/
public static String getLocalFileSha256HashString(File file) {
try (
// 获取文件输入流
FileInputStream fileInputStream = new FileInputStream(file);
// 获取字节流通道
FileChannel channel = fileInputStream.getChannel()
) {
// 设置8k缓冲区
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
while (channel.read(buffer) != -1) {
buffer.flip();
MESSAGE_DIGEST_SHA_256.update(buffer);
buffer.clear();
}
} catch (IOException e) {
throw new AppException(e);
}
return bytes2HashCode(MESSAGE_DIGEST_SHA_256.digest());
}
/**
* 获取本地文件Sha256哈希值字符串
*
* @param pathStr 本地文件路径字符串
* @return 本地文件Sha256哈希值
*/
public static String getLocalFileSha256HashString(String pathStr) {
return getLocalFileSha256HashString(new File(pathStr));
}
/**
* 获取本地文件Sha256哈希值字符串
*
* @param path 本地文件路径
* @return 本地文件Sha256哈希值
*/
public static String getLocalFileSha256HashString(Path path) {
return getLocalFileSha256HashString(path.toFile());
}
/**
* 获取文件中的文本内容
*
* @param file 文件对象
* @return 文本内容
*/
public static String getFileText(File file) {
return getFileText(file, EncodingDetector.detectEncodingCharset(file));
}
/**
* 获取文件中的文本内容
*
* @param file 文件对象
* @param encoding 文件编码
* @return 文本内容
*/
public static String getFileText(File file, Charset encoding) {
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
String line;
while ((line = reader.readLine()) != null) {
if (!stringBuilder.isEmpty()) {
stringBuilder.append("\n");
}
stringBuilder.append(line);
}
} catch (IOException ignored) {
LogUtil.getLogger(OpenFile.class).info("已忽视IO异常!");
}
return stringBuilder.toString();
}
}

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.util;
package org.jcnc.jnotepad.common.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.util;
package org.jcnc.jnotepad.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.util;
package org.jcnc.jnotepad.common.util;
import org.jcnc.jnotepad.model.enums.DialogType;
import org.jcnc.jnotepad.ui.dialog.AppDialogBuilder;
@ -110,6 +110,32 @@ public class PopUpUtil {
.build().showAndWait();
}
/**
* 设置疑问弹窗
*
* @param title 弹窗标题
* @param headerText 头文本
* @param message 消息文本
* @param leftBtnAction 左侧按钮点击事件
* @param rightBtnAction 右侧按钮点击事件
* @apiNote
* @since 2023/9/3 11:54
*/
public static void questionAlert(
String title, String headerText, String message,
DialogButtonAction leftBtnAction, DialogButtonAction rightBtnAction, String leftBtnText, String rightBtnText) {
getCustomDialog()
.setDialogType(DialogType.QUESTION)
.setTitle(title)
.setHeaderText(headerText)
.setCustomText(message)
.setLeftBtnAction(leftBtnAction)
.setRightBtnAction(rightBtnAction)
.setLeftBtnText(leftBtnText)
.setRightBtnText(rightBtnText)
.build().showAndWait();
}
public static void successAlert(
String title, String headerText, String message,
DialogButtonAction leftBtnAction, DialogButtonAction rightBtnAction) {

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.util;
package org.jcnc.jnotepad.common.util;
import atlantafx.base.theme.Styles;
import javafx.scene.image.Image;

View File

@ -1,10 +1,10 @@
package org.jcnc.jnotepad.controller;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.controller.config.PluginConfigController;
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
import org.jcnc.jnotepad.exception.AppException;
import org.jcnc.jnotepad.plugin.PluginLoader;
import org.jcnc.jnotepad.util.LogUtil;
import org.slf4j.Logger;
import java.io.IOException;

View File

@ -2,10 +2,10 @@ package org.jcnc.jnotepad.controller.cache;
import com.fasterxml.jackson.core.type.TypeReference;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
import org.jcnc.jnotepad.common.util.JsonUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
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;

View File

@ -1,10 +1,10 @@
package org.jcnc.jnotepad.controller.config;
import org.jcnc.jnotepad.common.util.JsonUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.PopUpUtil;
import org.jcnc.jnotepad.controller.interfaces.ConfigController;
import org.jcnc.jnotepad.exception.AppException;
import org.jcnc.jnotepad.util.JsonUtil;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.PopUpUtil;
import org.slf4j.Logger;
import java.io.BufferedWriter;

View File

@ -1,8 +1,8 @@
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.event.ActionEvent;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.util.LogUtil;
import java.io.File;

View File

@ -7,23 +7,22 @@ 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.common.util.EncodingDetector;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.UiUtil;
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;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import static org.jcnc.jnotepad.common.util.FileUtil.getFileText;
/**
* 打开文件的事件处理程序
* <p>
@ -68,7 +67,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
*
* @param file 文件对象
*/
public void openFile(File file) {
public static void openFile(File file) {
// 获取标签页集合
CenterTabPane jnotepadTabPane = CenterTabPane.getInstance();
// 遍历标签页查找匹配的标签页
@ -92,39 +91,30 @@ public class OpenFile implements EventHandler<ActionEvent> {
*
* @param file 文件对象
*/
public void getText(File file) {
public static void getText(File file) {
LineNumberTextArea textArea = createNewTextArea();
// 检测文件编码
Charset encoding = EncodingDetector.detectEncodingCharset(file);
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
String line;
while ((line = reader.readLine()) != null) {
if (!stringBuilder.isEmpty()) {
stringBuilder.append("\n");
}
stringBuilder.append(line);
}
String text = stringBuilder.toString();
LogUtil.getLogger(this.getClass()).info("已调用读取文件功能");
textArea.appendText(text);
String fileText = getFileText(file, encoding);
LogUtil.getLogger(OpenFile.class).info("已调用读取文件功能");
textArea.appendText(fileText);
CenterTab tab = createNewTab(file.getName(), textArea, encoding);
// 设置当前标签页关联本地文件
tab.setRelevance(true);
// 设置标签页关联文件
tab.setUserData(file);
// 设置关联文件最后的修改时间
tab.setLastModifiedTimeOfAssociatedFile(file.lastModified());
CenterTabPaneManager.getInstance().addNewTab(tab);
} catch (IOException ignored) {
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
}
}
/**
* 创建新的文本区域
*
* @return 新的文本区域
*/
private LineNumberTextArea createNewTextArea() {
private static LineNumberTextArea createNewTextArea() {
return new LineNumberTextArea();
}
@ -135,7 +125,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
* @param textArea 文本区域
* @return 新的标签页
*/
private CenterTab createNewTab(String tabName, LineNumberTextArea textArea, Charset charset) {
private static CenterTab createNewTab(String tabName, LineNumberTextArea textArea, Charset charset) {
return new CenterTab(tabName, textArea, charset);
}
}

View File

@ -7,10 +7,10 @@ import javafx.scene.input.KeyCode;
import javafx.stage.FileChooser;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.PopUpUtil;
import org.jcnc.jnotepad.common.util.UiUtil;
import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.PopUpUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;

View File

@ -1,7 +1,7 @@
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.event.ActionEvent;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
/**

View File

@ -6,13 +6,13 @@ 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.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.UiUtil;
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;
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
import org.jcnc.jnotepad.views.manager.TopMenuBarManager;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;

View File

@ -4,11 +4,11 @@ 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.Collections;
import java.util.List;
import java.util.Optional;
/**
* 控制器类实现 ControllerAble 接口用于管理文本编辑器的各种操作和事件处理
@ -40,14 +40,11 @@ public class Controller implements ControllerAble {
@Override
public void openAssociatedFileAndCreateTextArea(List<String> rawParameters) {
// 获取上次打开的页面
Cache cache = CACHE_MANAGER.getCache("tabs", "centerTabs");
List<String> fileTab;
if (cache == null) {
fileTab = Collections.emptyList();
} else {
fileTab = (List<String>) cache.getCacheData();
}
fileTab.forEach(filePath -> new OpenFile().openFile(new File(filePath)));
Optional<Object> cacheData = Optional.of(CACHE_MANAGER.getCacheData("tabs", "centerTabs"));
// 判空
List<String> fileTab = (List<String>) cacheData.orElse(Collections.emptyList());
// 打开上次打开的标签页
fileTab.forEach(filePath -> OpenFile.openFile(new File(filePath)));
if (!rawParameters.isEmpty()) {
String filePath = rawParameters.get(0);
@ -68,7 +65,7 @@ public class Controller implements ControllerAble {
public void openAssociatedFile(String filePath) {
File file = new File(filePath);
if (file.exists() && file.isFile()) {
new OpenFile().openFile(file);
OpenFile.openFile(file);
}
}
}

View File

@ -1,13 +1,13 @@
package org.jcnc.jnotepad.plugin;
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
import org.jcnc.jnotepad.common.util.JsonUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.controller.config.PluginConfigController;
import org.jcnc.jnotepad.exception.AppException;
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
import org.jcnc.jnotepad.plugin.interfaces.Plugin;
import org.jcnc.jnotepad.plugin.manager.PluginManager;
import org.jcnc.jnotepad.util.JsonUtil;
import org.jcnc.jnotepad.util.LogUtil;
import org.slf4j.Logger;
import java.io.*;

View File

@ -6,11 +6,11 @@ import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.PopUpUtil;
import org.jcnc.jnotepad.common.util.UiUtil;
import org.jcnc.jnotepad.plugin.manager.PluginManager;
import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.PopUpUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.slf4j.Logger;
import java.io.File;

View File

@ -1,12 +1,11 @@
package org.jcnc.jnotepad.plugin.manager;
import org.jcnc.jnotepad.app.manager.ApplicationManager;
import org.jcnc.jnotepad.app.util.ApplicationRestarter;
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.PopUpUtil;
import org.jcnc.jnotepad.controller.config.PluginConfigController;
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.PopUpUtil;
import org.slf4j.Logger;
import java.io.File;

View File

@ -5,9 +5,9 @@ import javafx.geometry.Pos;
import javafx.scene.image.Image;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.jcnc.jnotepad.common.util.UiUtil;
import org.jcnc.jnotepad.model.enums.DialogType;
import org.jcnc.jnotepad.ui.dialog.interfaces.DialogButtonAction;
import org.jcnc.jnotepad.util.UiUtil;
import org.kordamp.ikonli.javafx.FontIcon;
/**

View File

@ -8,9 +8,9 @@ import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.jcnc.jnotepad.app.util.ApplicationRestarter;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.PopUpUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.PopUpUtil;
import org.jcnc.jnotepad.common.util.UiUtil;
import org.slf4j.Logger;
/**

View File

@ -17,8 +17,8 @@ import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.UiUtil;
import org.jcnc.jnotepad.views.manager.RootManager;
import static org.jcnc.jnotepad.common.constants.AppConstants.*;

View File

@ -12,10 +12,10 @@ import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import org.jcnc.jnotepad.common.util.UiUtil;
import org.jcnc.jnotepad.plugin.PluginManagerInterface;
import org.jcnc.jnotepad.ui.module.CustomSetButton;
import org.jcnc.jnotepad.ui.module.SettingsComponent;
import org.jcnc.jnotepad.util.UiUtil;
import static org.jcnc.jnotepad.common.constants.AppConstants.SCREEN_LENGTH;
import static org.jcnc.jnotepad.common.constants.AppConstants.SCREEN_WIDTH;

View File

@ -25,13 +25,13 @@ import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.PopUpUtil;
import org.jcnc.jnotepad.common.util.UiUtil;
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
import org.jcnc.jnotepad.plugin.manager.PluginManager;
import org.jcnc.jnotepad.ui.module.CustomSetButton;
import org.jcnc.jnotepad.ui.setstage.AbstractPaneStage;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.PopUpUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.slf4j.Logger;
import java.awt.*;

View File

@ -2,9 +2,15 @@ package org.jcnc.jnotepad.views.manager;
import javafx.collections.ObservableList;
import javafx.scene.control.Tab;
import javafx.stage.Stage;
import org.jcnc.jnotepad.app.manager.ApplicationManager;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
import org.jcnc.jnotepad.common.util.FileUtil;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.PopUpUtil;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
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;
@ -48,15 +54,58 @@ public class CenterTabPaneManager {
private void initListeners() {
// tab选中行为监听器用于tab切换后更新与当前tab相关的组件
centerTabPane.getSelectionModel().selectedItemProperty().addListener(
(ov, from, to) -> {
if (to != null) {
(ov, preTab, currTab) -> {
if (currTab != null) {
// 更新菜单栏中与tab相关设置
TopMenuBar.getInstance().updateMenuStatusBySelectedTab();
// 判断当前标签页是否关联文件
CenterTab tab = (CenterTab) currTab;
// 检查文件标签页状态
checkFileTabStatus(tab);
}
// 更新状态标签
bottomStatusBoxManager.updateWhenTabSelected();
}
);
ApplicationManager.getInstance().getPrimaryStage().focusedProperty().addListener((observable, oldValue, newValue) -> {
if (Boolean.TRUE.equals(newValue)) {
checkFileTabStatus(getSelected());
}
});
}
/**
* 检查文件标签页状态
*
* @apiNote 该方法检查当前文件是否被修改如果被修改则返回true
*/
private void checkFileTabStatus(CenterTab tab) {
if (tab.isRelevance()) {
LogUtil.getLogger(this.getClass()).info("当前标签页关联文件");
// 获取当前文本域对象
LineNumberTextArea lineNumberTextArea = tab.getLineNumberTextArea();
// 获取当前标签页对应文件上次修改时间
Long lastModifiedTime = tab.getLastModifiedTimeOfAssociatedFile();
// 获取对应文件上次修改时间
File file = (File) tab.getUserData();
Long lastModifiedTimeOfFile = file.lastModified();
if (lastModifiedTimeOfFile.equals(lastModifiedTime)) {
return;
}
//fixme 这行代码不能直接放到绑定的方法中,猜测匿名内部类的延迟执行特性可能会导致在获取 FileUtil.getFileText(file) 的返回值时文件内容还没有被正确读取导致空串暂无解决办法
String fileText = FileUtil.getFileText(file);
// 当前文件已被外部修改
PopUpUtil.questionAlert(
"重新加载", file.getAbsolutePath(), "此文件已被外部修改,是否重新加载该文件?",
appDialog -> {
lineNumberTextArea.clear();
lineNumberTextArea.appendText(fileText);
appDialog.close();
}, Stage::close, "", "");
}
}
/**

View File

@ -9,14 +9,14 @@ import javafx.scene.control.*;
import javafx.scene.input.KeyCombination;
import javafx.stage.Stage;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.common.util.LogUtil;
import org.jcnc.jnotepad.common.util.UiUtil;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.controller.event.handler.menubar.*;
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
import org.jcnc.jnotepad.model.entity.ShortcutKey;
import org.jcnc.jnotepad.ui.setstage.HelpPaneStage;
import org.jcnc.jnotepad.ui.setstage.pluginstage.PluginManagementPane;
import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar;
import org.slf4j.Logger;

View File

@ -2,9 +2,9 @@ package org.jcnc.jnotepad.views.root.center.main.center.tab;
import javafx.scene.control.Tab;
import org.fxmisc.flowless.VirtualizedScrollPane;
import org.jcnc.jnotepad.common.util.LogUtil;
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;
@ -32,6 +32,10 @@ public class CenterTab extends Tab {
* 是否与本地文件关联
*/
private boolean isRelevance = false;
/**
* 关联文件上次修改时间
*/
private Long lastModifiedTimeOfAssociatedFile;
private Charset charset = Charset.defaultCharset();
public CenterTab(String tabTitle) {
@ -113,6 +117,8 @@ public class CenterTab extends Tab {
// 如果发生IO异常记录忽视的日志信息但不中断程序执行
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
}
// 更新最后修改时间
tab.setLastModifiedTimeOfAssociatedFile(file.lastModified());
}
/**
@ -138,4 +144,11 @@ public class CenterTab extends Tab {
saveSelectedFileTab();
}
public Long getLastModifiedTimeOfAssociatedFile() {
return lastModifiedTimeOfAssociatedFile;
}
public void setLastModifiedTimeOfAssociatedFile(Long lastModifiedTimeOfAssociatedFile) {
this.lastModifiedTimeOfAssociatedFile = lastModifiedTimeOfAssociatedFile;
}
}