实现带行标的textarea

(未隐藏滚动条)
This commit is contained in:
许轲 2023-08-19 14:12:58 +08:00
parent 9617ee5046
commit b2718c1932
15 changed files with 172 additions and 70 deletions

1
.gitignore vendored
View File

@ -38,3 +38,4 @@ build/
.DS_Store .DS_Store
/JNotepad/ /JNotepad/
/src/main/JNotepad.java /src/main/JNotepad.java
/.idea/

View File

@ -11,4 +11,5 @@ module org.jcnc.jnotepad {
exports org.jcnc.jnotepad.view.init; exports org.jcnc.jnotepad.view.init;
exports org.jcnc.jnotepad.view.manager; exports org.jcnc.jnotepad.view.manager;
exports org.jcnc.jnotepad.constants; exports org.jcnc.jnotepad.constants;
exports org.jcnc.jnotepad.ui;
} }

View File

@ -2,7 +2,7 @@ package org.jcnc.jnotepad.Interface;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.control.TextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
@ -18,7 +18,7 @@ public interface ControllerInterface {
* @param rawParameters 原始参数列表 * @param rawParameters 原始参数列表
* @return 创建的 TextArea * @return 创建的 TextArea
*/ */
TextArea openAssociatedFileAndCreateTextArea(List<String> rawParameters); LineNumberTextArea openAssociatedFileAndCreateTextArea(List<String> rawParameters);
/** /**
* 获取换行符处理事件处理程序 * 获取换行符处理事件处理程序
@ -26,7 +26,7 @@ public interface ControllerInterface {
* @param textArea 文本区域 * @param textArea 文本区域
* @return 换行符处理事件处理程序 * @return 换行符处理事件处理程序
*/ */
EventHandler<ActionEvent> getLineFeedEventHandler(TextArea textArea); EventHandler<ActionEvent> getLineFeedEventHandler(LineNumberTextArea textArea);
/** /**
* 获取新建文件处理事件处理程序 * 获取新建文件处理事件处理程序
@ -34,7 +34,7 @@ public interface ControllerInterface {
* @param textArea 文本区域 * @param textArea 文本区域
* @return 新建文件处理事件处理程序 * @return 新建文件处理事件处理程序
*/ */
EventHandler<ActionEvent> getNewFileEventHandler(TextArea textArea); EventHandler<ActionEvent> getNewFileEventHandler(LineNumberTextArea textArea);
/** /**
* 获取打开文件处理事件处理程序 * 获取打开文件处理事件处理程序
@ -56,14 +56,14 @@ public interface ControllerInterface {
* *
* @param textArea 文本区域 * @param textArea 文本区域
*/ */
void autoSave(TextArea textArea); void autoSave(LineNumberTextArea textArea);
/** /**
* 更新状态标签 * 更新状态标签
* *
* @param textArea 文本区域 * @param textArea 文本区域
*/ */
void updateStatusLabel(TextArea textArea); void updateStatusLabel(LineNumberTextArea textArea);
/** /**
* 打开关联文件 * 打开关联文件
@ -109,5 +109,5 @@ public interface ControllerInterface {
*/ */
void initTabPane(); void initTabPane();
void updateUIWithNewTextArea(TextArea textArea); void updateUIWithNewTextArea(LineNumberTextArea textArea);
} }

View File

