!23 添加保存按钮,优化项目代码逻辑

Merge pull request !23 from 格物方能致知/master
This commit is contained in:
Luke 2023-08-23 09:59:15 +00:00 committed by Gitee
commit ee78f2bc60
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
17 changed files with 162 additions and 166 deletions

View File

@ -70,7 +70,7 @@ public interface ControllerInterface {
*
* @param file 文件
*/
void getText(File file);
LineNumberTextArea getText(File file);
/**
* 更新编码标签

View File

@ -61,26 +61,22 @@ public class LunchApp extends Application {
primaryStage.setWidth(width);
primaryStage.setHeight(length);
primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResource(icon)).toString()));
primaryStage.show();
ViewManager viewManager = ViewManager.getInstance(scene);
viewManager.initScreen(scene);
// 初始化菜单项和标签栏
view.initTabPane();
view.initShortcutKey();
if (controller.isRelevance()) {
// 使用线程池加载关联文件并创建文本区域
List<String> rawParameters = getParameters().getRaw();
THREAD_POOL.execute(() -> {
LineNumberTextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters);
if (!Objects.isNull(textArea)) {
Platform.runLater(() -> controller.updateUiWithNewTextArea(textArea));
}
});
}
// 使用线程池加载关联文件并创建文本区域
List<String> rawParameters = getParameters().getRaw();
THREAD_POOL.execute(() -> {
LineNumberTextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters);
if (!Objects.isNull(textArea)) {
Platform.runLater(() -> controller.updateUiWithNewTextArea(textArea));
}
});
}
@Override

View File

@ -1,6 +1,5 @@
package org.jcnc.jnotepad.app.config;
import org.jcnc.jnotepad.Interface.ConfigInterface;
import org.jcnc.jnotepad.init.Config;
import java.util.Properties;
@ -17,13 +16,10 @@ public class GlobalConfig {
*/
public static final String TEXT_WRAP = "text.wrap";
private static final GlobalConfig APP_GLOBAL_CONFIG = new GlobalConfig();
private ConfigInterface configLoader;
private Properties properties;
private final Properties properties;
private GlobalConfig() {
this.configLoader = new Config();
properties = this.configLoader.readPropertiesFromFile();
properties = new Config().readPropertiesFromFile();
}
/**
@ -32,12 +28,12 @@ public class GlobalConfig {
* @return true, 自动换行false不自动换行
*/
public boolean getAutoLineConfig() {
return Boolean.parseBoolean(this.properties.getProperty(TEXT_WRAP, "true"));
return Boolean.parseBoolean(properties.getProperty(TEXT_WRAP, "true"));
}
public void setAutoLineConfig(boolean isAutoLine) {
String autoLineConfig = String.valueOf(isAutoLine);
this.properties.setProperty(TEXT_WRAP, autoLineConfig);
properties.setProperty(TEXT_WRAP, autoLineConfig);
}
public static GlobalConfig getConfig() {

View File

@ -2,28 +2,23 @@ package org.jcnc.jnotepad.controller.event.handler;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import org.jcnc.jnotepad.app.config.GlobalConfig;
/**
* 换行事件处理针对当前选中tab进行格式化
* 配置变更时
* 1. 更新内存全局配置, see {@linkplain org.jcnc.jnotepad.app.config.GlobalConfig}
* 2. 对当前tab生效配置每次tab切换根据全局配置设置进行变更
* 换行事件处理针对当前选中tab进行格式化<br/>
* 配置变更时<br/>
* 1. 更新内存全局配置<br/>
* 2. 对当前tab生效配置每次tab切换根据全局配置设置进行变更<br/>
* <p>
* 用于在文本区域中插入一个换行符
* @see GlobalConfig
*
* @Deprecated 事件处理使用item的listener实现
* @deprecated 事件处理将使用item的listener实现
*
* @author 许轲
*/
@Deprecated
public class LineFeed implements EventHandler<ActionEvent> {
/**
* 构造函数初始化 LineFeed 对象
*/
public LineFeed() {
}
/**
* 处理事件的方法将一个换行符插入到文本区域的末尾
*

View File

@ -2,7 +2,6 @@ package org.jcnc.jnotepad.controller.event.handler;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Tab;
import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTab;

View File

@ -2,16 +2,8 @@ package org.jcnc.jnotepad.controller.event.handler;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Tab;
import javafx.stage.FileChooser;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import static org.jcnc.jnotepad.tool.FileUtil.saveTab;
/**
@ -32,26 +24,6 @@ public class SaveAsFile implements EventHandler<ActionEvent> {
*/
@Override
public void handle(ActionEvent event) {
Tab selectedTab = JNotepadTabPane.getInstance().getSelected();
if (selectedTab != null) {
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialFileName(selectedTab.getText());
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt"));
File file = fileChooser.showSaveDialog(null);
if (file != null) {
try (
BufferedWriter writer = new BufferedWriter(new FileWriter(file))
) {
LineNumberTextArea textArea = (LineNumberTextArea) selectedTab.getContent(); // 获取当前Tab页的文本编辑区
String text = textArea.getMainTextArea().getText();
writer.write(text); // 写入文件内容
writer.flush();
selectedTab.setText(file.getName()); // 更新Tab页标签上的文件名
selectedTab.setUserData(file); // 将文件对象保存到Tab页的UserData中
} catch (IOException ignored) {
LogUtil.info("已忽视IO异常!",this.getClass());
}
}
}
saveTab(this.getClass());
}
}

View File

@ -0,0 +1,49 @@
package org.jcnc.jnotepad.controller.event.handler;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Tab;
import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import org.slf4j.Logger;
import static org.jcnc.jnotepad.tool.FileUtil.saveTab;
/**
* 保存文件
*
* @author gewuyou
*/
public class SaveFile implements EventHandler<ActionEvent> {
Logger logger = LogUtil.getLogger(this.getClass());
/**
* 保存文件
*
* @param actionEvent 事件对象
* @apiNote
*/
@Override
public void handle(ActionEvent actionEvent) {
// 获取当前tab页
Tab selectedTab = JNotepadTabPane.getInstance().getSelected();
if (selectedTab == null) {
return;
}
// 获取当前Tab页的文本编辑区
LineNumberTextArea textArea = (LineNumberTextArea) selectedTab.getContent();
// 打开的是非关联文件则调用另存为api
if (!textArea.isRelevance()) {
logger.info("当前保存文件为非关联打开文件,调用另存为方法");
saveTab(this.getClass());
} else {
logger.info("当前保存文件为关联打开文件,调用自动保存方法");
// 打开的是关联文件
Controller controller = Controller.getInstance();
// 自动保存
controller.autoSave(textArea);
}
}
}

View File

@ -6,7 +6,6 @@ import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Tab;
import org.jcnc.jnotepad.Interface.ControllerInterface;
import org.jcnc.jnotepad.controller.event.handler.LineFeed;
import org.jcnc.jnotepad.controller.event.handler.NewFile;
import org.jcnc.jnotepad.controller.event.handler.OpenFile;
import org.jcnc.jnotepad.controller.event.handler.SaveAsFile;
@ -29,14 +28,6 @@ import java.util.List;
*/
public class Controller implements ControllerInterface {
private static final Controller INSTANCE = new Controller();
/**
* 是否关联
*/
private boolean isRelevance = true;
public boolean isRelevance() {
return isRelevance;
}
private Controller() {
}
@ -59,6 +50,8 @@ public class Controller implements ControllerInterface {
return null;
} else {
LineNumberTextArea textArea = createNewTextArea();
// 设置当前标签页与本地文件无关联
textArea.setRelevance(false);
configureTextArea(textArea);
return textArea;
}
@ -99,9 +92,9 @@ public class Controller implements ControllerInterface {
if (file != null) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(newValue);
LogUtil.info("正在自动保存---",this.getClass());
LogUtil.getLogger(this.getClass()).info("正在自动保存---");
} catch (IOException ignored) {
LogUtil.info("已忽视IO异常!",this.getClass());
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
}
}
}
@ -141,7 +134,6 @@ public class Controller implements ControllerInterface {
public void openAssociatedFile(String filePath) {
File file = new File(filePath);
if (file.exists() && file.isFile()) {
isRelevance = false;
openFile(file);
}
}
@ -152,8 +144,10 @@ public class Controller implements ControllerInterface {
* @param file 文件对象
*/
@Override
public void getText(File file) {
public LineNumberTextArea getText(File file) {
LineNumberTextArea textArea = createNewTextArea();
// 设置当前标签页关联本地文件
textArea.setRelevance(true);
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
StringBuilder textBuilder = new StringBuilder();
String line;
@ -164,17 +158,17 @@ public class Controller implements ControllerInterface {
Platform.runLater(() -> {
textArea.getMainTextArea().setText(text);
JNotepadTab tab = createNewTab(file.getName(), textArea);
tab.setUserData(file);
JNotepadTabPane.getInstance().addNewTab(tab);
updateStatusLabel(textArea);
autoSave(textArea);
});
} catch (IOException ignored) {
LogUtil.info("已忽视IO异常!",this.getClass());
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
}
return textArea;
}
/**
@ -225,7 +219,6 @@ public class Controller implements ControllerInterface {
*/
@Override
public void initTabPane() {
Controller controller = new Controller();
JNotepadTabPane.getInstance().getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> {
LineNumberTextArea textArea;
if (newTab != null) {
@ -236,13 +229,13 @@ public class Controller implements ControllerInterface {
textArea = openAssociatedFileAndCreateTextArea(new ArrayList<>());
}
// 更新状态标签
controller.updateStatusLabel(textArea);
INSTANCE.updateStatusLabel(textArea);
// 监听文本光标位置的变化更新状态标签
textArea.getMainTextArea().caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> controller.updateStatusLabel(textArea));
textArea.getMainTextArea().caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> INSTANCE.updateStatusLabel(textArea));
// 更新编码标签
controller.upDateEncodingLabel(textArea.getMainTextArea().getText());
INSTANCE.upDateEncodingLabel(textArea.getMainTextArea().getText());
});
}
@ -309,12 +302,10 @@ public class Controller implements ControllerInterface {
* @return 打开文件的任务
*/
private Task<Void> createOpenFileTask(File file) {
LineNumberTextArea textArea = createNewTextArea();
return new Task<>() {
@Override
protected Void call() {
getText(file);
upDateEncodingLabel(textArea.getMainTextArea().getText());
upDateEncodingLabel(getText(file).getMainTextArea().getText());
return null;
}
};

View File

@ -34,7 +34,7 @@ public class ShortcutKey implements ShortcutKeyInterface {
jsonData.append(line);
}
} catch (IOException e) {
LogUtil.error("读取配置失败!",e,this.getClass());
LogUtil.getLogger(this.getClass()).error("读取配置失败!", e);
}
} else {
// todo new InputStreamReader(inputStream) 实参 'inputStream' 可能为null
@ -44,7 +44,7 @@ public class ShortcutKey implements ShortcutKeyInterface {
jsonData.append(line);
}
} catch (IOException e) {
LogUtil.error("读取配置失败!",e,this.getClass());
LogUtil.getLogger(this.getClass()).error("读取配置失败!", e);
}
}

View File

@ -37,7 +37,7 @@ public class EncodingDetector {
// 尝试常见的编码
for (Charset charset : commonCharsets()) {
if (isValidEncoding(text, charset)) {
Platform.runLater(()-> LogUtil.info("编码监测结果:" + isValidEncoding(text, charset),EncodingDetector.class));
Platform.runLater(() -> LogUtil.getLogger(EncodingDetector.class).info("编码监测结果:{}", isValidEncoding(text, charset)));
return charset.name();
}
}

View File

@ -1,5 +1,10 @@
package org.jcnc.jnotepad.tool;
import javafx.scene.control.Tab;
import javafx.stage.FileChooser;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import java.io.*;
import java.nio.charset.StandardCharsets;
@ -30,9 +35,49 @@ public class FileUtil {
jsonStr = sb.toString();
return jsonStr;
} catch (IOException e) {
LogUtil.error("读取配置失败!",e,FileUtil.class);
LogUtil.getLogger(FileUtil.class).error("读取配置失败!", e);
return null;
}
}
/**
* 保存页面方法
*
* @param currentClass 调用该方法的类
* @apiNote 将当前选中的标签页进行弹出窗口式的保存
* @see LogUtil
*/
public static void saveTab(Class<?> currentClass) {
Tab selectedTab = JNotepadTabPane.getInstance().getSelected();
if (selectedTab != null) {
// 创建一个文件窗口
FileChooser fileChooser = new FileChooser();
// 设置保存文件名称
fileChooser.setInitialFileName(selectedTab.getText());
// 设置保存文件类型
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt"));
File file = fileChooser.showSaveDialog(null);
if (file != null) {
try (
BufferedWriter writer = new BufferedWriter(new FileWriter(file))
) {
// 获取当前Tab页的文本编辑区
LineNumberTextArea textArea = (LineNumberTextArea) selectedTab.getContent();
// 将保存后的文件设置为已关联
textArea.setRelevance(true);
String text = textArea.getMainTextArea().getText();
// 写入文件内容
writer.write(text);
writer.flush();
// 更新Tab页标签上的文件名
selectedTab.setText(file.getName());
// 将文件对象保存到Tab页的UserData中
selectedTab.setUserData(file);
} catch (IOException ignored) {
LogUtil.getLogger(currentClass).info("已忽视IO异常!");
}
}
}
}
}

