diff --git a/pom.xml b/pom.xml index e6fde4c234c128e741e5388077ca21058ab26a38..c57ff05a3c0c65e39d7775fc25f40eff731c3288 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,18 @@ gson 2.10.1 - + + + org.slf4j + slf4j-api + 1.7.32 + + + + ch.qos.logback + logback-classic + 1.2.9 + diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index c4adc8ce20db19558fe2c33f73133f05e009b16a..3aa0d42fd932bac5623e16f43b0a3a51cfedfd92 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -4,6 +4,7 @@ module org.jcnc.jnotepad { // requires cn.hutool.json; // requires cn.hutool.core; requires com.google.gson; + requires org.slf4j; exports org.jcnc.jnotepad; exports org.jcnc.jnotepad.tool; exports org.jcnc.jnotepad.Interface; @@ -13,4 +14,5 @@ module org.jcnc.jnotepad { exports org.jcnc.jnotepad.view.manager; exports org.jcnc.jnotepad.constants; exports org.jcnc.jnotepad.ui; + exports org.jcnc.jnotepad.exception; } \ No newline at end of file diff --git a/src/main/java/org/jcnc/jnotepad/Interface/ConfigInterface.java b/src/main/java/org/jcnc/jnotepad/Interface/ConfigInterface.java index fda55fcddc9004b92ae7781eab6d53e8dd2d6f2b..008eb2d7e13aa1bcf73f69603ae3ec1312a6cbe9 100644 --- a/src/main/java/org/jcnc/jnotepad/Interface/ConfigInterface.java +++ b/src/main/java/org/jcnc/jnotepad/Interface/ConfigInterface.java @@ -2,6 +2,9 @@ package org.jcnc.jnotepad.Interface; import java.util.Properties; +/** + * @author 许轲 + */ public interface ConfigInterface { void showErrorAlert(); Properties readPropertiesFromFile(); diff --git a/src/main/java/org/jcnc/jnotepad/Interface/ControllerInterface.java b/src/main/java/org/jcnc/jnotepad/Interface/ControllerInterface.java index db1f719ec882414fb43d1dc784f5224c220de00c..3914ac4b024d721bfc639585dfa669e28eea890b 100644 --- a/src/main/java/org/jcnc/jnotepad/Interface/ControllerInterface.java +++ b/src/main/java/org/jcnc/jnotepad/Interface/ControllerInterface.java @@ -9,6 +9,7 @@ import java.util.List; /** * 控制器接口类 + * @author 许轲 */ public interface ControllerInterface { diff --git a/src/main/java/org/jcnc/jnotepad/Interface/ShortcutKeyInterface.java b/src/main/java/org/jcnc/jnotepad/Interface/ShortcutKeyInterface.java index 2f8c52eb87632ab0eae2d856852408f316cef91d..36c7122b1f5819a606ff3041ffe141ce81e30981 100644 --- a/src/main/java/org/jcnc/jnotepad/Interface/ShortcutKeyInterface.java +++ b/src/main/java/org/jcnc/jnotepad/Interface/ShortcutKeyInterface.java @@ -2,9 +2,8 @@ package org.jcnc.jnotepad.Interface; /** * @author 一个大转盘 - * @date 2023/8/18 */ public interface ShortcutKeyInterface { - public void createShortcutKeyByConfig(); + void createShortcutKeyByConfig(); } diff --git a/src/main/java/org/jcnc/jnotepad/LunchApp.java b/src/main/java/org/jcnc/jnotepad/LunchApp.java index ddd7b78d5c756fc877b7c18ec4dc6e1d9eb2cd36..4d0285831ed14486facbbee39d670569e345bbbd 100644 --- a/src/main/java/org/jcnc/jnotepad/LunchApp.java +++ b/src/main/java/org/jcnc/jnotepad/LunchApp.java @@ -7,7 +7,7 @@ import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.layout.Pane; import javafx.stage.Stage; -import org.jcnc.jnotepad.constants.Constants; +import org.jcnc.jnotepad.constants.AppConstants; import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.init.Config; import org.jcnc.jnotepad.ui.LineNumberTextArea; @@ -20,9 +20,16 @@ import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +/** + * 启动程序 + * + * @author 许轲 + */ public class LunchApp extends Application { - private static final ExecutorService threadPool = Executors.newCachedThreadPool(); - public static boolean isRelevance = true; + /** + * 线程池 + */ + private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); Controller controller = Controller.getInstance(); Scene scene; @@ -42,9 +49,9 @@ public class LunchApp extends Application { Pane root = new Pane(); - double width = Constants.SCREEN_WIDTH; - double length = Constants.SCREEN_LENGTH; - String icon = Constants.APP_ICON; + double width = AppConstants.SCREEN_WIDTH; + double length = AppConstants.SCREEN_LENGTH; + String icon = AppConstants.APP_ICON; scene = new Scene(root, width, length); Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet()); @@ -65,11 +72,10 @@ public class LunchApp extends Application { view.initTabPane(); view.initShortcutKey(); - if (isRelevance) { - + if (controller.isRelevance()) { // 使用线程池加载关联文件并创建文本区域 List rawParameters = getParameters().getRaw(); - threadPool.execute(() -> { + THREAD_POOL.execute(() -> { LineNumberTextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters); if (!Objects.isNull(textArea)) { Platform.runLater(() -> controller.updateUiWithNewTextArea(textArea)); @@ -82,7 +88,7 @@ public class LunchApp extends Application { @Override public void stop() { // 关闭线程池 - threadPool.shutdownNow(); + THREAD_POOL.shutdownNow(); } public static void main(String[] args) { diff --git a/src/main/java/org/jcnc/jnotepad/constants/AppConstants.java b/src/main/java/org/jcnc/jnotepad/constants/AppConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..3650c4b267cf607df5e2469ed0f07f5b1132e304 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/constants/AppConstants.java @@ -0,0 +1,34 @@ +package org.jcnc.jnotepad.constants; + +/** + * 应用常量 + * @author 许轲 + */ + +public class AppConstants { + private AppConstants() { + } + + /** + * 初始宽度 + */ + public static final double SCREEN_WIDTH = 800; + /** + * 初始高度 + */ + public static final double SCREEN_LENGTH = 600; + /** + * 应用名 + */ + public static final String APP_NAME = "JNotepad"; + /** + * logo地址 + */ + public static final String APP_ICON = "/img/icon.png"; + + /** + * 配置文件名 + */ + public static final String PROPERTY_FILE_NAME = "project.txt"; + +} diff --git a/src/main/java/org/jcnc/jnotepad/constants/Constants.java b/src/main/java/org/jcnc/jnotepad/constants/Constants.java deleted file mode 100644 index a2185ce64074a54353b36287dacc2ef57cb6e1c6..0000000000000000000000000000000000000000 --- a/src/main/java/org/jcnc/jnotepad/constants/Constants.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.jcnc.jnotepad.constants; - -/** - * Constants持有所有共享信息的全局变量 - */ - -public class Constants { - public static final double SCREEN_WIDTH = 800; //宽度 - public static final double SCREEN_LENGTH = 600; //高度 - public static final String APP_NAME = "JNotepad"; //名字 - public static final String APP_ICON = "/img/icon.png"; //logo地址 - - //配置文件 - public static final String PROPERTY_FILE_NAME = "project.txt"; //配置文件名字 - -} diff --git a/src/main/java/org/jcnc/jnotepad/constants/PathConstants.java b/src/main/java/org/jcnc/jnotepad/constants/PathConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..e666e75cdeed67e6a986d668541515f87496fefd --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/constants/PathConstants.java @@ -0,0 +1,17 @@ +package org.jcnc.jnotepad.constants; + +/** + * 路径常量 + * + * @author gewuyou + */ +public class PathConstants { + private PathConstants() { + } + + /** + * 快捷键配置文件路径 + * todo:这里这个配置可以通过配置文件读取 + */ + public static final String SHORTCUT_KEY_CONFIGURATION_FILE_PATH = "/config/shortcutKey.json"; +} diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/LineFeed.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/LineFeed.java index bf8e9ab3ba21d67da34b918939b1cd64b3df6e00..8c5af377b4c2abbdb96658db6e84b817d75fd9c3 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/LineFeed.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/LineFeed.java @@ -8,6 +8,7 @@ import org.jcnc.jnotepad.ui.LineNumberTextArea; * 换行程序。 *

* 用于在文本区域中插入一个换行符。 + * @author 许轲 */ public class LineFeed implements EventHandler { private final LineNumberTextArea textArea; diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java index 7482cd3a78fde78758c5662229b79087cc81d77f..8e79a0179134214d81556d4e02e9a441801330ef 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java @@ -3,16 +3,17 @@ package org.jcnc.jnotepad.controller.event.handler; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Tab; -import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.controller.manager.Controller; +import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.view.manager.ViewManager; -import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane; /** * 新建文件事件的事件处理程序。 *

* 当用户选择新建文件时候,将创建一个新的文本编辑区,并在Tab页中显示。 + * + * @author 许轲 */ public class NewFile implements EventHandler { /** @@ -28,24 +29,22 @@ public class NewFile implements EventHandler { // 创建一个新的文本编辑区 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(); // 创建一个新的Tab页 - Tab tab = new Tab("新建文本 " + ++ViewManager.tabIndex); + Tab tab = new Tab("新建文本 " + viewManager.selfIncreaseAndGetTabIndex()); tab.setContent(textArea); - // 将Tab页添加到TabPane中 - tabPane.getTabs().add(tab); + viewManager.getTabPane().getTabs().add(tab); // 将新建的Tab页设置为选中状态 - tabPane.getSelectionModel().select(tab); + viewManager.getTabPane().getSelectionModel().select(tab); // 更新状态标签 controller.updateStatusLabel(textArea); diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java index 635a34a02f300d1a5c4d0da2650d0f497a686de6..ddb64b86ad9285dbc8422fea567c888078f1b064 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java @@ -3,19 +3,19 @@ package org.jcnc.jnotepad.controller.event.handler; import javafx.concurrent.Task; import javafx.event.ActionEvent; import javafx.event.EventHandler; - import javafx.stage.FileChooser; -import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.controller.manager.Controller; +import org.jcnc.jnotepad.ui.LineNumberTextArea; +import org.jcnc.jnotepad.view.manager.ViewManager; import java.io.File; -import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane; /** * 打开文件的事件处理程序。 *

* 当用户选择打开文件时,将创建一个新的文本编辑区,并在Tab页中显示。 + * @author 许轲 */ public class OpenFile implements EventHandler { /** @@ -25,6 +25,8 @@ public class OpenFile implements EventHandler { */ @Override public void handle(ActionEvent event) { + // 获取ViewManager的实例 + ViewManager viewManager = ViewManager.getInstance(); // 获取控制器 Controller controller = Controller.getInstance(); // 创建文件选择器 @@ -39,7 +41,7 @@ public class OpenFile implements EventHandler { // 调用控制器的getText方法,读取文件内容 controller.getText(file); // 更新编码标签 - controller.upDateEncodingLabel(((LineNumberTextArea) tabPane.getSelectionModel().getSelectedItem().getContent()).getMainTextArea().getText()); + controller.upDateEncodingLabel(((LineNumberTextArea) viewManager.getTabPane().getSelectionModel().getSelectedItem().getContent()).getMainTextArea().getText()); return null; } }; diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/SaveAsFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/SaveAsFile.java index 3299bf6812557f519ba2cd9aab2545a03847ace7..b2c1536f9d68d925ae9359b28718283fcb107d8d 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/SaveAsFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/SaveAsFile.java @@ -4,14 +4,15 @@ import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Tab; import javafx.stage.FileChooser; +import org.jcnc.jnotepad.tool.LogUtil; import org.jcnc.jnotepad.ui.LineNumberTextArea; +import org.jcnc.jnotepad.view.manager.ViewManager; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane; /** * 保存文件事件处理器。 @@ -20,6 +21,8 @@ import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane; * 会弹出一个保存文件对话框,用户选择保存位置和文件名后, * 将当前文本编辑区的内容保存到指定文件中, * 并更新Tab页上的文件名和UserData。 + * + * @author 许轲 */ public class SaveAsFile implements EventHandler { /** @@ -29,23 +32,25 @@ public class SaveAsFile implements EventHandler { */ @Override public void handle(ActionEvent event) { - Tab selectedTab = tabPane.getSelectionModel().getSelectedItem(); + ViewManager viewManager = ViewManager.getInstance(); + Tab selectedTab = viewManager.getTabPane().getSelectionModel().getSelectedItem(); if (selectedTab != null) { FileChooser fileChooser = new FileChooser(); fileChooser.setInitialFileName(selectedTab.getText()); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt")); File file = fileChooser.showSaveDialog(null); if (file != null) { - try { - BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + try ( + BufferedWriter writer = new BufferedWriter(new FileWriter(file)) + ) { LineNumberTextArea textArea = (LineNumberTextArea) selectedTab.getContent(); // 获取当前Tab页的文本编辑区 String text = textArea.getMainTextArea().getText(); writer.write(text); // 写入文件内容 writer.flush(); - writer.close(); selectedTab.setText(file.getName()); // 更新Tab页标签上的文件名 selectedTab.setUserData(file); // 将文件对象保存到Tab页的UserData中 } catch (IOException ignored) { + LogUtil.info("已忽略IO异常!",this.getClass()); } } } diff --git a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java index 099e8be09db2ce0fd73ac85b11e0289685224e99..a7b14174a9f780fdcd854777d49d2e92bae77b39 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java +++ b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java @@ -6,12 +6,12 @@ import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Tab; import org.jcnc.jnotepad.Interface.ControllerInterface; -import org.jcnc.jnotepad.LunchApp; import org.jcnc.jnotepad.controller.event.handler.LineFeed; 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.LogUtil; import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.view.manager.ViewManager; @@ -26,8 +26,15 @@ import java.util.List; * @author 许轲 */ public class Controller implements ControllerInterface { - private static final Controller INSTANCE = new Controller(); + /** + * 是否关联 + */ + private boolean isRelevance = true; + + public boolean isRelevance() { + return isRelevance; + } private Controller() { } @@ -95,15 +102,15 @@ public class Controller implements ControllerInterface { @Override public void autoSave(LineNumberTextArea textArea) { textArea.getMainTextArea().textProperty().addListener((observable, oldValue, newValue) -> { - Tab tab = ViewManager.tabPane.getSelectionModel().getSelectedItem(); + Tab tab = ViewManager.getInstance().getTabPane().getSelectionModel().getSelectedItem(); if (tab != null) { File file = (File) tab.getUserData(); if (file != null) { try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { writer.write(newValue); - System.out.println("正在自动保存---"); + LogUtil.info("正在自动保存---",this.getClass()); } catch (IOException ignored) { - + LogUtil.info("已忽略IO异常!",this.getClass()); } } } @@ -131,7 +138,7 @@ public class Controller implements ControllerInterface { int row = getRow(caretPosition, textArea.getMainTextArea().getText()); int column = getColumn(caretPosition, textArea.getMainTextArea().getText()); int length = textArea.getMainTextArea().getLength(); - ViewManager.statusLabel.setText("行: " + row + " \t列: " + column + " \t字数: " + length); + ViewManager.getInstance().getStatusLabel().setText("行: " + row + " \t列: " + column + " \t字数: " + length); } /** @@ -143,7 +150,7 @@ public class Controller implements ControllerInterface { public void openAssociatedFile(String filePath) { File file = new File(filePath); if (file.exists() && file.isFile()) { - LunchApp.isRelevance = false; + isRelevance = false; openFile(file); } } @@ -155,6 +162,7 @@ public class Controller implements ControllerInterface { */ @Override public void getText(File file) { + ViewManager viewManager = ViewManager.getInstance(); LineNumberTextArea textArea = createNewTextArea(); try (BufferedReader reader = new BufferedReader(new FileReader(file))) { StringBuilder textBuilder = new StringBuilder(); @@ -169,15 +177,15 @@ public class Controller implements ControllerInterface { Tab tab = createNewTab(file.getName(), textArea); tab.setUserData(file); - ViewManager.tabPane.getTabs().add(tab); + viewManager.getTabPane().getTabs().add(tab); // ViewManager.tabPane.sets - ViewManager.tabPane.getSelectionModel().select(tab); + viewManager.getTabPane().getSelectionModel().select(tab); updateStatusLabel(textArea); autoSave(textArea); }); } catch (IOException ignored) { - + LogUtil.info("已忽略IO异常!",this.getClass()); } } @@ -189,7 +197,7 @@ public class Controller implements ControllerInterface { @Override public void upDateEncodingLabel(String text) { String encoding = EncodingDetector.detectEncoding(text); - ViewManager.enCodingLabel.setText("\t编码: " + encoding); + ViewManager.getInstance().getEnCodingLabel().setText("\t编码: " + encoding); } /** @@ -230,7 +238,7 @@ public class Controller implements ControllerInterface { @Override public void initTabPane() { Controller controller = new Controller(); - ViewManager.tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { + ViewManager.getInstance().getTabPane().getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { LineNumberTextArea textArea; if (newTab != null) { // 获取新选定的标签页并关联的文本区域 @@ -253,16 +261,17 @@ public class Controller implements ControllerInterface { /** * 更新UI和标签页 * - * @param textArea 文本域 + * @param textArea 文本域 * @apiNote * @since 2023/8/20 12:40 */ @Override public void updateUiWithNewTextArea(LineNumberTextArea textArea) { - Tab tab = new Tab("新建文件 " + (++ViewManager.tabIndex)); + ViewManager viewManager = ViewManager.getInstance(); + Tab tab = new Tab("新建文件 " + viewManager.selfIncreaseAndGetTabIndex()); tab.setContent(textArea); - ViewManager.tabPane.getTabs().add(tab); - ViewManager.tabPane.getSelectionModel().select(tab); + viewManager.getTabPane().getTabs().add(tab); + viewManager.getTabPane().getSelectionModel().select(tab); updateStatusLabel(textArea); } diff --git a/src/main/java/org/jcnc/jnotepad/controller/manager/ShortcutKey.java b/src/main/java/org/jcnc/jnotepad/controller/manager/ShortcutKey.java index d6a7874c20b55ddb5f5d75c09f350e152b4e3281..3228404932f9b367a9a0c793a40c5c5a0f6cefe2 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/manager/ShortcutKey.java +++ b/src/main/java/org/jcnc/jnotepad/controller/manager/ShortcutKey.java @@ -6,44 +6,45 @@ import com.google.gson.reflect.TypeToken; import javafx.scene.control.MenuItem; import javafx.scene.input.KeyCombination; import org.jcnc.jnotepad.Interface.ShortcutKeyInterface; -import org.jcnc.jnotepad.tool.FileUtil; +import org.jcnc.jnotepad.tool.LogUtil; import org.jcnc.jnotepad.view.manager.ViewManager; import java.io.*; -import java.net.URL; import java.util.Map; import java.util.Objects; +import static org.jcnc.jnotepad.constants.PathConstants.SHORTCUT_KEY_CONFIGURATION_FILE_PATH; + /** - * @author 一个大转盘 - * @date 2023/8/18 + * @author 一个大转盘
*/ public class ShortcutKey implements ShortcutKeyInterface { @Override public void createShortcutKeyByConfig() { - String rootPath =System.getProperty("user.dir"); + String rootPath = System.getProperty("user.dir"); // 构建JSON文件路径 - String jsonFilePath = rootPath +"/config/shortcutKey.json"; - InputStream inputStream = getClass().getResourceAsStream("/config/shortcutKey.json"); + String jsonFilePath = rootPath + SHORTCUT_KEY_CONFIGURATION_FILE_PATH; + InputStream inputStream = getClass().getResourceAsStream(SHORTCUT_KEY_CONFIGURATION_FILE_PATH); StringBuffer jsonData = new StringBuffer(); File file = new File(jsonFilePath); - if(file.exists()){ + if (file.exists()) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) { String line; while ((line = reader.readLine()) != null) { jsonData.append(line); } } catch (IOException e) { - e.printStackTrace(); + LogUtil.error(e.getMessage(),e,this.getClass()); } - }else { + } else { + // todo new InputStreamReader(inputStream) 实参 'inputStream' 可能为null try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = reader.readLine()) != null) { jsonData.append(line); } } catch (IOException e) { - e.printStackTrace(); + LogUtil.error(e.getMessage(),e,this.getClass()); } } @@ -54,16 +55,13 @@ public class ShortcutKey implements ShortcutKeyInterface { }.getType()); for (Map.Entry stringObjectEntry : shortcutKeyConfig.entrySet()) { // 保证json的key必须和变量名一致 - MenuItem menuItem = ViewManager.itemMap.get(stringObjectEntry.getKey()); + MenuItem menuItem = ViewManager.getInstance().getItemMap().get(stringObjectEntry.getKey()); String shortKeyValue = stringObjectEntry.getValue(); - if ("".equals(shortKeyValue) || Objects.isNull(menuItem)) { continue; } // 动态添加快捷键 menuItem.setAccelerator(KeyCombination.keyCombination(shortKeyValue)); } - - } } diff --git a/src/main/java/org/jcnc/jnotepad/exception/AppException.java b/src/main/java/org/jcnc/jnotepad/exception/AppException.java new file mode 100644 index 0000000000000000000000000000000000000000..af597831786e511d6f6e0d9b48314208a612235c --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/exception/AppException.java @@ -0,0 +1,14 @@ +package org.jcnc.jnotepad.exception; +import org.jcnc.jnotepad.tool.LogUtil; + +/** + * 应用异常类 + * + * @author gewuyou + */ +public class AppException extends RuntimeException{ + public AppException(String message) { + super(message); + LogUtil.error(message,this.getClass()); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/init/Config.java b/src/main/java/org/jcnc/jnotepad/init/Config.java index 8eb85bb38fe0c7ae9ad1fc679febf24bd6140d9d..fa5f3168499513d02c9cdd859c3f7642e81c9a9a 100644 --- a/src/main/java/org/jcnc/jnotepad/init/Config.java +++ b/src/main/java/org/jcnc/jnotepad/init/Config.java @@ -6,8 +6,11 @@ import org.jcnc.jnotepad.Interface.ConfigInterface; import java.io.*; import java.util.Properties; -import static org.jcnc.jnotepad.constants.Constants.PROPERTY_FILE_NAME; +import static org.jcnc.jnotepad.constants.AppConstants.PROPERTY_FILE_NAME; +/** + * @author 许轲 + */ public class Config implements ConfigInterface { public Properties readPropertiesFromFile() { Properties properties = new Properties(); diff --git a/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java b/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java index 0bdd00cc8adc1197ac8d364ba22b39db1e702114..938af8ae4d7616380f6a83df3348185c5292c8e8 100644 --- a/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java +++ b/src/main/java/org/jcnc/jnotepad/tool/EncodingDetector.java @@ -8,8 +8,12 @@ import java.nio.charset.StandardCharsets; /** * 编码检测工具类 + * + * @author 许轲 */ public class EncodingDetector { + private EncodingDetector() { + } /** * 检测 TextArea 中的文本编码 @@ -19,7 +23,6 @@ public class EncodingDetector { */ public static String detectEncoding(LineNumberTextArea textArea) { String text = textArea.getMainTextArea().getText(); - return detectEncoding(text); } @@ -33,7 +36,7 @@ public class EncodingDetector { // 尝试常见的编码 for (Charset charset : commonCharsets()) { if (isValidEncoding(text, charset)) { - System.out.println("编码监测结果:" + isValidEncoding(text, charset)); + LogUtil.info("编码监测结果:" + isValidEncoding(text, charset), EncodingDetector.class); return charset.name(); } } diff --git a/src/main/java/org/jcnc/jnotepad/tool/FileUtil.java b/src/main/java/org/jcnc/jnotepad/tool/FileUtil.java index 752350f0f8eb2af5e9ae0de65a6fe7d2e6bbc097..9156a90c2eaacbb4fe1c91a768fc4a5faf46a049 100644 --- a/src/main/java/org/jcnc/jnotepad/tool/FileUtil.java +++ b/src/main/java/org/jcnc/jnotepad/tool/FileUtil.java @@ -5,32 +5,32 @@ import java.nio.charset.StandardCharsets; /** * @author 一个大转盘 - * @date 2023/8/18 */ public class FileUtil { + private FileUtil() { + } /** * 把一个文件中的内容读取成一个String字符串 - * @date 2023/8/18 0:54 - * @param jsonFile + * + * @param jsonFile json文件 * @return String */ - public static String getJsonStr(File jsonFile){ - String jsonStr = ""; - try { - FileReader fileReader = new FileReader(jsonFile); - Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8); - int ch = 0; + public static String getJsonStr(File jsonFile) { + String jsonStr; + try ( + Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8) + ) { + + int ch; StringBuffer sb = new StringBuffer(); while ((ch = reader.read()) != -1) { sb.append((char) ch); } - fileReader.close(); - reader.close(); jsonStr = sb.toString(); return jsonStr; } catch (IOException e) { - e.printStackTrace(); + LogUtil.error(e.getMessage(),e,FileUtil.class); return null; } } diff --git a/src/main/java/org/jcnc/jnotepad/tool/LogUtil.java b/src/main/java/org/jcnc/jnotepad/tool/LogUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..163985524fed071de6d5066640892a01e0b57d36 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/tool/LogUtil.java @@ -0,0 +1,79 @@ +package org.jcnc.jnotepad.tool; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 日志工具类 + * + * @author gewuyou + */ +public class LogUtil { + private LogUtil() { + } + + /** + * 日志信息打印 + * + * @param message 日志信息 + * @param currentClass 所要记录的类 + * + * @apiNote 传入当前需要记录的类,方便知晓是哪个位置记录的日志 + */ + public static void info(String message, Class currentClass) { + Logger logger = LoggerFactory.getLogger(currentClass); + logger.info(message); + } + /** + * 日志排错信息打印 + * + * @param message 日志信息 + * @param currentClass 所要记录的类 + * + * @apiNote 传入当前需要记录的类,方便知晓是哪个位置记录的日志 + */ + + public static void debug(String message, Class currentClass) { + Logger logger = LoggerFactory.getLogger(currentClass); + logger.debug(message); + } + /** + * 日志警告信息打印 + * + * @param message 日志信息 + * @param currentClass 所要记录的类 + * + * @apiNote 传入当前需要记录的类,方便知晓是哪个位置记录的日志 + */ + public static void warn(String message, Class currentClass) { + Logger logger = LoggerFactory.getLogger(currentClass); + logger.warn(message); + } + /** + * 日志错误信息打印 + * + * @param message 日志信息 + * @param currentClass 所要记录的类 + * + * @apiNote 传入当前需要记录的类,方便知晓是哪个位置记录的日志 + */ + public static void error(String message, Class currentClass) { + Logger logger = LoggerFactory.getLogger(currentClass); + logger.error(message); + } + /** + * 日志错误信息打印 + * + * @param message 日志信息 + * @param throwable 抛出的异常 + * @param currentClass 所要记录的类 + * + * @apiNote 这个方法用来弥补当抛出异常或手动抛出异常时,无法捕捉到所抛异常 + */ + + public static void error(String message, Throwable throwable, Class currentClass) { + Logger logger = LoggerFactory.getLogger(currentClass); + logger.error(message, throwable); + } +} + diff --git a/src/main/java/org/jcnc/jnotepad/ui/LineNumberTextArea.java b/src/main/java/org/jcnc/jnotepad/ui/LineNumberTextArea.java index b911ba136eea9da1d38ba2b99816557384345f1b..34a1a9754d758d7d99aab0f7fc84573f7e2d26bd 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/LineNumberTextArea.java +++ b/src/main/java/org/jcnc/jnotepad/ui/LineNumberTextArea.java @@ -4,13 +4,14 @@ import javafx.beans.property.StringProperty; import javafx.scene.control.TextArea; import javafx.scene.layout.BorderPane; +/** + * @author 许轲 + */ public class LineNumberTextArea extends BorderPane { - - private final TextArea mainTextArea; private final TextArea lineNumberArea; - static final int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999, + static final int[] SIZE_TABLE = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE}; private static final int MIN_LINE_NUMBER_WIDTH = 30; @@ -27,15 +28,10 @@ public class LineNumberTextArea extends BorderPane { mainTextArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberArea()); // 当主要文本区域的垂直滚动位置发生变化时,使行号文本区域的滚动位置保持一致 - 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); setLeft(lineNumberArea); } @@ -43,13 +39,13 @@ public class LineNumberTextArea extends BorderPane { private void updateLineNumberWidth() { int numOfLines = mainTextArea.getParagraphs().size(); int count = 1; - for (int i = 0; i < sizeTable.length; i++) { - if (numOfLines <= sizeTable[i]) { + for (int i = 0; i < SIZE_TABLE.length; i++) { + if (numOfLines <= SIZE_TABLE[i]) { count = i + 1; break; } } - //单数字宽度10像素,4为padding=左3+右1 + // 单数字宽度10像素,4为padding=左3+右1 int actualWidth = Math.max(count * 10 + 11, MIN_LINE_NUMBER_WIDTH); if (actualWidth != lineNumberArea.getWidth()) { lineNumberArea.setPrefWidth(actualWidth); diff --git a/src/main/java/org/jcnc/jnotepad/view/init/View.java b/src/main/java/org/jcnc/jnotepad/view/init/View.java index 4e99f634dece14296cdd9a49465116c827e53e29..258b0b2ca26cfce6d9adddacc74e40d623ee675e 100644 --- a/src/main/java/org/jcnc/jnotepad/view/init/View.java +++ b/src/main/java/org/jcnc/jnotepad/view/init/View.java @@ -2,28 +2,32 @@ package org.jcnc.jnotepad.view.init; import javafx.event.ActionEvent; import javafx.event.EventHandler; -import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.ShortcutKey; +import org.jcnc.jnotepad.ui.LineNumberTextArea; +import org.jcnc.jnotepad.view.manager.ViewManager; import java.util.HashMap; import java.util.Map; -import static org.jcnc.jnotepad.view.manager.ViewManager.*; - +/** + * @author 许轲 + */ public class View { - private static Map itmeMap = new HashMap<>(); + // todo 这个东西干嘛的,都没用过 + private static Map itmeMap = new HashMap<>(); public void initItem() { + ViewManager viewManager = ViewManager.getInstance(); // 初始化菜单项的事件处理器 EventHandler newFileEventHandler = Controller.getInstance().getNewFileEventHandler(new LineNumberTextArea()); - newItem.setOnAction(newFileEventHandler); + viewManager.getNewItem().setOnAction(newFileEventHandler); EventHandler openFileEventHandler = Controller.getInstance().getOpenFileEventHandler(); - openItem.setOnAction(openFileEventHandler); + viewManager.getOpenItem().setOnAction(openFileEventHandler); EventHandler saveAsFileEventHandler = Controller.getInstance().getSaveAsFileEventHandler(); - saveAsItem.setOnAction(saveAsFileEventHandler); - lineFeedItem.setOnAction(Controller.getInstance().getLineFeedEventHandler(new LineNumberTextArea())); + viewManager.getSaveAsItem().setOnAction(saveAsFileEventHandler); + viewManager.getLineFeedItem().setOnAction(Controller.getInstance().getLineFeedEventHandler(new LineNumberTextArea())); } public void initTabPane() { @@ -31,7 +35,7 @@ public class View { } // 初始化快捷键 - public void initShortcutKey(){ + public void initShortcutKey() { new ShortcutKey().createShortcutKeyByConfig(); } diff --git a/src/main/java/org/jcnc/jnotepad/view/manager/ViewManager.java b/src/main/java/org/jcnc/jnotepad/view/manager/ViewManager.java index d479541c70f6d891fce43d5178cefcdcc8620c9d..0842809d35930dc47901206446b76d99ee166576 100644 --- a/src/main/java/org/jcnc/jnotepad/view/manager/ViewManager.java +++ b/src/main/java/org/jcnc/jnotepad/view/manager/ViewManager.java @@ -5,42 +5,159 @@ import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; +import org.jcnc.jnotepad.exception.AppException; import java.util.HashMap; import java.util.Map; -import java.util.Objects; + /** * 该类管理记事本应用程序的视图组件。 + * + * @author 许轲 */ public class ViewManager { - public static Label enCodingLabel; // 显示文本编码 + /** + * 显示文本编码 + */ + private Label enCodingLabel; // 显示文本编码 - public static int tabIndex = 0; + private int tabIndex = 0; - public static Boolean Line = true; + private Boolean line = true; + /// 菜单栏组件 + /** + * 菜单栏 + */ + private MenuBar menuBar; + /** + * 文件菜单 + */ + private Menu fileMenu; + /** + * 插件菜单 + */ + private Menu setMenu; + /** + * 插件菜单 + */ + private Menu pluginMenu; - // 菜单栏组件 - public static MenuBar menuBar; //菜单栏 - public static Menu fileMenu, setMenu, pluginMenu; //文件菜单//设置菜单//插件菜单 菜单 - public static MenuItem newItem, openItem, saveAsItem, addItem, countItem; //新建/打开/保存/保存至//增加//查看 菜单按钮 + /// 菜单按钮 - public static CheckMenuItem lineFeedItem; //自动换行点击菜单按钮 - // 主界面布局 - public static BorderPane root; //主布局 + /** + * 新建 + */ + private MenuItem newItem; + /** + * 打开 + */ + private MenuItem openItem; + /** + * 保存 + */ + private MenuItem saveAsItem; + /** + * 增加 + */ + private MenuItem addItem; + /** + * 查看 + */ + private MenuItem countItem; + private CheckMenuItem lineFeedItem; // 自动换行点击菜单按钮 + // 主界面布局 + private BorderPane root; // 主布局 // 多个标签页 - public static TabPane tabPane; //标签页栏 + private TabPane tabPane; // 标签页栏 // 状态栏 - public static Label statusLabel; + private Label statusLabel; private static ViewManager instance = null; - public static Map itemMap = new HashMap<>(); + private Map itemMap = new HashMap<>(); + + + public Label getEnCodingLabel() { + return enCodingLabel; + } + /** + * 自增并获取标签页索引 + * + * + * @return int 标签页索引 + * @apiNote ++tabIndex + */ + + public int selfIncreaseAndGetTabIndex() { + return ++tabIndex; + } + + public Boolean getLine() { + return line; + } + + public MenuBar getMenuBar() { + return menuBar; + } + + public Menu getFileMenu() { + return fileMenu; + } + + public Menu getSetMenu() { + return setMenu; + } + + public Menu getPluginMenu() { + return pluginMenu; + } + + public MenuItem getNewItem() { + return newItem; + } + + public MenuItem getOpenItem() { + return openItem; + } + + public MenuItem getSaveAsItem() { + return saveAsItem; + } + + public MenuItem getAddItem() { + return addItem; + } + + public MenuItem getCountItem() { + return countItem; + } + + public CheckMenuItem getLineFeedItem() { + return lineFeedItem; + } + + public BorderPane getRoot() { + return root; + } + + public TabPane getTabPane() { + return tabPane; + } + + public Label getStatusLabel() { + return statusLabel; + } + + public Map getItemMap() { + return itemMap; + } + /** * 获取ViewManager的实例。如果实例不存在,则创建一个新实例。 @@ -49,13 +166,20 @@ public class ViewManager { * @return ViewManager的实例。 */ public static ViewManager getInstance(Scene scene) { - if (instance == null) { instance = new ViewManager(scene); } return instance; } + public static ViewManager getInstance() { + if (instance != null) { + return instance; + } else { + throw new AppException("ViewManager实例未初始化!"); + } + } + /** * 构造函数。设置场景和根布局。 * @@ -63,10 +187,7 @@ public class ViewManager { */ private ViewManager(Scene scene) { root = new BorderPane(); - - scene.setRoot(root); - } /** @@ -78,7 +199,7 @@ public class ViewManager { // 创建菜单栏并添加菜单项 menuBar = new MenuBar(); - //文件菜单 + // 文件菜单 fileMenu = new Menu("文件"); newItem = new MenuItem("新建"); @@ -92,7 +213,7 @@ public class ViewManager { fileMenu.getItems().addAll(newItem, openItem, saveAsItem); - //设置菜单 + // 设置菜单 setMenu = new Menu("设置"); lineFeedItem = new CheckMenuItem("自动换行"); @@ -101,7 +222,7 @@ public class ViewManager { setMenu.getItems().addAll(lineFeedItem); - //插件菜单 + // 插件菜单 pluginMenu = new Menu("插件"); addItem = new MenuItem("增加插件"); itemMap.put("addItem", addItem); @@ -111,7 +232,7 @@ public class ViewManager { pluginMenu.getItems().addAll(addItem, countItem); - //菜单栏 + // 菜单栏 menuBar.getMenus().addAll(fileMenu, setMenu, pluginMenu); // 创建主界面布局 @@ -131,8 +252,5 @@ public class ViewManager { BorderPane.setMargin(statusBox, new Insets(5, 10, 5, 10)); scene.setRoot(root); - - - } } diff --git a/src/main/resources/img/icon.svg b/src/main/resources/img/icon.svg index 6d9d5340a238f7548898a8a249ae454542e057b4..794655025eece2abeb583e0a285c3bc38bade7ca 100644 --- a/src/main/resources/img/icon.svg +++ b/src/main/resources/img/icon.svg @@ -1,7 +1,8 @@ -