@ -4,13 +4,13 @@ import atlantafx.base.theme.PrimerLight;
import javafx.application.Application; import javafx.application.Application;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.jcnc.jnotepad.constants.Constants; import org.jcnc.jnotepad.constants.Constants;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.view.init.View; import org.jcnc.jnotepad.view.init.View;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.view.manager.ViewManager;
@ -23,6 +23,7 @@ public class LunchApp extends Application {
private static final ExecutorService threadPool = Executors.newCachedThreadPool(); private static final ExecutorService threadPool = Executors.newCachedThreadPool();
public static boolean isRelevance = true; public static boolean isRelevance = true;
Scene scene;
Controller controller = new Controller(); Controller controller = new Controller();
View view; View view;
@ -30,23 +31,24 @@ public class LunchApp extends Application {
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
view =new View(); view = new View();
Pane root = new Pane(); Pane root = new Pane();
double width = Constants.SCREEN_WIDTH; double width = Constants.SCREEN_WIDTH;
double length = Constants.SCREEN_LENGTH; double length = Constants.SCREEN_LENGTH;
String name = Constants.APP_NAME; String name = Constants.APP_NAME;
String icon = Constants.APP_ICON; String icon = Constants.APP_ICON;
Scene scene = new Scene(root, width, length); scene = new Scene(root, width, length);
Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet()); Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
primaryStage.setTitle(name); primaryStage.setTitle(name);
primaryStage.setWidth(width); primaryStage.setWidth(width);
primaryStage.setHeight(length); primaryStage.setHeight(length);
primaryStage.setScene(scene); primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResource(icon)).toString())); primaryStage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResource(icon)).toString()));
primaryStage.show(); primaryStage.show();
ViewManager viewManager = ViewManager.getInstance(scene); ViewManager viewManager = ViewManager.getInstance(scene);
@ -58,15 +60,17 @@ public class LunchApp extends Application {
view.initShortcutKey(); view.initShortcutKey();
if (isRelevance) { if (isRelevance) {
// 使用线程池加载关联文件并创建文本区域 // 使用线程池加载关联文件并创建文本区域
List<String> rawParameters = getParameters().getRaw(); List<String> rawParameters = getParameters().getRaw();
threadPool.execute(() -> { threadPool.execute(() -> {
TextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters); LineNumberTextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters);
if (!Objects.isNull(textArea)) { if (!Objects.isNull(textArea)) {
Platform.runLater(() -> controller.updateUIWithNewTextArea(textArea)); Platform.runLater(() -> controller.updateUIWithNewTextArea(textArea));
} }
}); });
} }
} }
@Override @Override

View File