View File

@ -18,68 +18,9 @@ public class LogUtil {
*
* @param currentClass 所要记录的类
* @return org.apache.logging.log4j.Logger 日志对象
* @apiNote 传入当前需要记录的类返回记录该类的日志类也可直接使用工具类定义好的方法也可调用这个方法自定义
* @see LogUtil
* @apiNote 传入当前需要记录的类返回记录该类的日志类 <br>建议一个类调用超过两次这个方法时应当将该日志类变成成员对象而不是多次调用
*/
public static Logger getLogger(Class<?> currentClass) {
return LoggerFactory.getLogger(currentClass);
}
/**
* 日志信息打印
*
* @param message 日志信息
* @param currentClass 所要记录的类
* @apiNote 传入当前需要记录的类方便知晓是哪个位置记录的日志
*/
public static void info(String message, Class<?> currentClass) {
getLogger(currentClass).info(message);
}
/**
* 日志排错信息打印
*
* @param message 日志信息
* @param currentClass 所要记录的类
* @apiNote 传入当前需要记录的类方便知晓是哪个位置记录的日志
*/
public static void debug(String message, Class<?> currentClass) {
getLogger(currentClass).debug(message);
}
/**
* 日志警告信息打印
*
* @param message 日志信息
* @param currentClass 所要记录的类
* @apiNote 传入当前需要记录的类方便知晓是哪个位置记录的日志
*/
public static void warn(String message, Class<?> currentClass) {
getLogger(currentClass).warn(message);
}
/**
* 日志错误信息打印
*
* @param message 日志信息
* @param currentClass 所要记录的类
* @apiNote 传入当前需要记录的类方便知晓是哪个位置记录的日志
*/
public static void error(String message, Class<?> currentClass) {
getLogger(currentClass).error(message);
}
/**
* 日志错误信息打印
*
* @param message 日志信息
* @param throwable 抛出的异常
* @param currentClass 所要记录的类
* @apiNote 这个方法用来弥补当抛出异常或手动抛出异常时无法捕捉到所抛异常
*/
public static void error(String message, Throwable throwable, Class<?> currentClass) {
getLogger(currentClass).error(message, throwable);
}
}

