diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 482b8a0702f7daa4d4a6047bac2fb5045517e406..52561f67c8e011b83fad1f7b7fcaa7827e6fb61b 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -2,4 +2,7 @@ module org.jcnc.jnotepad { requires javafx.controls; exports org.jcnc.jnotepad; + exports org.jcnc.jnotepad.controller; + exports org.jcnc.jnotepad.tool; + exports org.jcnc.jnotepad.Interface; } \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/Constants.java b/src/main/java/org/jcnc/jnotepad/Constants.java index 5ed90790daa76f5f9705ee072bb7065e609e3135..facf66bb771763b5b585ce71484ff9ee3a43b7ce 100644 --- a/src/main/java/org/jcnc/jnotepad/Constants.java +++ b/src/main/java/org/jcnc/jnotepad/Constants.java @@ -5,7 +5,6 @@ package org.jcnc.jnotepad; */ public class Constants { - public static final double SCREEN_WIDTH = 800; //宽度 public static final double SCREEN_LENGTH = 600; //高度 public static final String APP_NAME = "JNotepad"; //名字 diff --git a/src/main/java/org/jcnc/jnotepad/Interface/ControllerInterface.java b/src/main/java/org/jcnc/jnotepad/Interface/ControllerInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..bb0da77c3bea88551f6d2658c2e533d1ead22739 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/Interface/ControllerInterface.java @@ -0,0 +1,39 @@ +package org.jcnc.jnotepad.Interface; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.control.TextArea; + +import java.io.File; +import java.util.List; + +public interface ControllerInterface { + + TextArea openAssociatedFileAndCreateTextArea(List rawParameters); + + EventHandler getLineFeedEventHandler(TextArea textArea); + + EventHandler getNewFileEventHandler(TextArea textArea); + + EventHandler getOpenFileEventHandler(); + + void autoSave(TextArea textArea); + + EventHandler getSaveFileEventHandler(); + + EventHandler getSaveAsFileEventHandler(); + + void saveAsFile(); + + void updateStatusLabel(TextArea textArea); + + void openAssociatedFile(String filePath); + + void getText(File file); + + void upDateEncodingLabel(String text); + + int getRow(int caretPosition, String text); + + int getColumn(int caretPosition, String text); +} diff --git a/src/main/java/org/jcnc/jnotepad/LunchApp.java b/src/main/java/org/jcnc/jnotepad/LunchApp.java index 146ef7c1286b42b9b23c475552660e4cbb54eafe..6fd636cc48ee7656cf18efc6dbd85f1a3302c188 100644 --- a/src/main/java/org/jcnc/jnotepad/LunchApp.java +++ b/src/main/java/org/jcnc/jnotepad/LunchApp.java @@ -16,10 +16,15 @@ import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import static org.jcnc.jnotepad.view.View.initItem; +import static org.jcnc.jnotepad.view.View.initTabPane; + public class LunchApp extends Application { private static final ExecutorService threadPool = Executors.newCachedThreadPool(); public static boolean isRelevance = true; + Controller controller = new Controller(); + @Override public void start(Stage primaryStage) { Pane root = new Pane(); @@ -42,14 +47,14 @@ public class LunchApp extends Application { viewManager.initScreen(scene); // 初始化菜单项和标签栏 - View.initItem(); - View.initTabPane(); + initItem(); + initTabPane(); if (isRelevance) { // 使用线程池加载关联文件并创建文本区域 List rawParameters = getParameters().getRaw(); threadPool.execute(() -> { - TextArea textArea = Controller.openAssociatedFileAndCreateTextArea(rawParameters); + TextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters); Platform.runLater(() -> updateUIWithNewTextArea(textArea)); }); } @@ -60,7 +65,7 @@ public class LunchApp extends Application { tab.setContent(textArea); ViewManager.tabPane.getTabs().add(tab); ViewManager.tabPane.getSelectionModel().select(tab); - Controller.updateStatusLabel(textArea); + controller.updateStatusLabel(textArea); } @Override diff --git a/src/main/java/org/jcnc/jnotepad/ViewManager.java b/src/main/java/org/jcnc/jnotepad/ViewManager.java index 248bbfa94daa50875aad076da7277d5aca7cca23..3995049cf9ae24a4ef7dd279ef181c368f9f82a1 100644 --- a/src/main/java/org/jcnc/jnotepad/ViewManager.java +++ b/src/main/java/org/jcnc/jnotepad/ViewManager.java @@ -5,7 +5,6 @@ import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; -import org.jcnc.jnotepad.controller.Controller; /** * 该类管理记事本应用程序的视图组件。 diff --git a/src/main/java/org/jcnc/jnotepad/controller/Controller.java b/src/main/java/org/jcnc/jnotepad/controller/Controller.java index 525ca873a8ebdcb9a6a02605ca36554682cae381..c20bb0052993a54e0908499efed4fb67fed48534 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/Controller.java +++ b/src/main/java/org/jcnc/jnotepad/controller/Controller.java @@ -7,160 +7,74 @@ import javafx.event.EventHandler; import javafx.scene.control.Tab; import javafx.scene.control.TextArea; import javafx.stage.FileChooser; +import org.jcnc.jnotepad.Interface.ControllerInterface; import org.jcnc.jnotepad.LunchApp; import java.io.*; -import java.nio.charset.StandardCharsets; import java.util.List; import static org.jcnc.jnotepad.ViewManager.*; -import static org.jcnc.jnotepad.controller.EncodingDetector.detectEncoding; - -/** - * 控制器类负责处理与用户界面的交互,并实现相关事件处理逻辑。 - */ -public class Controller { - - /** - * 打开关联文件并创建一个文本编辑区。 - * - * @param rawParameters 文件路径参数的列表 - * @return 创建的文本编辑区 - */ - public static TextArea openAssociatedFileAndCreateTextArea(List rawParameters) { +import static org.jcnc.jnotepad.tool.EncodingDetector.detectEncoding; + +public class Controller implements ControllerInterface { + + @Override + public TextArea openAssociatedFileAndCreateTextArea(List rawParameters) { if (!rawParameters.isEmpty()) { String filePath = rawParameters.get(0); - openAssociatedFile(filePath); //// 调用关联文件打开方法 + openAssociatedFile(filePath); } - TextArea textArea = new TextArea(); // 创建新的文本编辑区 + TextArea textArea = createNewTextArea(); + configureTextArea(textArea); - // 自动换行 - textArea.setWrapText(true); - upDateEncodingLabel(textArea.getText()); // 更新文本编码信息 - updateStatusLabel(textArea); - - // 添加文本变更监听器 - textArea.textProperty().addListener((observable, oldValue, newValue) -> { - // 更新状态栏信息 - updateStatusLabel(textArea); - }); - autoSave(textArea); // 自动保存 return textArea; } - public static class LineFeedEventHandler implements EventHandler { - private final TextArea textArea; - private boolean wrapText = true; - - public LineFeedEventHandler(TextArea textArea) { - this.textArea = textArea; - } - - @Override - public void handle(ActionEvent event) { - wrapText = !wrapText; // 切换自动换行状态 - textArea.setWrapText(wrapText); - } + @Override + public EventHandler getLineFeedEventHandler(TextArea textArea) { + return new LineFeedEventHandler(textArea); } - - // 新建文件事件处理器 - public static class NewFileEventHandler implements EventHandler { - @Override - public void handle(ActionEvent event) { - TextArea textArea = new TextArea(); // 创建新的文本编辑区 - Tab tab = new Tab("新建文本 " + ++tabIndex); // 创建新的Tab页 - tab.setContent(textArea); - tabPane.getTabs().add(tab); - tabPane.getSelectionModel().select(tab); - updateStatusLabel(textArea); - // 更新编码信息 - upDateEncodingLabel(textArea.getText()); // 更新文本编码信息 - } + @Override + public EventHandler getNewFileEventHandler(TextArea textArea) { + return new NewFileEventHandler(); } - // 打开文件事件处理器 - public static class OpenFileEventHandler implements EventHandler { - @Override - public void handle(ActionEvent event) { - FileChooser fileChooser = new FileChooser(); - File file = fileChooser.showOpenDialog(null); - if (file != null) { - Task openFileTask = new Task<>() { - @Override - protected Void call() { - getText(file); - upDateEncodingLabel(((TextArea) tabPane.getSelectionModel().getSelectedItem().getContent()).getText()); - return null; - } - }; - - openFileTask.setOnSucceeded(e -> { - // 在需要时处理成功 - }); - - openFileTask.setOnFailed(e -> { - // 在需要时处理失败 - }); - - Thread thread = new Thread(openFileTask); - thread.start(); - } - } + @Override + public EventHandler getOpenFileEventHandler() { + return new OpenFileEventHandler(); } - // 自动保存方法 - public static void autoSave(TextArea textArea) { + @Override + public void autoSave(TextArea textArea) { textArea.textProperty().addListener((observable, oldValue, newValue) -> { Tab tab = tabPane.getSelectionModel().getSelectedItem(); if (tab != null) { - File f = (File) tab.getUserData(); - if (f != null) { - try (BufferedWriter writer = new BufferedWriter(new FileWriter(f))) { + File file = (File) tab.getUserData(); + if (file != null) { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { writer.write(newValue); } catch (IOException ignored) { - // 适当地处理异常 + } } } }); } - // 保存文件事件处理器 - public static class SaveFileEventHandler implements EventHandler { - @Override - public void handle(ActionEvent event) { - Tab selectedTab = tabPane.getSelectionModel().getSelectedItem(); - if (selectedTab != null) { - File file = (File) selectedTab.getUserData(); - if (file == null) { - saveAsFile(); - } else { - try { - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)); - TextArea textArea = (TextArea) selectedTab.getContent(); - String text = textArea.getText(); - writer.write(text); - writer.flush(); - writer.close(); - } catch (IOException ignored) { - } - } - } - } + @Override + public EventHandler getSaveFileEventHandler() { + return new SaveFileEventHandler(); } - // 另存为文件事件处理器 - public static class SaveAsFileEventHandler implements EventHandler { - @Override - public void handle(ActionEvent event) { - saveAsFile(); - } + @Override + public EventHandler getSaveAsFileEventHandler() { + return new SaveAsFileEventHandler(); } - // 另存为文件方法 - public static void saveAsFile() { + @Override + public void saveAsFile() { Tab selectedTab = tabPane.getSelectionModel().getSelectedItem(); if (selectedTab != null) { FileChooser fileChooser = new FileChooser(); @@ -168,45 +82,32 @@ public class Controller { fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt")); File file = fileChooser.showSaveDialog(null); if (file != null) { - try { - BufferedWriter writer = new BufferedWriter(new FileWriter(file)); - TextArea textArea = (TextArea) selectedTab.getContent(); // 获取当前Tab页的文本编辑区 - autoSave(textArea);// 自动保存 - String text = textArea.getText(); - writer.write(text); // 写入文件内容 - writer.flush(); - writer.close(); - selectedTab.setText(file.getName()); // 更新Tab页标签上的文件名 - selectedTab.setUserData(file); // 将文件对象保存到Tab页的UserData中 - } catch (IOException ignored) { - } + saveFile(); } } } - // 更新状态栏标签信息 - public static void updateStatusLabel(TextArea textArea) { + @Override + public void updateStatusLabel(TextArea textArea) { int caretPosition = textArea.getCaretPosition(); int row = getRow(caretPosition, textArea.getText()); int column = getColumn(caretPosition, textArea.getText()); int length = textArea.getLength(); statusLabel.setText("行: " + row + " \t列: " + column + " \t字数: " + length); - System.out.println(" 正在监测字数"); } - // 关联文件打开 - public static void openAssociatedFile(String filePath) { - // 根据给定的文件路径打开关联文件 + @Override + public void openAssociatedFile(String filePath) { File file = new File(filePath); if (file.exists() && file.isFile()) { LunchApp.isRelevance = false; - getText(file);// 调用读取文件方法 - upDateEncodingLabel(((TextArea) tabPane.getSelectionModel().getSelectedItem().getContent()).getText()); // 更新文本编码信息 + openFile(file); } } - public static void getText(File file) { - TextArea textArea = new TextArea(); + @Override + public void getText(File file) { + TextArea textArea = createNewTextArea(); try (BufferedReader reader = new BufferedReader(new FileReader(file))) { StringBuilder textBuilder = new StringBuilder(); String line; @@ -218,48 +119,26 @@ public class Controller { Platform.runLater(() -> { textArea.setText(text); - Tab tab = new Tab(file.getName()); - tab.setContent(textArea); - tab.setUserData(file); - + Tab tab = createNewTab(file.getName(), textArea); tabPane.getTabs().add(tab); tabPane.getSelectionModel().select(tab); updateStatusLabel(textArea); - autoSave(textArea); // 在更新界面后调用 autoSave + autoSave(textArea); }); } catch (IOException ignored) { - // 适当地处理异常 + } } - // 更新文本编码标签信息 - public static void upDateEncodingLabel(String text) { + @Override + public void upDateEncodingLabel(String text) { String encoding = detectEncoding(text); enCodingLabel.setText("\t编码: " + encoding); } -/* // 判断编码是否有效 - public static boolean isEncodingValid(String text, Charset encoding) { - byte[] bytes = text.getBytes(encoding); - String decodedText = new String(bytes, encoding); - return text.equals(decodedText); - }*/ - -/* // 检测文本编码 - public static String detectEncoding(String text) { - Charset[] possibleEncodings = {StandardCharsets.UTF_8, StandardCharsets.ISO_8859_1, StandardCharsets.UTF_16}; - for (Charset encoding : possibleEncodings) { - if (isEncodingValid(text, Charset.forName(String.valueOf(encoding)))) { - System.out.println("正在检测编码"); - return encoding.displayName(); - } - } - return "未知"; - }*/ - - // 获取光标所在行数 - public static int getRow(int caretPosition, String text) { + @Override + public int getRow(int caretPosition, String text) { caretPosition = Math.min(caretPosition, text.length()); String substring = text.substring(0, caretPosition); int count = 0; @@ -268,12 +147,54 @@ public class Controller { count++; } } - return count + 1; // Add 1 for the current line + return count + 1; } - - // 获取光标所在列数 - public static int getColumn(int caretPosition, String text) { + @Override + public int getColumn(int caretPosition, String text) { return caretPosition - text.lastIndexOf("\n", caretPosition - 1); } + + private void configureTextArea(TextArea textArea) { + textArea.setWrapText(true); + upDateEncodingLabel(textArea.getText()); + updateStatusLabel(textArea); + + textArea.textProperty().addListener((observable, oldValue, newValue) -> updateStatusLabel(textArea)); + + autoSave(textArea); + } + + private TextArea createNewTextArea() { + return new TextArea(); + } + + private Tab createNewTab(String tabName, TextArea textArea) { + Tab tab = new Tab(tabName); + tab.setContent(textArea); + tab.setUserData(null); + return tab; + } + + private Task createOpenFileTask(File file) { + TextArea textArea = createNewTextArea(); + return new Task<>() { + @Override + protected Void call() { + getText(file); + upDateEncodingLabel(textArea.getText()); + return null; + } + }; + } + + private void openFile(File file) { + Task openFileTask = createOpenFileTask(file); + Thread thread = new Thread(openFileTask); + thread.start(); + } + + private void saveFile() { + new SaveFileEventHandler(); + } } diff --git a/src/main/java/org/jcnc/jnotepad/controller/EncodingDetector.java b/src/main/java/org/jcnc/jnotepad/controller/EncodingDetector.java deleted file mode 100644 index 83bb86cc312eda0a933848844747eb68224316de..0000000000000000000000000000000000000000 --- a/src/main/java/org/jcnc/jnotepad/controller/EncodingDetector.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.jcnc.jnotepad.controller; - -import javafx.scene.control.TextArea; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; - -public class EncodingDetector { - - public static String detectEncoding(TextArea textArea) { - String text = textArea.getText(); - - return detectEncoding(text); - } - - public static String detectEncoding(String text) { - // 尝试常见的编码 - for (Charset charset : commonCharsets()) { - if (isValidEncoding(text, charset)) { - System.out.println(isValidEncoding(text, charset)); - return charset.name(); - } - } - - return "UNKNOWN"; - } - - private static Charset[] commonCharsets() { - return new Charset[] { - StandardCharsets.UTF_8, - StandardCharsets.UTF_16, - StandardCharsets.UTF_16LE, - StandardCharsets.UTF_16BE, - StandardCharsets.ISO_8859_1 - }; - } - - private static boolean isValidEncoding(String text, Charset encoding) { - // 尝试使用指定编码解码 - byte[] bytes = text.getBytes(encoding); - String decoded = new String(bytes, encoding); - - - // 解码后的文本相同表示编码有效 - return text.equals(decoded); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/controller/LineFeedEventHandler.java b/src/main/java/org/jcnc/jnotepad/controller/LineFeedEventHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..c14bd9791b9446d10dd60307c154950df2485afd --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/controller/LineFeedEventHandler.java @@ -0,0 +1,18 @@ +package org.jcnc.jnotepad.controller; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.control.TextArea; + +public class LineFeedEventHandler implements EventHandler { + private final TextArea textArea; + + public LineFeedEventHandler(TextArea textArea) { + this.textArea = textArea; + } + @Override + public void handle(ActionEvent event) { + String text = textArea.getText(); + textArea.setText(text + "\n"); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/controller/NewFileEventHandler.java b/src/main/java/org/jcnc/jnotepad/controller/NewFileEventHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..48083f7a9b9eef6310ce5bb72f9ecc5edb8a0646 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/controller/NewFileEventHandler.java @@ -0,0 +1,24 @@ +package org.jcnc.jnotepad.controller; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.control.Tab; +import javafx.scene.control.TextArea; +import org.jcnc.jnotepad.ViewManager; + +import static org.jcnc.jnotepad.ViewManager.tabPane; + +public class NewFileEventHandler implements EventHandler { + @Override + public void handle(ActionEvent event) { + Controller controller = new Controller(); + TextArea textArea = new TextArea(); // 创建新的文本编辑区 + Tab tab = new Tab("新建文本 " + ++ViewManager.tabIndex); // 创建新的Tab页 + tab.setContent(textArea); + tabPane.getTabs().add(tab); + tabPane.getSelectionModel().select(tab); + controller.updateStatusLabel(textArea); + // 更新编码信息 + controller.upDateEncodingLabel(textArea.getText()); // 更新文本编码信息 + } +} \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/controller/OpenFileEventHandler.java b/src/main/java/org/jcnc/jnotepad/controller/OpenFileEventHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..68e3aabf56cdb547f10998234fb1b3893d2ac384 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/controller/OpenFileEventHandler.java @@ -0,0 +1,42 @@ +package org.jcnc.jnotepad.controller; + +import javafx.concurrent.Task; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.control.TextArea; +import javafx.stage.FileChooser; + +import java.io.File; + +import static org.jcnc.jnotepad.ViewManager.tabPane; + +// 打开文件事件处理器 +public class OpenFileEventHandler implements EventHandler { + @Override + public void handle(ActionEvent event) { + Controller controller = new Controller(); + FileChooser fileChooser = new FileChooser(); + File file = fileChooser.showOpenDialog(null); + if (file != null) { + Task openFileTask = new Task<>() { + @Override + protected Void call() { + controller.getText(file); + controller.upDateEncodingLabel(((TextArea) tabPane.getSelectionModel().getSelectedItem().getContent()).getText()); + return null; + } + }; + + openFileTask.setOnSucceeded(e -> { + // 在需要时处理成功 + }); + + openFileTask.setOnFailed(e -> { + // 在需要时处理失败 + }); + + Thread thread = new Thread(openFileTask); + thread.start(); + } + } +} diff --git a/src/main/java/org/jcnc/jnotepad/controller/SaveAsFileEventHandler.java b/src/main/java/org/jcnc/jnotepad/controller/SaveAsFileEventHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..3ec07723014c9b70633f926bf7f05be6adcaf555 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/controller/SaveAsFileEventHandler.java @@ -0,0 +1,42 @@ +package org.jcnc.jnotepad.controller; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.control.Tab; +import javafx.scene.control.TextArea; +import javafx.stage.FileChooser; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import static org.jcnc.jnotepad.ViewManager.tabPane; + +public class SaveAsFileEventHandler implements EventHandler { + @Override + public void handle(ActionEvent event) { + Controller controller = new Controller(); + Tab selectedTab = tabPane.getSelectionModel().getSelectedItem(); + if (selectedTab != null) { + FileChooser fileChooser = new FileChooser(); + fileChooser.setInitialFileName("新建文本"); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt")); + File file = fileChooser.showSaveDialog(null); + if (file != null) { + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + TextArea textArea = (TextArea) selectedTab.getContent(); // 获取当前Tab页的文本编辑区 + controller.autoSave(textArea);// 自动保存 + String text = textArea.getText(); + writer.write(text); // 写入文件内容 + writer.flush(); + writer.close(); + selectedTab.setText(file.getName()); // 更新Tab页标签上的文件名 + selectedTab.setUserData(file); // 将文件对象保存到Tab页的UserData中 + } catch (IOException ignored) { + } + } + } + } +} diff --git a/src/main/java/org/jcnc/jnotepad/controller/SaveFileEventHandler.java b/src/main/java/org/jcnc/jnotepad/controller/SaveFileEventHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..af8b25ec9814cbb5d299598d7740ac4f4c0b6810 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/controller/SaveFileEventHandler.java @@ -0,0 +1,36 @@ +package org.jcnc.jnotepad.controller; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.control.Tab; +import javafx.scene.control.TextArea; + +import java.io.*; +import java.nio.charset.StandardCharsets; + +import static org.jcnc.jnotepad.ViewManager.tabPane; + +// 保存文件事件处理器 +public class SaveFileEventHandler implements EventHandler { + @Override + public void handle(ActionEvent event) { + Controller controller = new Controller(); + Tab selectedTab = tabPane.getSelectionModel().getSelectedItem(); + if (selectedTab != null) { + File file = (File) selectedTab.getUserData(); + if (file == null) { + controller.saveAsFile(); + } else { + try { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)); + TextArea textArea = (TextArea) selectedTab.getContent(); + String text = textArea.getText(); + writer.write(text); + writer.flush(); + writer.close(); + } catch (IOException ignored) { + } + } + } + } +} diff --git a/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java b/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..bc6184efc1b9e3b8edac8fcd1b8e2bc60f4a350c --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java @@ -0,0 +1,48 @@ +package org.jcnc.jnotepad.tool; + +import javafx.scene.control.TextArea; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class EncodingDetector { + + public static String detectEncoding(TextArea textArea) { + String text = textArea.getText(); + + return detectEncoding(text); + } + + public static String detectEncoding(String text) { + // 尝试常见的编码 + for (Charset charset : commonCharsets()) { + if (isValidEncoding(text, charset)) { + System.out.println(isValidEncoding(text, charset)); + return charset.name(); + } + } + + return "UNKNOWN"; + } + + private static Charset[] commonCharsets() { + return new Charset[]{ + StandardCharsets.UTF_8, + StandardCharsets.UTF_16, + StandardCharsets.UTF_16LE, + StandardCharsets.UTF_16BE, + StandardCharsets.ISO_8859_1 + }; + } + + private static boolean isValidEncoding(String text, Charset encoding) { + // 尝试使用指定编码解码 + byte[] bytes = text.getBytes(encoding); + String decoded = new String(bytes, encoding); + + + // 解码后的文本相同表示编码有效 + return text.equals(decoded); + } + +} \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/view/View.java b/src/main/java/org/jcnc/jnotepad/view/View.java index 692ca01fb96e77b8def97ef9b5591eabe5a768b7..269e9b9064d686c35fc323fb8289cf6501ddc773 100644 --- a/src/main/java/org/jcnc/jnotepad/view/View.java +++ b/src/main/java/org/jcnc/jnotepad/view/View.java @@ -4,36 +4,38 @@ import javafx.scene.control.TextArea; import org.jcnc.jnotepad.controller.Controller; import static org.jcnc.jnotepad.ViewManager.*; -import static org.jcnc.jnotepad.controller.Controller.upDateEncodingLabel; -import static org.jcnc.jnotepad.controller.Controller.updateStatusLabel; + public class View { public static void initItem() { // 初始化菜单项的事件处理器 - newItem.setOnAction(new Controller.NewFileEventHandler()); - openItem.setOnAction(new Controller.OpenFileEventHandler()); - saveItem.setOnAction(new Controller.SaveFileEventHandler()); - saveAsItem.setOnAction(new Controller.SaveAsFileEventHandler()); - lineFeedItem.setOnAction(new Controller.LineFeedEventHandler(new TextArea())); + newItem.setOnAction(new Controller().getNewFileEventHandler(new TextArea())); + openItem.setOnAction(new Controller().getOpenFileEventHandler()); + saveItem.setOnAction(new Controller().getSaveFileEventHandler()); + saveAsItem.setOnAction(new Controller().getSaveAsFileEventHandler()); + lineFeedItem.setOnAction(new Controller().getLineFeedEventHandler(new TextArea())); } public static void initTabPane() { + Controller controller = new Controller(); + tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { if (newTab != null) { // 获取新选定的标签页并关联的文本区域 TextArea textArea = (TextArea) newTab.getContent(); // 更新状态标签 - updateStatusLabel(textArea); + controller.updateStatusLabel(textArea); // 监听文本光标位置的变化,更新状态标签 - textArea.caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> updateStatusLabel(textArea)); + textArea.caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> controller.updateStatusLabel(textArea)); // 更新编码标签 - upDateEncodingLabel(textArea.getText()); + controller.upDateEncodingLabel(textArea.getText()); } }); } + }