@ -2,7 +2,7 @@ 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.TextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
/** /**
* 换行程序 * 换行程序
@ -10,13 +10,13 @@ import javafx.scene.control.TextArea;
* 用于在文本区域中插入一个换行符 * 用于在文本区域中插入一个换行符
*/ */
public class LineFeed implements EventHandler<ActionEvent> { public class LineFeed implements EventHandler<ActionEvent> {
private final TextArea textArea; private final LineNumberTextArea textArea;
/** /**
* 构造函数初始化 LineFeed 对象 * 构造函数初始化 LineFeed 对象
* @param textArea 要操作的文本区域 * @param textArea 要操作的文本区域
*/ */
public LineFeed(TextArea textArea) { public LineFeed(LineNumberTextArea textArea) {
this.textArea = textArea; this.textArea = textArea;
} }
@ -26,7 +26,7 @@ public class LineFeed implements EventHandler<ActionEvent> {
*/ */
@Override @Override
public void handle(ActionEvent event) { public void handle(ActionEvent event) {
String text = textArea.getText(); String text = textArea.getMainTextArea().getText();
textArea.setText(text + "\n"); textArea.getMainTextArea().setText(text + "\n");
} }
} }

View File

@ -3,10 +3,12 @@ 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 javafx.scene.control.Tab;
import javafx.scene.control.TextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.view.manager.ViewManager;
import java.util.Objects;
import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane; import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane;
/** /**
@ -25,15 +27,21 @@ public class NewFile implements EventHandler<ActionEvent> {
// 获取控制器 // 获取控制器
Controller controller = new Controller(); Controller controller = new Controller();
LineNumberTextArea lineNumberTextArea = new LineNumberTextArea();
// 创建一个新的文本编辑区 // 创建一个新的文本编辑区
TextArea textArea = new TextArea(); LineNumberTextArea textArea = new LineNumberTextArea();
textArea.setStyle( textArea.setStyle(
"-fx-border-color:white;" + "-fx-border-color:white ;-fx-background-color:white;"
"-fx-background-color:white"
); );
// 创建一个新的Tab页 // 创建一个新的Tab页
Tab tab = new Tab("新建文本 " + ++ViewManager.tabIndex); Tab tab = new Tab("新建文本 " + ++ViewManager.tabIndex);
tab.setContent(textArea); tab.setContent(lineNumberTextArea.getMainTextArea());
// 将Tab页添加到TabPane中 // 将Tab页添加到TabPane中
tabPane.getTabs().add(tab); tabPane.getTabs().add(tab);
@ -42,9 +50,9 @@ public class NewFile implements EventHandler<ActionEvent> {
tabPane.getSelectionModel().select(tab); tabPane.getSelectionModel().select(tab);
// 更新状态标签 // 更新状态标签
controller.updateStatusLabel(textArea); controller.updateStatusLabel(lineNumberTextArea);
// 更新编码信息 // 更新编码信息
controller.upDateEncodingLabel(textArea.getText()); controller.upDateEncodingLabel(lineNumberTextArea.getMainTextArea().getText());
} }
} }

View File

@ -3,8 +3,9 @@ package org.jcnc.jnotepad.controller.event.handler;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.control.TextArea;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import java.io.File; import java.io.File;
@ -38,7 +39,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
// 调用控制器的getText方法读取文件内容 // 调用控制器的getText方法读取文件内容
controller.getText(file); controller.getText(file);
// 更新编码标签 // 更新编码标签
controller.upDateEncodingLabel(((TextArea) tabPane.getSelectionModel().getSelectedItem().getContent()).getText()); controller.upDateEncodingLabel(((LineNumberTextArea) tabPane.getSelectionModel().getSelectedItem().getContent()).getMainTextArea().getText());
return null; return null;
} }
}; };

View File

@ -3,9 +3,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 javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TextArea;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
@ -39,8 +38,8 @@ public class SaveAsFile implements EventHandler<ActionEvent> {
if (file != null) { if (file != null) {
try { try {
BufferedWriter writer = new BufferedWriter(new FileWriter(file)); BufferedWriter writer = new BufferedWriter(new FileWriter(file));
TextArea textArea = (TextArea) selectedTab.getContent(); // 获取当前Tab页的文本编辑区 LineNumberTextArea textArea = (LineNumberTextArea) selectedTab.getContent(); // 获取当前Tab页的文本编辑区
String text = textArea.getText(); String text = textArea.getMainTextArea().getText();
writer.write(text); // 写入文件内容 writer.write(text); // 写入文件内容
writer.flush(); writer.flush();
writer.close(); writer.close();

View File

@ -5,10 +5,9 @@ import javafx.concurrent.Task;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TextArea;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import org.jcnc.jnotepad.Interface.ControllerInterface; import org.jcnc.jnotepad.Interface.ControllerInterface;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.LunchApp; import org.jcnc.jnotepad.LunchApp;
import org.jcnc.jnotepad.controller.event.handler.LineFeed; import org.jcnc.jnotepad.controller.event.handler.LineFeed;
import org.jcnc.jnotepad.controller.event.handler.NewFile; import org.jcnc.jnotepad.controller.event.handler.NewFile;
@ -33,13 +32,13 @@ public class Controller implements ControllerInterface {
* @return 创建的文本区域 * @return 创建的文本区域
*/ */
@Override @Override
public TextArea openAssociatedFileAndCreateTextArea(List<String> rawParameters) { public LineNumberTextArea openAssociatedFileAndCreateTextArea(List<String> rawParameters) {
if (!rawParameters.isEmpty()) { if (!rawParameters.isEmpty()) {
String filePath = rawParameters.get(0); String filePath = rawParameters.get(0);
openAssociatedFile(filePath); openAssociatedFile(filePath);
return null; return null;
} else { } else {
TextArea textArea = createNewTextArea(); LineNumberTextArea textArea = createNewTextArea();
configureTextArea(textArea); configureTextArea(textArea);
return textArea; return textArea;
} }
@ -52,7 +51,7 @@ public class Controller implements ControllerInterface {
* @return 行分隔事件处理程序 * @return 行分隔事件处理程序
*/ */
@Override @Override
public EventHandler<ActionEvent> getLineFeedEventHandler(TextArea textArea) { public EventHandler<ActionEvent> getLineFeedEventHandler(LineNumberTextArea textArea) {
return new LineFeed(textArea); return new LineFeed(textArea);
} }
@ -63,7 +62,7 @@ public class Controller implements ControllerInterface {
* @return 新建文件事件处理程序 * @return 新建文件事件处理程序
*/ */
@Override @Override
public EventHandler<ActionEvent> getNewFileEventHandler(TextArea textArea) { public EventHandler<ActionEvent> getNewFileEventHandler(LineNumberTextArea textArea) {
return new NewFile(); return new NewFile();
} }
@ -83,7 +82,7 @@ public class Controller implements ControllerInterface {
* @param textArea 文本区域 * @param textArea 文本区域
*/ */
@Override @Override
public void autoSave(TextArea textArea) { public void autoSave(LineNumberTextArea textArea) {
textArea.textProperty().addListener((observable, oldValue, newValue) -> { textArea.textProperty().addListener((observable, oldValue, newValue) -> {
Tab tab = ViewManager.tabPane.getSelectionModel().getSelectedItem(); Tab tab = ViewManager.tabPane.getSelectionModel().getSelectedItem();
if (tab != null) { if (tab != null) {
@ -116,11 +115,11 @@ public class Controller implements ControllerInterface {
* @param textArea 文本区域 * @param textArea 文本区域
*/ */
@Override @Override
public void updateStatusLabel(TextArea textArea) { public void updateStatusLabel(LineNumberTextArea textArea) {
int caretPosition = textArea.getCaretPosition(); int caretPosition = textArea.getMainTextArea().getCaretPosition();
int row = getRow(caretPosition, textArea.getText()); int row = getRow(caretPosition, textArea.getMainTextArea().getText());
int column = getColumn(caretPosition, textArea.getText()); int column = getColumn(caretPosition, textArea.getMainTextArea().getText());
int length = textArea.getLength(); int length = textArea.getMainTextArea().getLength();
ViewManager.statusLabel.setText("行: " + row + " \t列: " + column + " \t字数: " + length); ViewManager.statusLabel.setText("行: " + row + " \t列: " + column + " \t字数: " + length);
} }
@ -145,7 +144,7 @@ public class Controller implements ControllerInterface {
*/ */
@Override @Override
public void getText(File file) { public void getText(File file) {
TextArea textArea = createNewTextArea(); LineNumberTextArea textArea = createNewTextArea();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
StringBuilder textBuilder = new StringBuilder(); StringBuilder textBuilder = new StringBuilder();
String line; String line;
@ -155,7 +154,7 @@ public class Controller implements ControllerInterface {
String text = textBuilder.toString(); String text = textBuilder.toString();
Platform.runLater(() -> { Platform.runLater(() -> {
textArea.setText(text); textArea.getMainTextArea().setText(text);
Tab tab = createNewTab(file.getName(), textArea); Tab tab = createNewTab(file.getName(), textArea);
tab.setUserData(file); tab.setUserData(file);
@ -224,22 +223,22 @@ public class Controller implements ControllerInterface {
ViewManager.tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { ViewManager.tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> {
if (newTab != null) { if (newTab != null) {
// 获取新选定的标签页并关联的文本区域 // 获取新选定的标签页并关联的文本区域
TextArea textArea = (TextArea) newTab.getContent(); LineNumberTextArea textArea = (LineNumberTextArea) newTab.getContent();
// 更新状态标签 // 更新状态标签
controller.updateStatusLabel(textArea); controller.updateStatusLabel(textArea);
// 监听文本光标位置的变化更新状态标签 // 监听文本光标位置的变化更新状态标签
textArea.caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> controller.updateStatusLabel(textArea)); textArea.getMainTextArea().caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> controller.updateStatusLabel(textArea));
// 更新编码标签 // 更新编码标签
controller.upDateEncodingLabel(textArea.getText()); controller.upDateEncodingLabel(textArea.getMainTextArea().getText());
} }
}); });
} }
@Override @Override
public void updateUIWithNewTextArea(TextArea textArea) { public void updateUIWithNewTextArea(LineNumberTextArea textArea) {
Tab tab = new Tab("新建文件 " + (++ViewManager.tabIndex)); Tab tab = new Tab("新建文件 " + (++ViewManager.tabIndex));
tab.setContent(textArea); tab.setContent(textArea);
ViewManager.tabPane.getTabs().add(tab); ViewManager.tabPane.getTabs().add(tab);
@ -252,9 +251,9 @@ public class Controller implements ControllerInterface {
* *
* @param textArea 文本区域 * @param textArea 文本区域
*/ */
private void configureTextArea(TextArea textArea) { private void configureTextArea(LineNumberTextArea textArea) {
textArea.setWrapText(true); textArea.getMainTextArea().setWrapText(true);
upDateEncodingLabel(textArea.getText()); upDateEncodingLabel(textArea.getMainTextArea().getText());
updateStatusLabel(textArea); updateStatusLabel(textArea);
textArea.textProperty().addListener((observable, oldValue, newValue) -> updateStatusLabel(textArea)); textArea.textProperty().addListener((observable, oldValue, newValue) -> updateStatusLabel(textArea));
@ -267,8 +266,8 @@ public class Controller implements ControllerInterface {
* *
* @return 新的文本区域 * @return 新的文本区域
*/ */
private TextArea createNewTextArea() { private LineNumberTextArea createNewTextArea() {
TextArea textArea = new TextArea(); LineNumberTextArea textArea = new LineNumberTextArea();
textArea.setStyle( textArea.setStyle(
"-fx-border-color:white;" + "-fx-border-color:white;" +
"-fx-background-color:white" "-fx-background-color:white"
@ -283,7 +282,7 @@ public class Controller implements ControllerInterface {
* @param textArea 文本区域 * @param textArea 文本区域
* @return 新的标签页 * @return 新的标签页
*/ */
private Tab createNewTab(String tabName, TextArea textArea) { private Tab createNewTab(String tabName, LineNumberTextArea textArea) {
Tab tab = new Tab(tabName); Tab tab = new Tab(tabName);
tab.setContent(textArea); tab.setContent(textArea);
tab.setUserData(null); tab.setUserData(null);
@ -297,12 +296,12 @@ public class Controller implements ControllerInterface {
* @return 打开文件的任务 * @return 打开文件的任务
*/ */
private Task<Void> createOpenFileTask(File file) { private Task<Void> createOpenFileTask(File file) {
TextArea textArea = createNewTextArea(); LineNumberTextArea textArea = createNewTextArea();
return new Task<>() { return new Task<>() {
@Override @Override
protected Void call() { protected Void call() {
getText(file); getText(file);
upDateEncodingLabel(textArea.getText()); upDateEncodingLabel(textArea.getMainTextArea().getText());
return null; return null;
} }
}; };

View File

@ -1,6 +1,7 @@
package org.jcnc.jnotepad.tool; package org.jcnc.jnotepad.tool;
import javafx.scene.control.TextArea;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -16,8 +17,8 @@ public class EncodingDetector {
* @param textArea 文本区域 * @param textArea 文本区域
* @return 字符串表示的编码如果检测失败则返回 "UNKNOWN" * @return 字符串表示的编码如果检测失败则返回 "UNKNOWN"
*/ */
public static String detectEncoding(TextArea textArea) { public static String detectEncoding(LineNumberTextArea textArea) {
String text = textArea.getText(); String text = textArea.getMainTextArea().getText();
return detectEncoding(text); return detectEncoding(text);
} }

View File

@ -1,6 +1,7 @@
package org.jcnc.jnotepad.tool; package org.jcnc.jnotepad.tool;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets;
/** /**
* @author 一个大转盘 * @author 一个大转盘
@ -18,7 +19,7 @@ public class FileUtil {
String jsonStr = ""; String jsonStr = "";
try { try {
FileReader fileReader = new FileReader(jsonFile); FileReader fileReader = new FileReader(jsonFile);
Reader reader = new InputStreamReader(new FileInputStream(jsonFile),"utf-8"); Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8);
int ch = 0; int ch = 0;
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
while ((ch = reader.read()) != -1) { while ((ch = reader.read()) != -1) {

View File

@ -0,0 +1,70 @@
package org.jcnc.jnotepad.ui;
import javafx.beans.property.StringProperty;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import java.util.Objects;
public class LineNumberTextArea extends BorderPane {
private final TextArea mainTextArea;
private final TextArea lineNumberArea;
public LineNumberTextArea() {
mainTextArea = new TextArea();
lineNumberArea = new TextArea();
lineNumberArea.setEditable(false);
lineNumberArea.setMinWidth(55);
lineNumberArea.setMaxWidth(55);
// 设置显示滚动条样式类
/* lineNumberArea.getStyleClass().add("hide-scrollbars");
mainTextArea.getStyleClass().add("show-scrollbars"); */
mainTextArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberArea());
// 当主要文本区域的垂直滚动位置发生变化时使行号文本区域的滚动位置保持一致
mainTextArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> {
lineNumberArea.setScrollTop(mainTextArea.getScrollTop());
});
// 当行号文本区域的垂直滚动位置发生变化时使主要文本区域的滚动位置保持一致
lineNumberArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> {
mainTextArea.setScrollTop(lineNumberArea.getScrollTop());
});
setCenter(mainTextArea);
setLeft(lineNumberArea);
}
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;
}
}

View File

@ -2,11 +2,7 @@ package org.jcnc.jnotepad.view.init;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.Scene; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.controller.manager.ShortcutKey; import org.jcnc.jnotepad.controller.manager.ShortcutKey;
@ -21,13 +17,13 @@ public class View {
public void initItem() { public void initItem() {
// 初始化菜单项的事件处理器 // 初始化菜单项的事件处理器
EventHandler<ActionEvent> newFileEventHandler = new Controller().getNewFileEventHandler(new TextArea()); EventHandler<ActionEvent> newFileEventHandler = new Controller().getNewFileEventHandler(new LineNumberTextArea());
newItem.setOnAction(newFileEventHandler); newItem.setOnAction(newFileEventHandler);
EventHandler<ActionEvent> openFileEventHandler = new Controller().getOpenFileEventHandler(); EventHandler<ActionEvent> openFileEventHandler = new Controller().getOpenFileEventHandler();
openItem.setOnAction(openFileEventHandler); openItem.setOnAction(openFileEventHandler);
EventHandler<ActionEvent> saveAsFileEventHandler = new Controller().getSaveAsFileEventHandler(); EventHandler<ActionEvent> saveAsFileEventHandler = new Controller().getSaveAsFileEventHandler();
saveAsItem.setOnAction(saveAsFileEventHandler); saveAsItem.setOnAction(saveAsFileEventHandler);
lineFeedItem.setOnAction(new Controller().getLineFeedEventHandler(new TextArea())); lineFeedItem.setOnAction(new Controller().getLineFeedEventHandler(new LineNumberTextArea()));
} }
public void initTabPane() { public void initTabPane() {

View File

@ -3,12 +3,12 @@ package org.jcnc.jnotepad.view.manager;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* 该类管理记事本应用程序的视图组件 * 该类管理记事本应用程序的视图组件
@ -30,6 +30,8 @@ public class ViewManager {
// 主界面布局 // 主界面布局
public static BorderPane root; //主布局 public static BorderPane root; //主布局
// 多个标签页 // 多个标签页
public static TabPane tabPane; //标签页栏 public static TabPane tabPane; //标签页栏
@ -47,6 +49,7 @@ public class ViewManager {
* @return ViewManager的实例 * @return ViewManager的实例
*/ */
public static ViewManager getInstance(Scene scene) { public static ViewManager getInstance(Scene scene) {
if (instance == null) { if (instance == null) {
instance = new ViewManager(scene); instance = new ViewManager(scene);
} }
@ -60,7 +63,11 @@ public class ViewManager {
*/ */
private ViewManager(Scene scene) { private ViewManager(Scene scene) {
root = new BorderPane(); root = new BorderPane();
scene.setRoot(root); scene.setRoot(root);
} }
/** /**
@ -125,5 +132,8 @@ public class ViewManager {
BorderPane.setMargin(statusBox, new Insets(5, 10, 5, 10)); BorderPane.setMargin(statusBox, new Insets(5, 10, 5, 10));
scene.setRoot(root); scene.setRoot(root);
} }
} }

View File

@ -0,0 +1,11 @@
/* 显示滚动条 */
.show-scrollbars .scroll-pane {
-fx-hbar-policy: as-needed;
-fx-vbar-policy: as-needed;
}
/* 不显示滚动条 */
.hide-scrollbars .scroll-pane {
-fx-hbar-policy: never;
-fx-vbar-policy: never;
}