View File

@ -8,6 +8,10 @@ import javafx.scene.layout.BorderPane;
* @author 许轲
*/
public class LineNumberTextArea extends BorderPane {
/**
* 是否与本地文件关联
*/
private boolean isRelevance = false;
private final TextArea mainTextArea;
private final TextArea lineNumberArea;
@ -36,6 +40,14 @@ public class LineNumberTextArea extends BorderPane {
setLeft(lineNumberArea);
}
public boolean isRelevance() {
return isRelevance;
}
public void setRelevance(boolean relevance) {
isRelevance = relevance;
}
private void updateLineNumberWidth() {
int numOfLines = mainTextArea.getParagraphs().size();
int count = 1;

View File

@ -5,10 +5,7 @@ import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import org.jcnc.jnotepad.app.config.GlobalConfig;
import org.jcnc.jnotepad.controller.event.handler.LineFeed;
import org.jcnc.jnotepad.controller.event.handler.NewFile;
import org.jcnc.jnotepad.controller.event.handler.OpenFile;
import org.jcnc.jnotepad.controller.event.handler.SaveAsFile;
import org.jcnc.jnotepad.controller.event.handler.*;
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
@ -52,9 +49,13 @@ public class JNotepadMenuBar extends MenuBar {
*/
private MenuItem openItem;
/**
* 保存
* 另存为
*/
private MenuItem saveAsItem;
/**
* 保存
*/
private MenuItem saveItem;
/**
* 增加
*/
@ -97,10 +98,13 @@ public class JNotepadMenuBar extends MenuBar {
openItem = new MenuItem("打开");
itemMap.put("openItem", openItem);
saveItem = new MenuItem("保存");
itemMap.put("saveItem", saveItem);
saveAsItem = new MenuItem("另存为");
itemMap.put("saveAsItem", saveAsItem);
fileMenu.getItems().addAll(newItem, openItem, saveAsItem);
fileMenu.getItems().addAll(newItem, openItem, saveItem, saveAsItem);
}
/**
@ -142,6 +146,7 @@ public class JNotepadMenuBar extends MenuBar {
private void initEventHandlers() {
newItem.setOnAction(new NewFile());
openItem.setOnAction(new OpenFile());
saveItem.setOnAction(new SaveFile());
saveAsItem.setOnAction(new SaveAsFile());
lineFeedItem.setOnAction(new LineFeed());
lineFeedItem.selectedProperty().addListener((observableValue, before, after) -> {

View File

@ -1,14 +1,7 @@
package org.jcnc.jnotepad.view.init;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.controller.manager.ShortcutKey;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.view.manager.ViewManager;
import java.util.HashMap;
import java.util.Map;
/**

View File

@ -1,8 +1,8 @@
{
"newItem": "ctrl+n",
"openItem": "ctrl+o",
"saveItem": "ctrl+s",
"saveAsItem": "ctrl+shift+s",
"lineFeedItem": "",
"addItem": "",

View File

@ -10,9 +10,11 @@
<property name="log.maxHistory" value="30"/>
<!-- 日志存储路径 -->
<property name="log.filePath" value="logs"/>
<!--打包时,请使用下方的路径-->
<!--<property name="log.filePath" value="../logs"/>-->
<!-- 日志的显式格式 -->
<property name="log.pattern"
value="时间:[%d{yyyy-MM-dd HH:mm:ss.SSS}] 线程:[%thread] 日志级别:[%-5level] 调用位置:[%logger{50} [%L]] - 日志信息:[%msg]%n">
value="时间:[%d{yyyy-MM-dd HH:mm:ss.SSS}] 线程:[%thread] 日志级别:[%-5level] 调用位置:[%logger{50} 参见:[\(%F:%L\)]] - 日志信息:[%msg]%n">
</property>
<!-- 用于说明输出介质,此处说明控制台输出 -->
<appender name="consoleAppender"