feat: 实现侦测文件内容编码,并使用侦测成功的编码打开
This commit is contained in:
parent
58cd858643
commit
2410f6e213
1
.gitignore
vendored
1
.gitignore
vendored
@ -37,3 +37,4 @@ build/
|
|||||||
/src/main/JNotepad.java
|
/src/main/JNotepad.java
|
||||||
/.idea/
|
/.idea/
|
||||||
/project.txt
|
/project.txt
|
||||||
|
logs/
|
||||||
|
|||||||
5
pom.xml
5
pom.xml
@ -55,6 +55,11 @@
|
|||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
<version>1.4.11</version>
|
<version>1.4.11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ibm.icu</groupId>
|
||||||
|
<artifactId>icu4j</artifactId>
|
||||||
|
<version>68.1</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@ -9,6 +9,8 @@ module org.jcnc.jnotepad {
|
|||||||
requires org.slf4j;
|
requires org.slf4j;
|
||||||
requires ch.qos.logback.core;
|
requires ch.qos.logback.core;
|
||||||
requires ch.qos.logback.classic;
|
requires ch.qos.logback.classic;
|
||||||
|
requires com.ibm.icu;
|
||||||
|
|
||||||
exports org.jcnc.jnotepad;
|
exports org.jcnc.jnotepad;
|
||||||
exports org.jcnc.jnotepad.tool;
|
exports org.jcnc.jnotepad.tool;
|
||||||
exports org.jcnc.jnotepad.Interface;
|
exports org.jcnc.jnotepad.Interface;
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
package org.jcnc.jnotepad.Interface;
|
package org.jcnc.jnotepad.Interface;
|
||||||
|
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.event.EventHandler;
|
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -21,43 +19,6 @@ public interface ControllerInterface {
|
|||||||
*/
|
*/
|
||||||
LineNumberTextArea openAssociatedFileAndCreateTextArea(List<String> rawParameters);
|
LineNumberTextArea openAssociatedFileAndCreateTextArea(List<String> rawParameters);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取新建文件处理事件处理程序
|
|
||||||
*
|
|
||||||
* @param textArea 文本区域
|
|
||||||
* @return 新建文件处理事件处理程序
|
|
||||||
*/
|
|
||||||
EventHandler<ActionEvent> getNewFileEventHandler(LineNumberTextArea textArea);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取打开文件处理事件处理程序
|
|
||||||
*
|
|
||||||
* @return 打开文件处理事件处理程序
|
|
||||||
*/
|
|
||||||
EventHandler<ActionEvent> getOpenFileEventHandler();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取另存为文件处理事件处理程序
|
|
||||||
*
|
|
||||||
* @return 另存为文件处理事件处理程序
|
|
||||||
*/
|
|
||||||
EventHandler<ActionEvent> getSaveAsFileEventHandler();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自动保存
|
|
||||||
*
|
|
||||||
* @param textArea 文本区域
|
|
||||||
*/
|
|
||||||
void autoSave(LineNumberTextArea textArea);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新状态标签
|
|
||||||
*
|
|
||||||
* @param textArea 文本区域
|
|
||||||
*/
|
|
||||||
void updateStatusLabel(LineNumberTextArea textArea);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开关联文件
|
* 打开关联文件
|
||||||
*
|
*
|
||||||
@ -72,36 +33,6 @@ public interface ControllerInterface {
|
|||||||
*/
|
*/
|
||||||
LineNumberTextArea getText(File file);
|
LineNumberTextArea getText(File file);
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新编码标签
|
|
||||||
*
|
|
||||||
* @param text 编码标签文本
|
|
||||||
*/
|
|
||||||
void upDateEncodingLabel(String text);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取光标所在行号
|
|
||||||
*
|
|
||||||
* @param caretPosition 光标位置
|
|
||||||
* @param text 文本内容
|
|
||||||
* @return 行号
|
|
||||||
*/
|
|
||||||
int getRow(int caretPosition, String text);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取光标所在列号
|
|
||||||
*
|
|
||||||
* @param caretPosition 光标位置
|
|
||||||
* @param text 文本内容
|
|
||||||
* @return 列号
|
|
||||||
*/
|
|
||||||
int getColumn(int caretPosition, String text);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化 TabPane
|
|
||||||
*/
|
|
||||||
void initTabPane();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新UI和标签页
|
* 更新UI和标签页
|
||||||
*
|
*
|
||||||
|
|||||||
@ -65,8 +65,7 @@ public class LunchApp extends Application {
|
|||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
ViewManager viewManager = ViewManager.getInstance(scene);
|
ViewManager viewManager = ViewManager.getInstance(scene);
|
||||||
viewManager.initScreen(scene);
|
viewManager.initScreen(scene);
|
||||||
// 初始化菜单项和标签栏
|
// 初始化快捷键
|
||||||
view.initTabPane();
|
|
||||||
view.initShortcutKey();
|
view.initShortcutKey();
|
||||||
|
|
||||||
// 使用线程池加载关联文件并创建文本区域
|
// 使用线程池加载关联文件并创建文本区域
|
||||||
|
|||||||
@ -2,8 +2,8 @@ package org.jcnc.jnotepad.controller.event.handler;
|
|||||||
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import org.jcnc.jnotepad.controller.manager.Controller;
|
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
import org.jcnc.jnotepad.view.manager.ViewManager;
|
import org.jcnc.jnotepad.view.manager.ViewManager;
|
||||||
@ -24,29 +24,18 @@ public class NewFile implements EventHandler<ActionEvent> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void handle(ActionEvent event) {
|
public void handle(ActionEvent event) {
|
||||||
// 获取控制器
|
|
||||||
Controller controller = Controller.getInstance();
|
|
||||||
|
|
||||||
// 创建一个新的文本编辑区
|
// 创建一个新的文本编辑区
|
||||||
LineNumberTextArea textArea = new LineNumberTextArea();
|
LineNumberTextArea textArea = new LineNumberTextArea();
|
||||||
|
|
||||||
textArea.setStyle(
|
|
||||||
"-fx-border-color:white ;-fx-background-color:white;"
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: refactor:统一TextArea新建、绑定监听器入口
|
// TODO: refactor:统一TextArea新建、绑定监听器入口
|
||||||
// 增加autoSave监听器绑定
|
|
||||||
controller.autoSave(textArea);
|
|
||||||
ViewManager viewManager = ViewManager.getInstance();
|
ViewManager viewManager = ViewManager.getInstance();
|
||||||
// 将Tab页添加到TabPane中
|
// 将Tab页添加到TabPane中
|
||||||
JNotepadTabPane.getInstance().addNewTab(new JNotepadTab("新建文本 "
|
JNotepadTabPane.getInstance().addNewTab(new JNotepadTab("新建文本 "
|
||||||
+ viewManager.selfIncreaseAndGetTabIndex(),
|
+ viewManager.selfIncreaseAndGetTabIndex(),
|
||||||
textArea));
|
textArea));
|
||||||
|
|
||||||
// 更新状态标签
|
|
||||||
controller.updateStatusLabel(textArea);
|
|
||||||
|
|
||||||
// 更新编码信息
|
// 更新编码信息
|
||||||
controller.upDateEncodingLabel(textArea.getMainTextArea().getText());
|
JNotepadStatusBox.getInstance().updateEncodingLabel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5,8 +5,6 @@ import javafx.event.ActionEvent;
|
|||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import org.jcnc.jnotepad.controller.manager.Controller;
|
import org.jcnc.jnotepad.controller.manager.Controller;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@ -15,6 +13,7 @@ import java.io.File;
|
|||||||
* 打开文件的事件处理程序。
|
* 打开文件的事件处理程序。
|
||||||
* <p>
|
* <p>
|
||||||
* 当用户选择打开文件时,将创建一个新的文本编辑区,并在Tab页中显示。
|
* 当用户选择打开文件时,将创建一个新的文本编辑区,并在Tab页中显示。
|
||||||
|
*
|
||||||
* @author 许轲
|
* @author 许轲
|
||||||
*/
|
*/
|
||||||
public class OpenFile implements EventHandler<ActionEvent> {
|
public class OpenFile implements EventHandler<ActionEvent> {
|
||||||
@ -38,8 +37,6 @@ public class OpenFile implements EventHandler<ActionEvent> {
|
|||||||
protected Void call() {
|
protected Void call() {
|
||||||
// 调用控制器的getText方法,读取文件内容
|
// 调用控制器的getText方法,读取文件内容
|
||||||
controller.getText(file);
|
controller.getText(file);
|
||||||
// 更新编码标签
|
|
||||||
controller.upDateEncodingLabel(((LineNumberTextArea) JNotepadTabPane.getInstance().getSelected().getContent()).getMainTextArea().getText());
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,10 +2,9 @@ package org.jcnc.jnotepad.controller.event.handler;
|
|||||||
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
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.tool.LogUtil;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ public class SaveFile implements EventHandler<ActionEvent> {
|
|||||||
@Override
|
@Override
|
||||||
public void handle(ActionEvent actionEvent) {
|
public void handle(ActionEvent actionEvent) {
|
||||||
// 获取当前tab页
|
// 获取当前tab页
|
||||||
Tab selectedTab = JNotepadTabPane.getInstance().getSelected();
|
JNotepadTab selectedTab = JNotepadTabPane.getInstance().getSelected();
|
||||||
if (selectedTab == null) {
|
if (selectedTab == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -40,10 +39,8 @@ public class SaveFile implements EventHandler<ActionEvent> {
|
|||||||
saveTab(this.getClass());
|
saveTab(this.getClass());
|
||||||
} else {
|
} else {
|
||||||
logger.info("当前保存文件为关联打开文件,调用自动保存方法");
|
logger.info("当前保存文件为关联打开文件,调用自动保存方法");
|
||||||
// 打开的是关联文件
|
// 调用tab保存
|
||||||
Controller controller = Controller.getInstance();
|
selectedTab.save();
|
||||||
// 自动保存
|
|
||||||
controller.autoSave(textArea);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,13 +2,7 @@ package org.jcnc.jnotepad.controller.manager;
|
|||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.event.EventHandler;
|
|
||||||
import javafx.scene.control.Tab;
|
|
||||||
import org.jcnc.jnotepad.Interface.ControllerInterface;
|
import org.jcnc.jnotepad.Interface.ControllerInterface;
|
||||||
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.tool.EncodingDetector;
|
import org.jcnc.jnotepad.tool.EncodingDetector;
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
@ -16,8 +10,11 @@ import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
|||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
import org.jcnc.jnotepad.view.manager.ViewManager;
|
import org.jcnc.jnotepad.view.manager.ViewManager;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedReader;
|
||||||
import java.util.ArrayList;
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,74 +54,6 @@ public class Controller implements ControllerInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取新建文件事件处理程序。
|
|
||||||
*
|
|
||||||
* @param textArea 文本区域
|
|
||||||
* @return 新建文件事件处理程序
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public EventHandler<ActionEvent> getNewFileEventHandler(LineNumberTextArea textArea) {
|
|
||||||
return new NewFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取打开文件事件处理程序。
|
|
||||||
*
|
|
||||||
* @return 打开文件事件处理程序
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public EventHandler<ActionEvent> getOpenFileEventHandler() {
|
|
||||||
return new OpenFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自动保存文本内容。
|
|
||||||
*
|
|
||||||
* @param textArea 文本区域
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void autoSave(LineNumberTextArea textArea) {
|
|
||||||
textArea.getMainTextArea().textProperty().addListener((observable, oldValue, newValue) -> {
|
|
||||||
Tab tab = JNotepadTabPane.getInstance().getSelected();
|
|
||||||
if (tab != null) {
|
|
||||||
File file = (File) tab.getUserData();
|
|
||||||
if (file != null) {
|
|
||||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
|
|
||||||
writer.write(newValue);
|
|
||||||
LogUtil.getLogger(this.getClass()).info("正在自动保存---");
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取另存为文件事件处理程序。
|
|
||||||
*
|
|
||||||
* @return 另存为文件事件处理程序
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public EventHandler<ActionEvent> getSaveAsFileEventHandler() {
|
|
||||||
return new SaveAsFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新状态标签。
|
|
||||||
*
|
|
||||||
* @param textArea 文本区域
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void updateStatusLabel(LineNumberTextArea textArea) {
|
|
||||||
int caretPosition = textArea.getMainTextArea().getCaretPosition();
|
|
||||||
int row = getRow(caretPosition, textArea.getMainTextArea().getText());
|
|
||||||
int column = getColumn(caretPosition, textArea.getMainTextArea().getText());
|
|
||||||
int length = textArea.getMainTextArea().getLength();
|
|
||||||
ViewManager.getInstance().getStatusLabel().setText("行: " + row + " \t列: " + column + " \t字数: " + length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开关联文件。
|
* 打开关联文件。
|
||||||
*
|
*
|
||||||
@ -148,7 +77,9 @@ public class Controller implements ControllerInterface {
|
|||||||
LineNumberTextArea textArea = createNewTextArea();
|
LineNumberTextArea textArea = createNewTextArea();
|
||||||
// 设置当前标签页关联本地文件
|
// 设置当前标签页关联本地文件
|
||||||
textArea.setRelevance(true);
|
textArea.setRelevance(true);
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
// 检测文件编码
|
||||||
|
Charset encoding = EncodingDetector.detectEncodingCharset(file);
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
|
||||||
StringBuilder textBuilder = new StringBuilder();
|
StringBuilder textBuilder = new StringBuilder();
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
@ -158,11 +89,9 @@ public class Controller implements ControllerInterface {
|
|||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
textArea.getMainTextArea().setText(text);
|
textArea.getMainTextArea().setText(text);
|
||||||
JNotepadTab tab = createNewTab(file.getName(), textArea);
|
JNotepadTab tab = createNewTab(file.getName(), textArea, encoding);
|
||||||
tab.setUserData(file);
|
tab.setUserData(file);
|
||||||
JNotepadTabPane.getInstance().addNewTab(tab);
|
JNotepadTabPane.getInstance().addNewTab(tab);
|
||||||
updateStatusLabel(textArea);
|
|
||||||
autoSave(textArea);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
@ -171,74 +100,6 @@ public class Controller implements ControllerInterface {
|
|||||||
return textArea;
|
return textArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新编码标签。
|
|
||||||
*
|
|
||||||
* @param text 文本内容
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void upDateEncodingLabel(String text) {
|
|
||||||
String encoding = EncodingDetector.detectEncoding(text);
|
|
||||||
ViewManager.getInstance().getEnCodingLabel().setText("\t编码: " + encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取光标所在行号。
|
|
||||||
*
|
|
||||||
* @param caretPosition 光标位置
|
|
||||||
* @param text 文本内容
|
|
||||||
* @return 光标所在行号
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int getRow(int caretPosition, String text) {
|
|
||||||
caretPosition = Math.min(caretPosition, text.length());
|
|
||||||
String substring = text.substring(0, caretPosition);
|
|
||||||
int count = 0;
|
|
||||||
for (char c : substring.toCharArray()) {
|
|
||||||
if (c == '\n') {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取光标所在列号。
|
|
||||||
*
|
|
||||||
* @param caretPosition 光标位置
|
|
||||||
* @param text 文本内容
|
|
||||||
* @return 光标所在列号
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int getColumn(int caretPosition, String text) {
|
|
||||||
return caretPosition - text.lastIndexOf("\n", caretPosition - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化标签面板。
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void initTabPane() {
|
|
||||||
JNotepadTabPane.getInstance().getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> {
|
|
||||||
LineNumberTextArea textArea;
|
|
||||||
if (newTab != null) {
|
|
||||||
// 获取新选定的标签页并关联的文本区域
|
|
||||||
textArea = (LineNumberTextArea) newTab.getContent();
|
|
||||||
} else {
|
|
||||||
// 刷新状态
|
|
||||||
textArea = openAssociatedFileAndCreateTextArea(new ArrayList<>());
|
|
||||||
}
|
|
||||||
// 更新状态标签
|
|
||||||
INSTANCE.updateStatusLabel(textArea);
|
|
||||||
|
|
||||||
// 监听文本光标位置的变化,更新状态标签
|
|
||||||
textArea.getMainTextArea().caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> INSTANCE.updateStatusLabel(textArea));
|
|
||||||
|
|
||||||
// 更新编码标签
|
|
||||||
INSTANCE.upDateEncodingLabel(textArea.getMainTextArea().getText());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新UI和标签页
|
* 更新UI和标签页
|
||||||
*
|
*
|
||||||
@ -251,7 +112,6 @@ public class Controller implements ControllerInterface {
|
|||||||
ViewManager viewManager = ViewManager.getInstance();
|
ViewManager viewManager = ViewManager.getInstance();
|
||||||
String tabTitle = "新建文件 " + viewManager.selfIncreaseAndGetTabIndex();
|
String tabTitle = "新建文件 " + viewManager.selfIncreaseAndGetTabIndex();
|
||||||
JNotepadTabPane.getInstance().addNewTab(new JNotepadTab(tabTitle, textArea));
|
JNotepadTabPane.getInstance().addNewTab(new JNotepadTab(tabTitle, textArea));
|
||||||
updateStatusLabel(textArea);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -262,12 +122,6 @@ public class Controller implements ControllerInterface {
|
|||||||
*/
|
*/
|
||||||
private void configureTextArea(LineNumberTextArea textArea) {
|
private void configureTextArea(LineNumberTextArea textArea) {
|
||||||
textArea.getMainTextArea().setWrapText(true);
|
textArea.getMainTextArea().setWrapText(true);
|
||||||
upDateEncodingLabel(textArea.getMainTextArea().getText());
|
|
||||||
updateStatusLabel(textArea);
|
|
||||||
|
|
||||||
textArea.textProperty().addListener((observable, oldValue, newValue) -> updateStatusLabel(textArea));
|
|
||||||
|
|
||||||
autoSave(textArea);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -276,12 +130,7 @@ public class Controller implements ControllerInterface {
|
|||||||
* @return 新的文本区域
|
* @return 新的文本区域
|
||||||
*/
|
*/
|
||||||
private LineNumberTextArea createNewTextArea() {
|
private LineNumberTextArea createNewTextArea() {
|
||||||
LineNumberTextArea textArea = new LineNumberTextArea();
|
return new LineNumberTextArea();
|
||||||
textArea.setStyle(
|
|
||||||
"-fx-border-color:white;" +
|
|
||||||
"-fx-background-color:white"
|
|
||||||
);
|
|
||||||
return textArea;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -291,8 +140,8 @@ public class Controller implements ControllerInterface {
|
|||||||
* @param textArea 文本区域
|
* @param textArea 文本区域
|
||||||
* @return 新的标签页
|
* @return 新的标签页
|
||||||
*/
|
*/
|
||||||
private JNotepadTab createNewTab(String tabName, LineNumberTextArea textArea) {
|
private JNotepadTab createNewTab(String tabName, LineNumberTextArea textArea, Charset charset) {
|
||||||
return new JNotepadTab(tabName, textArea);
|
return new JNotepadTab(tabName, textArea, charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -305,7 +154,7 @@ public class Controller implements ControllerInterface {
|
|||||||
return new Task<>() {
|
return new Task<>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void call() {
|
protected Void call() {
|
||||||
upDateEncodingLabel(getText(file).getMainTextArea().getText());
|
getText(file);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,11 +1,21 @@
|
|||||||
package org.jcnc.jnotepad.tool;
|
package org.jcnc.jnotepad.tool;
|
||||||
|
|
||||||
|
|
||||||
|
import com.ibm.icu.text.CharsetDetector;
|
||||||
|
import com.ibm.icu.text.CharsetMatch;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编码检测工具类
|
* 编码检测工具类
|
||||||
@ -13,67 +23,46 @@ import java.nio.charset.StandardCharsets;
|
|||||||
* @author 许轲
|
* @author 许轲
|
||||||
*/
|
*/
|
||||||
public class EncodingDetector {
|
public class EncodingDetector {
|
||||||
private EncodingDetector() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
private static final Logger LOG = LoggerFactory.getLogger(EncodingDetector.class);
|
||||||
* 检测 TextArea 中的文本编码
|
public static final String UNKNOWN = "UNKNOWN";
|
||||||
*
|
|
||||||
* @param textArea 文本区域
|
private EncodingDetector() {
|
||||||
* @return 字符串表示的编码,如果检测失败则返回 "UNKNOWN"
|
|
||||||
*/
|
|
||||||
public static String detectEncoding(LineNumberTextArea textArea) {
|
|
||||||
String text = textArea.getMainTextArea().getText();
|
|
||||||
return detectEncoding(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检测文本编码
|
* 检测文本编码
|
||||||
*
|
*
|
||||||
* @param text 要检测的文本
|
* @param file 要检测的文件
|
||||||
* @return 字符串表示的编码,如果检测失败则返回 "UNKNOWN"
|
* @return 字符串表示的编码,如果检测失败则返回 "UNKNOWN"
|
||||||
*/
|
*/
|
||||||
public static String detectEncoding(String text) {
|
public static String detectEncoding(File file) {
|
||||||
// 尝试常见的编码
|
CharsetDetector charsetDetector = new CharsetDetector();
|
||||||
for (Charset charset : commonCharsets()) {
|
try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file.getPath()))) {
|
||||||
if (isValidEncoding(text, charset)) {
|
charsetDetector.setText(inputStream);
|
||||||
Platform.runLater(() -> LogUtil.getLogger(EncodingDetector.class).info("编码监测结果:{}", isValidEncoding(text, charset)));
|
CharsetMatch match = charsetDetector.detect();
|
||||||
return charset.name();
|
LOG.debug(match.getName() + " " + match.getConfidence());
|
||||||
|
if (match.getConfidence() > 50) {
|
||||||
|
return match.getName();
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "UNKNOWN";
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取常见的字符集数组
|
* 检测文本编码
|
||||||
*
|
*
|
||||||
* @return 常见字符集数组
|
* @param file 文件
|
||||||
|
* @return Charset编码
|
||||||
*/
|
*/
|
||||||
private static Charset[] commonCharsets() {
|
public static Charset detectEncodingCharset(File file) {
|
||||||
return new Charset[]{
|
String charset = detectEncoding(file);
|
||||||
StandardCharsets.UTF_8,
|
if (charset.equals(UNKNOWN)) {
|
||||||
StandardCharsets.UTF_16,
|
return StandardCharsets.UTF_8;
|
||||||
StandardCharsets.UTF_16LE,
|
}
|
||||||
StandardCharsets.UTF_16BE,
|
return Charset.forName(charset);
|
||||||
StandardCharsets.ISO_8859_1
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查指定编码是否能够正确解码文本
|
|
||||||
*
|
|
||||||
* @param text 要检测的文本
|
|
||||||
* @param encoding 要尝试的编码
|
|
||||||
* @return 如果指定编码能够正确解码文本,则返回 true,否则返回 false
|
|
||||||
*/
|
|
||||||
private static boolean isValidEncoding(String text, Charset encoding) {
|
|
||||||
// 尝试使用指定编码解码
|
|
||||||
byte[] bytes = text.getBytes(encoding);
|
|
||||||
String decoded = new String(bytes, encoding);
|
|
||||||
|
|
||||||
// 解码后的文本相同表示编码有效
|
|
||||||
return text.equals(decoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -3,6 +3,7 @@ package org.jcnc.jnotepad.tool;
|
|||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -48,7 +49,7 @@ public class FileUtil {
|
|||||||
* @see LogUtil
|
* @see LogUtil
|
||||||
*/
|
*/
|
||||||
public static void saveTab(Class<?> currentClass) {
|
public static void saveTab(Class<?> currentClass) {
|
||||||
Tab selectedTab = JNotepadTabPane.getInstance().getSelected();
|
JNotepadTab selectedTab = JNotepadTabPane.getInstance().getSelected();
|
||||||
if (selectedTab != null) {
|
if (selectedTab != null) {
|
||||||
// 创建一个文件窗口
|
// 创建一个文件窗口
|
||||||
FileChooser fileChooser = new FileChooser();
|
FileChooser fileChooser = new FileChooser();
|
||||||
@ -58,24 +59,13 @@ public class FileUtil {
|
|||||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt"));
|
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt"));
|
||||||
File file = fileChooser.showSaveDialog(null);
|
File file = fileChooser.showSaveDialog(null);
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
try (
|
selectedTab.save();
|
||||||
BufferedWriter writer = new BufferedWriter(new FileWriter(file))
|
// 将保存后的文件设置为已关联
|
||||||
) {
|
selectedTab.getLineNumberTextArea().setRelevance(true);
|
||||||
// 获取当前Tab页的文本编辑区
|
// 更新Tab页标签上的文件名
|
||||||
LineNumberTextArea textArea = (LineNumberTextArea) selectedTab.getContent();
|
selectedTab.setText(file.getName());
|
||||||
// 将保存后的文件设置为已关联
|
// 将文件对象保存到Tab页的UserData中
|
||||||
textArea.setRelevance(true);
|
selectedTab.setUserData(file);
|
||||||
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异常!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,18 @@
|
|||||||
package org.jcnc.jnotepad.ui;
|
package org.jcnc.jnotepad.ui;
|
||||||
|
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.scene.control.Tab;
|
||||||
import javafx.scene.control.TextArea;
|
import javafx.scene.control.TextArea;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
|
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 许轲
|
* @author 许轲
|
||||||
@ -28,16 +38,50 @@ public class LineNumberTextArea extends BorderPane {
|
|||||||
// 设定自定义样式
|
// 设定自定义样式
|
||||||
lineNumberArea.getStyleClass().add("text-line-number");
|
lineNumberArea.getStyleClass().add("text-line-number");
|
||||||
mainTextArea.getStyleClass().add("main-text-area");
|
mainTextArea.getStyleClass().add("main-text-area");
|
||||||
lineNumberArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberWidth());
|
this.setStyle(
|
||||||
mainTextArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberArea());
|
"-fx-border-color:white;" +
|
||||||
|
"-fx-background-color:white"
|
||||||
|
);
|
||||||
|
setCenter(mainTextArea);
|
||||||
|
setLeft(lineNumberArea);
|
||||||
|
|
||||||
|
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()));
|
||||||
setCenter(mainTextArea);
|
lineNumberArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberWidth());
|
||||||
setLeft(lineNumberArea);
|
|
||||||
|
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();
|
||||||
|
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() {
|
public boolean isRelevance() {
|
||||||
@ -91,5 +135,6 @@ public class LineNumberTextArea extends BorderPane {
|
|||||||
public TextArea getMainTextArea() {
|
public TextArea getMainTextArea() {
|
||||||
return mainTextArea;
|
return mainTextArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
115
src/main/java/org/jcnc/jnotepad/ui/status/JNotepadStatusBox.java
Normal file
115
src/main/java/org/jcnc/jnotepad/ui/status/JNotepadStatusBox.java
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package org.jcnc.jnotepad.ui.status;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TextArea;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态栏组件封装。
|
||||||
|
* 1. 文字统计
|
||||||
|
* 2. 编码
|
||||||
|
*
|
||||||
|
* @author songdragon
|
||||||
|
*/
|
||||||
|
public class JNotepadStatusBox extends HBox {
|
||||||
|
|
||||||
|
private static final JNotepadStatusBox STATUS_BOX = new JNotepadStatusBox();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字数统计及光标
|
||||||
|
*/
|
||||||
|
private final Label statusLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示文本编码
|
||||||
|
*/
|
||||||
|
private final Label enCodingLabel; // 显示文本编码
|
||||||
|
|
||||||
|
private JNotepadStatusBox() {
|
||||||
|
// 创建状态栏
|
||||||
|
statusLabel = new Label("行数:1 \t列数:1 \t字数:0 ");
|
||||||
|
// 创建新的标签以显示编码信息
|
||||||
|
enCodingLabel = new Label();
|
||||||
|
|
||||||
|
this.getChildren().add(statusLabel);
|
||||||
|
this.getChildren().add(enCodingLabel);
|
||||||
|
this.getProperties().put("borderpane-margin", new Insets(5, 10, 5, 10));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JNotepadStatusBox getInstance() {
|
||||||
|
return STATUS_BOX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateEncodingLabel() {
|
||||||
|
updateEncodingLabel(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新编码展示
|
||||||
|
* @param encoding 文件编码
|
||||||
|
*/
|
||||||
|
public void updateEncodingLabel(String encoding) {
|
||||||
|
if (encoding == null) {
|
||||||
|
encoding = Charset.defaultCharset().name();
|
||||||
|
}
|
||||||
|
this.enCodingLabel.setText("\t编码: " + encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新字数统计
|
||||||
|
*/
|
||||||
|
public void updateWordCountStatusLabel() {
|
||||||
|
TextArea textArea = JNotepadTabPane.getInstance().getSelected().getLineNumberTextArea().getMainTextArea();
|
||||||
|
int caretPosition = textArea.getCaretPosition();
|
||||||
|
int row = getRow(caretPosition, textArea.getText());
|
||||||
|
int column = getColumn(caretPosition, textArea.getText());
|
||||||
|
int length = textArea.getLength();
|
||||||
|
this.statusLabel.setText("行: " + row + " \t列: " + column + " \t字数: " + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tab选中时,更新状态栏
|
||||||
|
* 1. 状态栏更新当前选中tab的数字统计
|
||||||
|
* 2. 状态栏更新当前选中tab的字符编码
|
||||||
|
*/
|
||||||
|
public void updateWhenTabSelected() {
|
||||||
|
updateWordCountStatusLabel();
|
||||||
|
updateEncodingLabel(JNotepadTabPane.getInstance().getSelected().getCharset().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取光标所在行号。
|
||||||
|
*
|
||||||
|
* @param caretPosition 光标位置
|
||||||
|
* @param text 文本内容
|
||||||
|
* @return 光标所在行号
|
||||||
|
*/
|
||||||
|
public int getRow(int caretPosition, String text) {
|
||||||
|
caretPosition = Math.min(caretPosition, text.length());
|
||||||
|
String substring = text.substring(0, caretPosition);
|
||||||
|
int count = 0;
|
||||||
|
for (char c : substring.toCharArray()) {
|
||||||
|
if (c == '\n') {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取光标所在列号。
|
||||||
|
*
|
||||||
|
* @param caretPosition 光标位置
|
||||||
|
* @param text 文本内容
|
||||||
|
* @return 光标所在列号
|
||||||
|
*/
|
||||||
|
public int getColumn(int caretPosition, String text) {
|
||||||
|
return caretPosition - text.lastIndexOf("\n", caretPosition - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -4,6 +4,8 @@ import javafx.scene.control.Tab;
|
|||||||
import org.jcnc.jnotepad.app.config.GlobalConfig;
|
import org.jcnc.jnotepad.app.config.GlobalConfig;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 封装标签页组件,增加属于标签页的属性,例如:自动换行开关。
|
* 封装标签页组件,增加属于标签页的属性,例如:自动换行开关。
|
||||||
* 每个Tab关联一个LineNumberTextArea。
|
* 每个Tab关联一个LineNumberTextArea。
|
||||||
@ -17,12 +19,17 @@ public class JNotepadTab extends Tab {
|
|||||||
*/
|
*/
|
||||||
private boolean autoLine = false;
|
private boolean autoLine = false;
|
||||||
private final LineNumberTextArea lineNumberTextArea;
|
private final LineNumberTextArea lineNumberTextArea;
|
||||||
|
private Charset charset = Charset.defaultCharset();
|
||||||
|
|
||||||
public JNotepadTab(String tabTitle) {
|
public JNotepadTab(String tabTitle) {
|
||||||
this(tabTitle, new LineNumberTextArea());
|
this(tabTitle, new LineNumberTextArea());
|
||||||
}
|
}
|
||||||
|
|
||||||
public JNotepadTab(String tabTitle, LineNumberTextArea textArea) {
|
public JNotepadTab(String tabTitle, LineNumberTextArea textArea) {
|
||||||
|
this(tabTitle, textArea, Charset.defaultCharset());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JNotepadTab(String tabTitle, LineNumberTextArea textArea, Charset charset) {
|
||||||
super(tabTitle);
|
super(tabTitle);
|
||||||
lineNumberTextArea = textArea;
|
lineNumberTextArea = textArea;
|
||||||
this.setContent(lineNumberTextArea);
|
this.setContent(lineNumberTextArea);
|
||||||
@ -41,4 +48,16 @@ public class JNotepadTab extends Tab {
|
|||||||
public LineNumberTextArea getLineNumberTextArea() {
|
public LineNumberTextArea getLineNumberTextArea() {
|
||||||
return lineNumberTextArea;
|
return lineNumberTextArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Charset getCharset() {
|
||||||
|
return charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCharset(Charset charset) {
|
||||||
|
this.charset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
this.lineNumberTextArea.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.jnotepad.ui.tab;
|
|||||||
import javafx.scene.control.TabPane;
|
import javafx.scene.control.TabPane;
|
||||||
import org.jcnc.jnotepad.app.config.GlobalConfig;
|
import org.jcnc.jnotepad.app.config.GlobalConfig;
|
||||||
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
||||||
|
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标签页布局组件封装。
|
* 标签页布局组件封装。
|
||||||
@ -25,8 +26,11 @@ public class JNotepadTabPane extends TabPane {
|
|||||||
this.getSelectionModel().selectedItemProperty().addListener(
|
this.getSelectionModel().selectedItemProperty().addListener(
|
||||||
(ov, from, to) -> {
|
(ov, from, to) -> {
|
||||||
if (to != null) {
|
if (to != null) {
|
||||||
|
// 更新菜单栏中与tab相关设置
|
||||||
JNotepadMenuBar.getMenuBar().updateMenuStatusBySelectedTab();
|
JNotepadMenuBar.getMenuBar().updateMenuStatusBySelectedTab();
|
||||||
}
|
}
|
||||||
|
// 更新状态标签
|
||||||
|
JNotepadStatusBox.getInstance().updateWordCountStatusLabel();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -65,5 +69,6 @@ public class JNotepadTabPane extends TabPane {
|
|||||||
public void fireTabSelected() {
|
public void fireTabSelected() {
|
||||||
JNotepadTab selectedTab = getSelected();
|
JNotepadTab selectedTab = getSelected();
|
||||||
selectedTab.setAutoLine(GlobalConfig.getConfig().getAutoLineConfig());
|
selectedTab.setAutoLine(GlobalConfig.getConfig().getAutoLineConfig());
|
||||||
|
JNotepadStatusBox.getInstance().updateWhenTabSelected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package org.jcnc.jnotepad.view.init;
|
package org.jcnc.jnotepad.view.init;
|
||||||
|
|
||||||
import org.jcnc.jnotepad.controller.manager.Controller;
|
|
||||||
import org.jcnc.jnotepad.controller.manager.ShortcutKey;
|
import org.jcnc.jnotepad.controller.manager.ShortcutKey;
|
||||||
|
|
||||||
|
|
||||||
@ -9,10 +8,6 @@ import org.jcnc.jnotepad.controller.manager.ShortcutKey;
|
|||||||
*/
|
*/
|
||||||
public class View {
|
public class View {
|
||||||
|
|
||||||
public void initTabPane() {
|
|
||||||
Controller.getInstance().initTabPane();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化快捷键
|
// 初始化快捷键
|
||||||
public void initShortcutKey() {
|
public void initShortcutKey() {
|
||||||
new ShortcutKey().createShortcutKeyByConfig();
|
new ShortcutKey().createShortcutKeyByConfig();
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import javafx.scene.layout.BorderPane;
|
|||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import org.jcnc.jnotepad.exception.AppException;
|
import org.jcnc.jnotepad.exception.AppException;
|
||||||
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
||||||
|
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
|
|
||||||
|
|
||||||
@ -17,11 +18,6 @@ import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
|||||||
*/
|
*/
|
||||||
public class ViewManager {
|
public class ViewManager {
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示文本编码
|
|
||||||
*/
|
|
||||||
private Label enCodingLabel; // 显示文本编码
|
|
||||||
|
|
||||||
private int tabIndex = 0;
|
private int tabIndex = 0;
|
||||||
|
|
||||||
private Boolean line = true;
|
private Boolean line = true;
|
||||||
@ -30,19 +26,13 @@ public class ViewManager {
|
|||||||
// 主界面布局
|
// 主界面布局
|
||||||
private BorderPane root; // 主布局
|
private BorderPane root; // 主布局
|
||||||
|
|
||||||
// 状态栏
|
|
||||||
private Label statusLabel;
|
|
||||||
|
|
||||||
private static ViewManager instance = null;
|
private static ViewManager instance = null;
|
||||||
|
|
||||||
|
|
||||||
public Label getEnCodingLabel() {
|
|
||||||
return enCodingLabel;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 自增并获取标签页索引
|
* 自增并获取标签页索引
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @return int 标签页索引
|
* @return int 标签页索引
|
||||||
* @apiNote ++tabIndex
|
* @apiNote ++tabIndex
|
||||||
*/
|
*/
|
||||||
@ -59,10 +49,6 @@ public class ViewManager {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Label getStatusLabel() {
|
|
||||||
return statusLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取ViewManager的实例。如果实例不存在,则创建一个新实例。
|
* 获取ViewManager的实例。如果实例不存在,则创建一个新实例。
|
||||||
@ -109,14 +95,7 @@ public class ViewManager {
|
|||||||
|
|
||||||
// 创建标签页和文本编辑区域
|
// 创建标签页和文本编辑区域
|
||||||
root.setCenter(JNotepadTabPane.getInstance());
|
root.setCenter(JNotepadTabPane.getInstance());
|
||||||
|
root.setBottom(JNotepadStatusBox.getInstance());
|
||||||
// 创建状态栏
|
|
||||||
statusLabel = new Label("行数:1 \t列数:1 \t字数:0 ");
|
|
||||||
|
|
||||||
enCodingLabel = new Label(); // 创建新的标签以显示编码信息
|
|
||||||
HBox statusBox = new HBox(statusLabel, enCodingLabel); // 使用HBox放置状态标签和编码标签
|
|
||||||
root.setBottom(statusBox);
|
|
||||||
BorderPane.setMargin(statusBox, new Insets(5, 10, 5, 10));
|
|
||||||
|
|
||||||
scene.setRoot(root);
|
scene.setRoot(root);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user