增加行号文本框的注释

This commit is contained in:
许轲 2023-09-08 00:36:03 +08:00
parent 40e17cbe8c
commit 5b8dab62fa

View File

@ -24,117 +24,204 @@ import java.io.IOException;
*/ */
public class LineNumberTextArea extends BorderPane { public class LineNumberTextArea extends BorderPane {
static final int[] SIZE_TABLE = {9, 99, 999, 9999, 99999, 999999, 9999999, /**
* 用于确定行号区域宽度的大小表格每个元素表示不同的行数范围
*/
private static final int[] SIZE_TABLE = {9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE}; 99999999, 999999999, Integer.MAX_VALUE};
private static final Logger logger = LogUtil.getLogger(LineNumberTextArea.class);
private static final int MIN_LINE_NUMBER_WIDTH = 30;
private final TextArea mainTextArea;
private final TextArea lineNumberArea;
/**
* 用于记录日志的静态Logger对象
*/
private static final Logger logger = LogUtil.getLogger(LineNumberTextArea.class);
/**
* 行号区域的最小宽度
*/
private static final int MIN_LINE_NUMBER_WIDTH = 30;
/**
* 主文本区域的TextArea实例
*/
private final TextArea mainTextArea = new TextArea();
/**
* 行号区域的TextArea实例
*/
private final TextArea lineNumberArea = new TextArea();
/**
* 构造函数
* <p>
* 用于创建 LineNumberTextArea 对象
*/
public LineNumberTextArea() { public LineNumberTextArea() {
mainTextArea = new TextArea(); // 设置主文本区域是否自动换行根据应用配置决定
mainTextArea.setWrapText(SingletonUtil.getAppConfigController().getAutoLineConfig()); mainTextArea.setWrapText(SingletonUtil.getAppConfigController().getAutoLineConfig());
lineNumberArea = new TextArea();
// 设置行号区域不可编辑
lineNumberArea.setEditable(false); lineNumberArea.setEditable(false);
// 设置行号区域的首选宽度和最小宽度为最小行号宽度
lineNumberArea.setPrefWidth(MIN_LINE_NUMBER_WIDTH); lineNumberArea.setPrefWidth(MIN_LINE_NUMBER_WIDTH);
lineNumberArea.setMinWidth(MIN_LINE_NUMBER_WIDTH); lineNumberArea.setMinWidth(MIN_LINE_NUMBER_WIDTH);
// 设定自定义样式
// 为行号区域和主文本区域添加CSS样式类
lineNumberArea.getStyleClass().add("text-line-number"); lineNumberArea.getStyleClass().add("text-line-number");
mainTextArea.getStyleClass().add("main-text-area"); mainTextArea.getStyleClass().add("main-text-area");
// 设置 LineNumberTextArea 的样式包括边框和背景颜色
this.setStyle( this.setStyle(
"-fx-border-color:white;" + "-fx-border-color:white;" +
"-fx-background-color:white" "-fx-background-color:white"
); );
// 初始化监听器用于处理事件
initListeners(); initListeners();
// 将主文本区域设置为中央内容将行号区域设置为左侧内容
setCenter(mainTextArea); setCenter(mainTextArea);
setLeft(lineNumberArea); setLeft(lineNumberArea);
} }
/**
* 初始化监听器方法
*/
private void initListeners() { private void initListeners() {
// 当主要文本区域的垂直滚动位置发生变化时使行号文本区域的滚动位置保持一致 // 监听主要文本区域的滚动位置变化
mainTextArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> lineNumberArea.setScrollTop(mainTextArea.getScrollTop())); mainTextArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> lineNumberArea.setScrollTop(mainTextArea.getScrollTop()));
// 监听行号文本区域的滚动位置变化
// 当行号文本区域的垂直滚动位置发生变化时使主要文本区域的滚动位置保持一致
lineNumberArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> mainTextArea.setScrollTop(lineNumberArea.getScrollTop())); lineNumberArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> mainTextArea.setScrollTop(lineNumberArea.getScrollTop()));
// 监听行号文本区域的文本变化
lineNumberArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberWidth()); lineNumberArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberWidth());
// 监听主要文本区域的光标位置变化
this.mainTextArea.caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> BottomStatusBox.getInstance().updateWordCountStatusLabel()); this.mainTextArea.caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> BottomStatusBox.getInstance().updateWordCountStatusLabel());
// 监听主要文本区域的文本变化
this.textProperty().addListener((observable, oldValue, newValue) -> { this.textProperty().addListener((observable, oldValue, newValue) -> {
// 更新行号
updateLineNumberArea(); updateLineNumberArea();
// 更新状态栏
BottomStatusBox.getInstance().updateWordCountStatusLabel(); BottomStatusBox.getInstance().updateWordCountStatusLabel();
// 自动保存
save(); save();
}); });
} }
/** /**
* 以原文件编码格式写回文件 * 保存方法
*/ */
public void save() { public void save() {
// 获取当前选定的中央标签页CenterTab对象
CenterTab tab = CenterTabPane.getInstance().getSelected(); CenterTab tab = CenterTabPane.getInstance().getSelected();
// 如果没有选定标签页返回不执行保存操作
if (tab == null) { if (tab == null) {
return; return;
} }
// 从标签页的用户数据中获取文件对象
File file = (File) tab.getUserData(); File file = (File) tab.getUserData();
// 获取主文本区域中的文本内容
String newValue = this.mainTextArea.getText(); String newValue = this.mainTextArea.getText();
// 如果文件对象为空记录警告信息并返回不执行保存操作
if (file == null) { if (file == null) {
// 文件对象不存在
logger.warn("Tab上没有关联文件信息"); logger.warn("Tab上没有关联文件信息");
return; return;
} }
// 尝试使用BufferedWriter写入文件内容
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, tab.getCharset()))) { try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, tab.getCharset()))) {
// 将新的文本内容写入文件
writer.write(newValue); writer.write(newValue);
// 记录保存操作的日志信息
LogUtil.getLogger(this.getClass()).info("正在自动保存---"); LogUtil.getLogger(this.getClass()).info("正在自动保存---");
} catch (IOException ignored) { } catch (IOException ignored) {
// 如果发生IO异常记录忽略的日志信息但不中断程序执行
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!"); LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
} }
} }
/**
* 更新行号宽度方法
*/
private void updateLineNumberWidth() { private void updateLineNumberWidth() {
// 获取主文本区域的段落数量即文本的行数
int numOfLines = mainTextArea.getParagraphs().size(); int numOfLines = mainTextArea.getParagraphs().size();
// 初始化一个计数器用于确定适合的行号宽度
int count = 1; int count = 1;
// 遍历行号宽度大小的表格
for (int i = 0; i < SIZE_TABLE.length; i++) { for (int i = 0; i < SIZE_TABLE.length; i++) {
// 检查文本行数是否在当前表格项的范围内
if (numOfLines <= SIZE_TABLE[i]) { if (numOfLines <= SIZE_TABLE[i]) {
// 如果是设置计数器为当前索引+1并退出循环
count = i + 1; count = i + 1;
break; break;
} }
} }
// 单数字宽度10像素4为padding=左3+右1
// 计算实际的行号区域宽度确保不小于一个最小宽度值
int actualWidth = Math.max(count * 10 + 11, MIN_LINE_NUMBER_WIDTH); int actualWidth = Math.max(count * 10 + 11, MIN_LINE_NUMBER_WIDTH);
// 检查实际宽度是否与当前行号区域的宽度不同
if (actualWidth != lineNumberArea.getWidth()) { if (actualWidth != lineNumberArea.getWidth()) {
// 如果不同设置行号区域的首选宽度为实际宽度
lineNumberArea.setPrefWidth(actualWidth); lineNumberArea.setPrefWidth(actualWidth);
} }
} }
/**
* 获取主要文本区域的text属性
*
* @return 主要文本区域的text属性
*/
public StringProperty textProperty() { public StringProperty textProperty() {
return mainTextArea.textProperty(); return mainTextArea.textProperty();
} }
/**
* 更新行号区域方法
*/
private void updateLineNumberArea() { private void updateLineNumberArea() {
// 保存当前的滚动位置 // 获取主文本区域的垂直滚动位置
/*
更新行号文本区域的内容根据主要文本区域的段落数生成行号
*/
double mainTextAreaScrollTop = mainTextArea.getScrollTop(); double mainTextAreaScrollTop = mainTextArea.getScrollTop();
// 获取行号区域的垂直滚动位置
double lineNumberAreaScrollTop = lineNumberArea.getScrollTop(); double lineNumberAreaScrollTop = lineNumberArea.getScrollTop();
// 获取主文本区域的段落数量即文本的行数
int numOfLines = mainTextArea.getParagraphs().size(); int numOfLines = mainTextArea.getParagraphs().size();
// 用于构建行号文本的字符串构建器
StringBuilder lineNumberText = new StringBuilder(); StringBuilder lineNumberText = new StringBuilder();
// 循环迭代生成行号文本,
for (int i = 1; i <= numOfLines; i++) { for (int i = 1; i <= numOfLines; i++) {
// 将行号和换行符添加到字符串中
lineNumberText.append(i).append("\n"); lineNumberText.append(i).append("\n");
} }
// 将生成的行号文本设置到行号区域
lineNumberArea.setText(lineNumberText.toString()); lineNumberArea.setText(lineNumberText.toString());
// 恢复之前的滚动位置 // 恢复主文本区域的垂直滚动位置
mainTextArea.setScrollTop(mainTextAreaScrollTop); mainTextArea.setScrollTop(mainTextAreaScrollTop);
// 恢复行号区域的垂直滚动位置
lineNumberArea.setScrollTop(lineNumberAreaScrollTop); lineNumberArea.setScrollTop(lineNumberAreaScrollTop);
} }
/**
* 获取主要文本区域
*
* @return 主要文本区域
*/
public TextArea getMainTextArea() { public TextArea getMainTextArea() {
return mainTextArea; return mainTextArea;
} }
} }