JNotepad/src/main/java/org/jcnc/jnotepad/ui/LineNumberTextArea.java

152 lines
5.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package org.jcnc.jnotepad.ui;
import javafx.beans.property.StringProperty;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import org.jcnc.jnotepad.app.config.AppConfig;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author 许轲
*/
public class LineNumberTextArea extends BorderPane {
/**
* 是否与本地文件关联
*/
private boolean isRelevance = false;
private final TextArea mainTextArea;
private final TextArea lineNumberArea;
static final int[] SIZE_TABLE = {9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE};
private static final int MIN_LINE_NUMBER_WIDTH = 30;
public LineNumberTextArea() {
mainTextArea = new TextArea();
mainTextArea.setWrapText(AppConfigController.getInstance().getAutoLineConfig());
lineNumberArea = new TextArea();
lineNumberArea.setEditable(false);
lineNumberArea.setPrefWidth(MIN_LINE_NUMBER_WIDTH);
lineNumberArea.setMinWidth(MIN_LINE_NUMBER_WIDTH);
// 设定自定义样式
lineNumberArea.getStyleClass().add("text-line-number");
mainTextArea.getStyleClass().add("main-text-area");
this.setStyle(
"-fx-border-color:white;" +
"-fx-background-color:white"
);
initListeners();
setCenter(mainTextArea);
setLeft(lineNumberArea);
}
private void initListeners() {
// 当主要文本区域的垂直滚动位置发生变化时,使行号文本区域的滚动位置保持一致
mainTextArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> lineNumberArea.setScrollTop(mainTextArea.getScrollTop()));
// 当行号文本区域的垂直滚动位置发生变化时,使主要文本区域的滚动位置保持一致
lineNumberArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> mainTextArea.setScrollTop(lineNumberArea.getScrollTop()));
lineNumberArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberWidth());
this.mainTextArea.caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> JNotepadStatusBox.getInstance().updateWordCountStatusLabel());
this.textProperty().addListener((observable, oldValue, newValue) -> {
// 更新行号
updateLineNumberArea();
// 更新状态栏
JNotepadStatusBox.getInstance().updateWordCountStatusLabel();
// 自动保存
save();
});
}
/**
* 以原文件编码格式写回文件
*/
public void save() {
JNotepadTab tab = JNotepadTabPane.getInstance().getSelected();
if (tab != null) {
File file = (File) tab.getUserData();
String newValue = this.mainTextArea.getText();
if (file != null) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, tab.getCharset()))) {
writer.write(newValue);
LogUtil.getLogger(this.getClass()).info("正在自动保存---");
} catch (IOException ignored) {
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
}
}
}
}
public boolean isRelevance() {
return isRelevance;
}
public void setRelevance(boolean relevance) {
isRelevance = relevance;
}
private void updateLineNumberWidth() {
int numOfLines = mainTextArea.getParagraphs().size();
int count = 1;
for (int i = 0; i < SIZE_TABLE.length; i++) {
if (numOfLines <= SIZE_TABLE[i]) {
count = i + 1;
break;
}
}
// 单数字宽度10像素4为padding=左3+右1
int actualWidth = Math.max(count * 10 + 11, MIN_LINE_NUMBER_WIDTH);
if (actualWidth != lineNumberArea.getWidth()) {
lineNumberArea.setPrefWidth(actualWidth);
}
}
public StringProperty textProperty() {
return mainTextArea.textProperty();
}
private void updateLineNumberArea() {
// 保存当前的滚动位置
/*
更新行号文本区域的内容,根据主要文本区域的段落数生成行号。
*/
double mainTextAreaScrollTop = mainTextArea.getScrollTop();
double lineNumberAreaScrollTop = lineNumberArea.getScrollTop();
int numOfLines = mainTextArea.getParagraphs().size();
StringBuilder lineNumberText = new StringBuilder();
for (int i = 1; i <= numOfLines; i++) {
lineNumberText.append(i).append("\n");
}
lineNumberArea.setText(lineNumberText.toString());
// 恢复之前的滚动位置
mainTextArea.setScrollTop(mainTextAreaScrollTop);
lineNumberArea.setScrollTop(lineNumberAreaScrollTop);
}
public TextArea getMainTextArea() {
return mainTextArea;
}
}