!66 feature-I7XXVS:优化项目doc注释和符合规范

Merge pull request !66 from Luke/feature-I7XXVS
This commit is contained in:
Luke 2023-09-02 04:48:01 +00:00 committed by Gitee
commit 71dfbb76d4
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
53 changed files with 777 additions and 436 deletions

View File

@ -20,9 +20,14 @@ module org.jcnc.jnotepad {
exports org.jcnc.jnotepad.controller.manager;
exports org.jcnc.jnotepad.controller.i18n;
exports org.jcnc.jnotepad.controller.event.handler.tool;
exports org.jcnc.jnotepad.controller.event.handler.menuBar;
exports org.jcnc.jnotepad.controller.event.handler.menubar;
exports org.jcnc.jnotepad.tool;
exports org.jcnc.jnotepad.Interface;
exports org.jcnc.jnotepad.interfaces;
exports org.jcnc.jnotepad.ui.module;
exports org.jcnc.jnotepad.ui.setstage;
exports org.jcnc.jnotepad.root.center.main.center.tab;
exports org.jcnc.jnotepad.root.top.menu;
exports org.jcnc.jnotepad.view.manager;
opens org.jcnc.jnotepad.app.config;
exports org.jcnc.jnotepad.root.center.main.bottom.status;

View File

@ -1,19 +0,0 @@
package org.jcnc.jnotepad.Interface;
import javafx.scene.Node;
public interface BorderPaneAble {
void setTopComponent(Node node);
void setBottomComponent(Node node);
void setLeftComponent(Node node);
void setRightComponent(Node node);
void setCenterComponent(Node node);
}

View File

@ -1,13 +0,0 @@
package org.jcnc.jnotepad.Interface;
import javafx.scene.Node;
import javafx.scene.layout.HBox;
public interface HBoxAble {
void addChild(Node node);
void addChild(Node... nodes);
HBox getHBox();
}

View File

@ -1,12 +0,0 @@
package org.jcnc.jnotepad.Interface;
import javafx.scene.Node;
import javafx.scene.layout.VBox;
public interface VBoxAble {
void addChild(Node node);
void addChild(Node... nodes);
VBox getVBox();
}

View File

@ -1,6 +1,5 @@
package org.jcnc.jnotepad;
import atlantafx.base.theme.PrimerLight;
import javafx.application.Application;
import javafx.scene.Scene;
@ -20,13 +19,18 @@ import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
/**
* 启动程序
* 启动程序类
*
* <p>该类用于启动 JNotepad 记事本应用程序</p>
*
* @author 许轲
*/
public class LunchApp extends Application {
/**
* 线程池
*/
private final ExecutorService threadPool = ThreadPoolManager.getThreadPool();
private static final Pane ROOT = new Pane();
private static final Scene SCENE;
@ -37,14 +41,19 @@ public class LunchApp extends Application {
}
/**
* 线程池
* 应用程序的入口点启动 JavaFX 应用程序
*
* @param args 命令行参数
*/
private final ExecutorService threadPool = ThreadPoolManager.getThreadPool();
public static void main(String[] args) {
launch(args);
}
/**
* 获取当前窗口
*
* @return 当前窗口
*/
public static Window getWindow() {
return SCENE.getWindow();
}
@ -56,25 +65,19 @@ public class LunchApp extends Application {
initUiComponents();
UiResourceBundle.bindStringProperty(primaryStage.titleProperty(), TextConstants.TITLE);
/* // 获取自定义标题栏的实例并添加到BorderPane的顶部
CustomTitleBar customTitleBar = CustomTitleBar.getInstance();
// 使自定义标题栏可拖动
customTitleBar.makeDraggable(primaryStage);*/
// primaryStage.initStyle(StageStyle.UNDECORATED); // 移除默认窗口装饰
primaryStage.setScene(SCENE);
primaryStage.setWidth(SCENE.getWidth());
primaryStage.setHeight(SCENE.getHeight());
primaryStage.setScene(SCENE);
primaryStage.getIcons().add(UiUtil.getIcon());
primaryStage.show();
}
private void initUiComponents() {
//1. 加载语言
// 1. 加载语言
LocalizationController.initLocal();
//2. 加载组件
// 2. 加载组件
ViewManager viewManager = ViewManager.getInstance(SCENE);
viewManager.initScreen(SCENE);
@ -88,5 +91,4 @@ public class LunchApp extends Application {
// 关闭线程池
threadPool.shutdownNow();
}
}

View File

@ -1,11 +1,10 @@
package org.jcnc.jnotepad.constants;
/**
* 应用常量
* 应用常量用于存放应用程序中的常量值
*
* @author 许轲
*/
public class AppConstants {
/**
* 初始宽度
@ -20,6 +19,9 @@ public class AppConstants {
*/
public static final String APP_ICON = "/img/icon.png";
/**
* 私有构造函数防止该类被实例化
*/
private AppConstants() {
}

View File

@ -9,11 +9,6 @@ package org.jcnc.jnotepad.constants;
public class TextConstants {
public static final String TITLE = "title";
/// GlobalConfig文本常量
public static final String SAVE = "SAVE";
public static final String FILE = "FILE";
public static final String NEW = "NEW";

View File

@ -18,6 +18,8 @@ import java.util.List;
/**
* 应用程序配置控制器
*
* <p>该类负责管理应用程序的配置文件包括加载持久化和更新配置信息等操作</p>
*
* @author songdragon
*/
public class AppConfigController {
@ -36,12 +38,17 @@ public class AppConfigController {
loadConfig();
}
/**
* 获取 AppConfigController 的实例
*
* @return AppConfigController 的实例
*/
public static AppConfigController getInstance() {
return INSTANCE;
}
/**
* 加载配置文件内容
* 加载配置文件内容
*/
public void loadConfig() {
createConfigIfNotExists();
@ -59,7 +66,7 @@ public class AppConfigController {
}
/**
* 配置文件持久化
* 配置文件持久化
*/
public void writeAppConfig() {
createConfigIfNotExists();
@ -67,7 +74,7 @@ public class AppConfigController {
}
/**
* appConfig对象持久化到配置文件中
* appConfig 对象持久化到配置文件中
*
* @param appConfig 应用配置对象
*/
@ -83,6 +90,9 @@ public class AppConfigController {
}
}
/**
* 创建配置文件如果不存在
*/
public void createConfigIfNotExists() {
Path configPath = getConfigPath();
if (configPath.toFile().exists()) {
@ -95,6 +105,11 @@ public class AppConfigController {
writeAppConfig(null);
}
/**
* 获取配置文件的路径
*
* @return 配置文件的路径
*/
public Path getConfigPath() {
return Paths.get(getDir(), CONFIG_NAME);
}
@ -104,7 +119,7 @@ public class AppConfigController {
}
/**
* 获取当前配置文件所在目录
* 获取当前配置文件所在目录
*
* @return 所在目录
*/
@ -121,9 +136,9 @@ public class AppConfigController {
}
/**
* 获取自动换行设置默认自动换行
* 获取自动换行设置默认自动换行
*
* @return true, 自动换行false不自动换行
* @return true自动换行false不自动换行
*/
public boolean getAutoLineConfig() {
return getAppConfig().isTextWrap();
@ -134,7 +149,7 @@ public class AppConfigController {
}
/**
* 更新配置文件中的语言设置
* 更新配置文件中的语言设置
*
* @param language 更新后的语言设置
*/
@ -146,10 +161,20 @@ public class AppConfigController {
writeAppConfig();
}
/**
* 获取当前的语言设置
*
* @return 语言设置
*/
public String getLanguage() {
return this.appConfig.getLanguage();
}
/**
* 获取快捷键设置
*
* @return 快捷键设置列表
*/
public List<AppConfig.ShortcutKey> getShortcutKey() {
return this.appConfig.getShortcutKey();
}

View File

@ -1,20 +1,18 @@
package org.jcnc.jnotepad.controller.event.handler.menuBar;
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.constants.TextConstants;
import org.jcnc.jnotepad.root.center.main.bottom.status.JNotepadStatusBox;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTab;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTab;
import org.jcnc.jnotepad.tool.UiUtil;
import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
import org.jcnc.jnotepad.view.manager.ViewManager;
/**
* 新建文件事件的事件处理程序
* <p>
* 当用户选择新建文件时候,将创建一个新的文本编辑区并在Tab页中显示
*
* <p>当用户选择新建文件时将创建一个新的文本编辑区并在Tab页中显示</p>
*
* @author 许轲
*/
@ -30,21 +28,24 @@ public class NewFile implements EventHandler<ActionEvent> {
addNewFileTab();
}
/**
* 添加新的文件标签页
*/
public void addNewFileTab() {
// 创建一个新的文本编辑区
LineNumberTextArea textArea = new LineNumberTextArea();
// TODO: refactor统一TextArea新建绑定监听器入口
ViewManager viewManager = ViewManager.getInstance();
ViewManager viewManager = UiUtil.getViewManager();
// 创建标签页
JNotepadTab jNotepadTab = new JNotepadTab(
MainTab mainTab = new MainTab(
UiResourceBundle.getContent(TextConstants.NEW_FILE)
+ viewManager.selfIncreaseAndGetTabIndex(),
textArea);
// 设置当前标签页与本地文件无关联
jNotepadTab.setRelevance(false);
mainTab.setRelevance(false);
// 将Tab页添加到TabPane中
JNotepadTabPane.getInstance().addNewTab(jNotepadTab);
UiUtil.getJnotepadTabPane().addNewTab(mainTab);
// 更新编码信息
JNotepadStatusBox.getInstance().updateEncodingLabel();
UiUtil.getStatusBox().updateEncodingLabel();
}
}
}

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.controller.event.handler.menuBar;
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.event.ActionEvent;
import org.jcnc.jnotepad.tool.LogUtil;
@ -7,17 +7,24 @@ import org.jcnc.jnotepad.tool.SingletonUtil;
import java.io.File;
/**
* 打开配置文件事件
* 打开配置文件事件处理程序
*
* <p>该事件处理程序用于打开配置文件</p>
*
* @author gewuyou
*/
public class OpenConfig extends OpenFile {
/**
* 处理打开配置文件事件
*
* @param actionEvent 事件对象
*/
@Override
public void handle(ActionEvent actionEvent) {
// 显示文件选择对话框并获取配置文件
File file = SingletonUtil.getAppConfigController().getConfigPath().toFile();
LogUtil.getLogger(this.getClass()).info("已调用打开配置文件功能,{}", file);
LogUtil.getLogger(this.getClass()).info("已调用打开配置文件功能, {}", file);
// 创建打开文件的任务并启动线程执行任务
openFile(file);
}

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.controller.event.handler.menuBar;
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.application.Platform;
import javafx.concurrent.Task;
@ -9,8 +9,8 @@ import javafx.stage.FileChooser;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.constants.TextConstants;
import org.jcnc.jnotepad.manager.ThreadPoolManager;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTab;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTab;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTabPane;
import org.jcnc.jnotepad.tool.EncodingDetector;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.tool.UiUtil;
@ -25,7 +25,6 @@ import java.nio.charset.Charset;
import static org.jcnc.jnotepad.manager.ThreadPoolManager.threadContSelfSubtracting;
/**
* 打开文件的事件处理程序
* <p>
@ -84,9 +83,9 @@ public class OpenFile implements EventHandler<ActionEvent> {
*/
public void openFile(File file) {
// 获取标签页集合
JNotepadTabPane jnotepadTabPane = JNotepadTabPane.getInstance();
MainTabPane jnotepadMainTabPane = UiUtil.getJnotepadTabPane();
// 遍历标签页查找匹配的标签页
for (Tab tab : jnotepadTabPane.getTabs()) {
for (Tab tab : jnotepadMainTabPane.getTabs()) {
// 获取绑定的文件
File tabFile = (File) tab.getUserData();
if (tabFile == null) {
@ -94,7 +93,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
}
if (file.getPath().equals((tabFile).getPath())) {
// 找到匹配的标签页设置为选中状态并跳转
jnotepadTabPane.getSelectionModel().select(tab);
jnotepadMainTabPane.getSelectionModel().select(tab);
return;
}
}
@ -120,11 +119,11 @@ public class OpenFile implements EventHandler<ActionEvent> {
LogUtil.getLogger(this.getClass()).info("已调用读取文件功能");
Platform.runLater(() -> {
textArea.getMainTextArea().setText(text);
JNotepadTab tab = createNewTab(file.getName(), textArea, encoding);
MainTab tab = createNewTab(file.getName(), textArea, encoding);
// 设置当前标签页关联本地文件
tab.setRelevance(true);
tab.setUserData(file);
JNotepadTabPane.getInstance().addNewTab(tab);
UiUtil.getJnotepadTabPane().addNewTab(tab);
});
} catch (IOException ignored) {
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
@ -147,7 +146,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
* @param textArea 文本区域
* @return 新的标签页
*/
private JNotepadTab createNewTab(String tabName, LineNumberTextArea textArea, Charset charset) {
return new JNotepadTab(tabName, textArea, charset);
private MainTab createNewTab(String tabName, LineNumberTextArea textArea, Charset charset) {
return new MainTab(tabName, textArea, charset);
}
}

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.controller.event.handler.menuBar;
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
@ -7,8 +7,7 @@ import javafx.scene.input.KeyCode;
import javafx.stage.FileChooser;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.constants.TextConstants;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTab;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTab;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.tool.UiUtil;
import org.jcnc.jnotepad.ui.dialog.factory.impl.TextFileChooserFactory;
@ -17,7 +16,10 @@ import org.slf4j.Logger;
import java.io.File;
/**
* 重命名文件
* 重命名文件事件处理器
* <p>
* 当用户选择重命名文件时如果当前标签页关联文件则重命名关联文件
* 否则重命名标签页
*
* @author gewuyou
*/
@ -27,7 +29,7 @@ public class RenameFile implements EventHandler<ActionEvent> {
@Override
public void handle(ActionEvent actionEvent) {
// 获取当前标签页
JNotepadTab jnotepadtab = JNotepadTabPane.getInstance().getSelected();
MainTab jnotepadtab = UiUtil.getJnotepadtab();
if (jnotepadtab == null || jnotepadtab.getText().isEmpty()) {
return;
}
@ -43,12 +45,11 @@ public class RenameFile implements EventHandler<ActionEvent> {
}
/**
* 重命名标签页
* 重命名标签页
*
* @param jnotepadtab 标签页组件
* @since 2023/8/31 21:48
*/
private void handleRenameTab(JNotepadTab jnotepadtab) {
private void handleRenameTab(MainTab jnotepadtab) {
TextField textField = new TextField(jnotepadtab.getText());
textField.getStyleClass().add("tab-title-editable");
// 清空标签页名称
@ -82,12 +83,11 @@ public class RenameFile implements EventHandler<ActionEvent> {
}
/**
* 重命名关联文件
* 重命名关联文件
*
* @param jnotepadtab 标签页组件
* @since 2023/8/31 21:47
*/
private void handleRenameRelevanceFile(JNotepadTab jnotepadtab) {
private void handleRenameRelevanceFile(MainTab jnotepadtab) {
// 获取原始文件对象
File file = (File) jnotepadtab.getUserData();
// 获取应用窗口并绑定

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.controller.event.handler.menuBar;
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.event.ActionEvent;
import org.jcnc.jnotepad.tool.LogUtil;

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.controller.event.handler.menuBar;
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
@ -6,9 +6,7 @@ import javafx.stage.FileChooser;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.constants.TextConstants;
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTab;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane;
import org.jcnc.jnotepad.root.top.menu.JNotepadMenuBar;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTab;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.tool.SingletonUtil;
import org.jcnc.jnotepad.tool.UiUtil;
@ -20,7 +18,10 @@ import java.io.File;
import static org.jcnc.jnotepad.controller.config.AppConfigController.CONFIG_NAME;
/**
* 保存文件
* 保存文件事件处理程序
* <p>
* 当用户选择保存文件时如果当前标签页是关联文件则自动保存
* 否则调用另存为方法
*
* @author gewuyou
*/
@ -28,47 +29,48 @@ public class SaveFile implements EventHandler<ActionEvent> {
Logger logger = LogUtil.getLogger(this.getClass());
/**
* 保存文件
* 处理保存文件事件
*
* @param actionEvent 事件对象
* @apiNote
* @apiNote 当用户选择保存文件时如果当前标签页是关联文件则自动保存
* 否则调用另存为方法
*/
@Override
public void handle(ActionEvent actionEvent) {
// 获取当前tab页
JNotepadTab selectedTab = JNotepadTabPane.getInstance().getSelected();
MainTab selectedTab = UiUtil.getJnotepadtab();
if (selectedTab == null) {
return;
}
// 打开的是非关联文件则调用另存为api
// 如果打开的是非关联文件则调用另存为方法
if (!selectedTab.isRelevance()) {
logger.info("当前保存文件为非关联打开文件,调用另存为方法");
saveTab(this.getClass());
} else {
logger.info("当前保存文件为关联打开文件,调用自动保存方法");
// 调用tab保存
// 调用tab保存方法
selectedTab.save();
// 如果该文件是配置文件则刷新快捷键
// 如果该文件是配置文件则刷新快捷键
if (CONFIG_NAME.equals(selectedTab.getText())) {
// 重新加载语言包和快捷键
SingletonUtil.getAppConfigController().loadConfig();
JNotepadMenuBar.getInstance().initShortcutKeys();
UiUtil.getMenuBar().initShortcutKeys();
LocalizationController.initLocal();
logger.info("已刷新语言包!");
logger.info("已刷新快捷键!");
logger.info("已刷新语言包");
logger.info("已刷新快捷键");
}
}
}
/**
* 保存页面方法
* 保存标签页的方法
*
* @param currentClass 调用该方法的类
* @apiNote 将当前选中的标签页进行弹出窗口式的保存
* @apiNote 将当前选中的标签页进行另存为弹出窗口式的保存
* @see LogUtil
*/
protected void saveTab(Class<?> currentClass) {
JNotepadTab selectedTab = JNotepadTabPane.getInstance().getSelected();
MainTab selectedTab = UiUtil.getJnotepadtab();
if (selectedTab == null) {
return;
}
@ -79,11 +81,11 @@ public class SaveFile implements EventHandler<ActionEvent> {
new FileChooser.ExtensionFilter("All types", "*.*"))
.showSaveDialog(UiUtil.getAppWindow());
if (file != null) {
LogUtil.getLogger(currentClass).info("正在保存文件:{}", file.getName());
LogUtil.getLogger(currentClass).info("正在保存文件: {}", file.getName());
selectedTab.save(file);
// 将保存后的文件设置为关联
// 将保存后的文件设置为关联文件
selectedTab.setRelevance(true);
// 更新Tab页标签上的文件名
// 更新标签上的文件名
selectedTab.setText(file.getName());
}
}

View File

@ -4,18 +4,17 @@ import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import org.jcnc.jnotepad.ui.setStage.SetStage;
/**
* 设置按钮事件的事件处理程序
* <p>
* 当用户点击设置的时候,将打开设置窗口
*
* <p>当用户点击设置按钮时将打开设置窗口</p>
*
* @author 许轲
*/
public class SetBtn implements EventHandler<ActionEvent> {
/**
* 打开设置窗口处理事件
* 打开设置窗口处理事件
*
* @param event 事件对象
*/
@ -23,6 +22,4 @@ public class SetBtn implements EventHandler<ActionEvent> {
public void handle(ActionEvent event) {
SetStage.getInstance().openSetStage();
}
}
}

View File

@ -13,8 +13,9 @@ import static org.jcnc.jnotepad.constants.TextConstants.CHINESE;
import static org.jcnc.jnotepad.constants.TextConstants.ENGLISH;
/**
* 本地化控制器<br>
* 注意本地化配置加载应当优先于快捷键配置加载
* 本地化控制器
*
* <p>该类负责处理应用程序的本地化配置包括语言和区域设置</p>
*
* @author gewuyou
* @see LunchApp
@ -42,6 +43,11 @@ public class LocalizationController {
this.appConfigController = SingletonUtil.getAppConfigController();
}
/**
* 获取当前语言配置
*
* @return 当前语言的Locale对象
*/
public static Locale getCurrentLocal() {
return Locale.getDefault();
}
@ -49,7 +55,7 @@ public class LocalizationController {
/**
* 设置当前语言配置
*
* @param locale 当前语言Local对象
* @param locale 当前语言Locale对象
*/
public static void setCurrentLocal(Locale locale) {
if (locale != null && locale.equals(getCurrentLocal())) {

View File

@ -1,15 +1,14 @@
package org.jcnc.jnotepad.controller.manager;
import org.jcnc.jnotepad.Interface.ControllerAble;
import org.jcnc.jnotepad.controller.event.handler.menuBar.NewFile;
import org.jcnc.jnotepad.controller.event.handler.menuBar.OpenFile;
import org.jcnc.jnotepad.controller.event.handler.menubar.NewFile;
import org.jcnc.jnotepad.controller.event.handler.menubar.OpenFile;
import org.jcnc.jnotepad.interfaces.ControllerAble;
import java.io.File;
import java.util.List;
/**
* 控制器类实现ControllerInterface接口用于管理文本编辑器的各种操作和事件处理
* 包括打开关联文件创建文本区域处理行分隔新建文件打开文件自动保存等功能
* 控制器类实现 ControllerAble 接口用于管理文本编辑器的各种操作和事件处理
*
* @author 许轲
*/
@ -20,6 +19,11 @@ public class Controller implements ControllerAble {
private Controller() {
}
/**
* 获取 Controller 的唯一实例
*
* @return Controller 的实例
*/
public static Controller getInstance() {
return INSTANCE;
}

View File

@ -1,17 +1,29 @@
package org.jcnc.jnotepad.exception;
/**
* 应用异常类
* 应用异常类用于处理应用程序中的异常情况
*
* <p>应用异常是一个运行时异常通常用于捕获和处理应用程序中的不可预料的错误和异常情况</p>
*
* @author gewuyou
*/
public class AppException extends RuntimeException {
/**
* 构造一个应用异常对象
*
* @param message 异常消息
*/
public AppException(String message) {
super(message);
}
/**
* 构造一个应用异常对象
*
* @param cause 异常的原因
*/
public AppException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,48 @@
package org.jcnc.jnotepad.interfaces;
import javafx.scene.Node;
/**
* 可设置BorderPane子组件的接口
*
* <p>该接口定义了设置BorderPane的各个子组件的方法</p>
*
* @author luke
*/
public interface BorderPaneAble {
/**
* 设置BorderPane的顶部组件
*
* @param node 要设置为顶部组件的节点
*/
void setTopComponent(Node node);
/**
* 设置BorderPane的底部组件
*
* @param node 要设置为底部组件的节点
*/
void setBottomComponent(Node node);
/**
* 设置BorderPane的左侧组件
*
* @param node 要设置为左侧组件的节点
*/
void setLeftComponent(Node node);
/**
* 设置BorderPane的右侧组件
*
* @param node 要设置为右侧组件的节点
*/
void setRightComponent(Node node);
/**
* 设置BorderPane的中间组件
*
* @param node 要设置为中间组件的节点
*/
void setCenterComponent(Node node);
}

View File

@ -1,27 +1,27 @@
package org.jcnc.jnotepad.Interface;
package org.jcnc.jnotepad.interfaces;
import java.util.List;
/**
* 控制器接口类
*
* <p>该接口定义了控制器的方法用于打开关联文件并创建TextArea</p>
*
* @author 许轲
*/
public interface ControllerAble {
/**
* 打开关联文件并创建 TextArea
* 打开关联文件并创建 TextArea
*
* @param rawParameters 原始参数列表
* @return 创建的 TextArea
*/
void openAssociatedFileAndCreateTextArea(List<String> rawParameters);
/**
* 打开关联文件
* 打开关联文件
*
* @param filePath 文件路径
*/
void openAssociatedFile(String filePath);
}

View File

@ -0,0 +1,34 @@
package org.jcnc.jnotepad.interfaces;
import javafx.scene.Node;
import javafx.scene.layout.HBox;
/**
* 可添加子节点的水平布局接口
*
* <p>该接口定义了添加子节点和获取水平布局的方法</p>
*
* @author luke
*/
public interface HorizontalBoxAble {
/**
* 添加一个或多个子节点到水平布局中
*
* @param node 要添加的子节点
*/
void addChild(Node node);
/**
* 添加一个或多个子节点到水平布局中
*
* @param nodes 要添加的子节点数组
*/
void addChild(Node... nodes);
/**
* 获取水平布局
*
* @return 水平布局
*/
HBox getHorizontalBox();
}

View File

@ -0,0 +1,34 @@
package org.jcnc.jnotepad.interfaces;
import javafx.scene.Node;
import javafx.scene.layout.VBox;
/**
* 可添加子节点的垂直布局接口
*
* <p>该接口定义了添加子节点和获取垂直布局的方法</p>
*
* @author luke
*/
public interface VerticalBoxAble {
/**
* 添加一个或多个子节点到垂直布局中
*
* @param node 要添加的子节点
*/
void addChild(Node node);
/**
* 添加一个或多个子节点到垂直布局中
*
* @param nodes 要添加的子节点数组
*/
void addChild(Node... nodes);
/**
* 获取垂直布局
*
* @return 垂直布局
*/
VBox getVerticalBox();
}

View File

@ -7,8 +7,9 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 线程池管理类<br>
* 项目中所有异步操作建议使用该类进行获取线程执行异步操作
* 线程池管理类
*
* <p>该类用于管理应用程序中的线程池提供了异步操作的执行环境</p>
*
* @author gewuyou
*/
@ -71,12 +72,16 @@ public class ThreadPoolManager {
*
* @apiNote 当你创建任务时务必在最后执行一次该方法
* @see ThreadPoolManager
* @since 2023/8/26 22:00
*/
public static void threadContSelfSubtracting() {
THREAD_COUNT.decrementAndGet();
}
/**
* 获取线程池实例
*
* @return 线程池实例
*/
public static ExecutorService getThreadPool() {
return THREAD_POOL;
}

View File

@ -1,41 +1,54 @@
package org.jcnc.jnotepad.root;
import org.jcnc.jnotepad.root.bottom.RootBottomSideBarVBox;
import org.jcnc.jnotepad.root.bottom.RootBottomSideBarVerticalBox;
import org.jcnc.jnotepad.root.center.main.MainBorderPane;
import org.jcnc.jnotepad.root.left.sidebar.tools.ToolHBox;
import org.jcnc.jnotepad.root.right.RootRightSideBarVBox;
import org.jcnc.jnotepad.root.left.sidebar.tools.ToolHorizontalBox;
import org.jcnc.jnotepad.root.right.RootRightSideBarVerticalBox;
import org.jcnc.jnotepad.root.top.RootTopBorderPane;
import org.jcnc.jnotepad.ui.module.AbstractBorderPane;
/**
* 根舞台下的Root主布局
* RootBorderPane 表示 JNotepad 应用程序的根布局
*
* <p>该布局包含了应用程序的主要组件包括主界面工具栏侧边栏菜单栏等</p>
*
* @author 许轲
*/
public class RootBorderPane extends AbstractBorderPane {
/**
* 单例模式保证只有一个 RootBorderPane 实例
*/
private static final RootBorderPane INSTANCE = new RootBorderPane();
private RootBorderPane() {
initRootBorderPane();
}
/**
* 初始化 RootBorderPane
*
* <p>设置主界面(MainBorderPane)工具栏(ToolHBox)侧边栏(RootRightSideBarVBox)
* 菜单栏(RootTopBorderPane)以及底部边栏(RootBottomSideBarVBox)等主要组件</p>
*/
private void initRootBorderPane() {
// 中间用于显示主界面
setCenterComponent(MainBorderPane.getInstance());
// 主界面的左边工具栏
setLeftComponent(ToolHorizontalBox.getInstance());
// 主界面的右边侧边栏
setRightComponent(RootRightSideBarVerticalBox.getInstance());
// 主界面的上面菜单栏
setTopComponent(RootTopBorderPane.getInstance());
// 主界面的下面底部边栏
setBottomComponent(RootBottomSideBarVerticalBox.getInstance());
}
/**
* 获取 RootBorderPane 的单例实例
*
* @return RootBorderPane 的单例实例
*/
public static RootBorderPane getInstance() {
return INSTANCE;
}
private void initRootBorderPane() {
//中间,用于显示Main主布局
setCenterComponent(MainBorderPane.getInstance());
//主布局的左边
setLeftComponent(ToolHBox.getInstance());
//主布局的右边
setRightComponent(RootRightSideBarVBox.getInstance());
//主布局的上面
setTopComponent(RootTopBorderPane.getInstance());
//主布局的下面
setBottomComponent(RootBottomSideBarVBox.getInstance());
}
}

View File

@ -1,21 +0,0 @@
package org.jcnc.jnotepad.root.bottom;
import org.jcnc.jnotepad.root.center.main.bottom.status.JNotepadStatusBox;
import org.jcnc.jnotepad.ui.module.AbstractVBox;
public class RootBottomSideBarVBox extends AbstractVBox {
private static final RootBottomSideBarVBox INSTANCE = new RootBottomSideBarVBox();
private RootBottomSideBarVBox() {
initSidebarVBox();
}
public static RootBottomSideBarVBox getInstance() {
return INSTANCE;
}
private void initSidebarVBox() {
getChildren().addAll(JNotepadStatusBox.getInstance());
}
}

View File

@ -0,0 +1,33 @@
package org.jcnc.jnotepad.root.bottom;
import org.jcnc.jnotepad.root.center.main.bottom.status.StatusHorizontalBox;
import org.jcnc.jnotepad.ui.module.AbstractVerticalBox;
/**
* 底部根侧边栏垂直布局
*
* <p>该类用于显示底部根侧边栏的垂直布局包括状态栏等</p>
*
* @author luke
*/
public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox();
private RootBottomSideBarVerticalBox() {
initSidebarVerticalBox();
}
private void initSidebarVerticalBox() {
getChildren().addAll(StatusHorizontalBox.getInstance());
}
/**
* 获取 RootBottomSideBarVerticalBox 的唯一实例
*
* @return RootBottomSideBarVerticalBox 的实例
*/
public static RootBottomSideBarVerticalBox getInstance() {
return INSTANCE;
}
}

View File

@ -1,10 +1,12 @@
package org.jcnc.jnotepad.root.center.main;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTabPane;
import org.jcnc.jnotepad.ui.module.AbstractBorderPane;
/**
* MainBorderPane区域,用于显示文本框以及文本框周边
* 主界面边界布局
*
* <p>该类用于显示文本框及其周边组件作为主界面的中心区域</p>
*
* @author 许轲
*/
@ -16,15 +18,17 @@ public class MainBorderPane extends AbstractBorderPane {
initRootBorderPane();
}
private void initRootBorderPane() {
// 文本框
setCenterComponent(MainTabPane.getInstance());
}
/**
* 获取 MainBorderPane 的唯一实例
*
* @return MainBorderPane 的实例
*/
public static MainBorderPane getInstance() {
return INSTANCE;
}
private void initRootBorderPane() {
//文本框
setCenterComponent(JNotepadTabPane.getInstance());
}
}

View File

@ -6,9 +6,9 @@ import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.constants.TextConstants;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTab;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane;
import org.jcnc.jnotepad.ui.module.AbstractHBox;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTab;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTabPane;
import org.jcnc.jnotepad.ui.module.AbstractHorizontalBox;
import java.nio.charset.Charset;
@ -19,9 +19,9 @@ import java.nio.charset.Charset;
*
* @author songdragon
*/
public class JNotepadStatusBox extends AbstractHBox {
public class StatusHorizontalBox extends AbstractHorizontalBox {
private static final JNotepadStatusBox STATUS_BOX = new JNotepadStatusBox();
private static final StatusHorizontalBox STATUS_BOX = new StatusHorizontalBox();
private static final String STATUS_LABEL_FORMAT = "%s : %d \t%s: %d \t%s: %d \t";
/**
* 字数统计及光标
@ -33,18 +33,16 @@ public class JNotepadStatusBox extends AbstractHBox {
private Label encodingLabel;
private JNotepadStatusBox() {
private StatusHorizontalBox() {
initStatusBox();
}
public static JNotepadStatusBox getInstance() {
public static StatusHorizontalBox getInstance() {
return STATUS_BOX;
}
/**
* 初始化状态栏组件
*
* @since 2023/8/27 9:33
*/
public void initStatusBox() {
@ -91,7 +89,7 @@ public class JNotepadStatusBox extends AbstractHBox {
* 更新字数统计
*/
public void updateWordCountStatusLabel() {
JNotepadTabPane instance = JNotepadTabPane.getInstance();
MainTabPane instance = MainTabPane.getInstance();
if (instance.getSelected() == null) {
return;
}
@ -109,12 +107,12 @@ public class JNotepadStatusBox extends AbstractHBox {
* <br>2. 状态栏更新当前选中tab的字符编码
*/
public void updateWhenTabSelected() {
JNotepadTabPane instance = JNotepadTabPane.getInstance();
MainTabPane instance = MainTabPane.getInstance();
if (instance.getSelected() != null) {
updateWordCountStatusLabel();
JNotepadTab jNotepadTab = instance.getSelected();
if (jNotepadTab != null) {
updateEncodingLabel(jNotepadTab.getCharset().name());
MainTab mainTab = instance.getSelected();
if (mainTab != null) {
updateEncodingLabel(mainTab.getCharset().name());
}
}
}

View File

@ -13,7 +13,7 @@ import java.nio.charset.Charset;
*
* @author songdragon
*/
public class JNotepadTab extends Tab {
public class MainTab extends Tab {
private final LineNumberTextArea lineNumberTextArea;
/**
@ -26,15 +26,15 @@ public class JNotepadTab extends Tab {
private boolean isRelevance = false;
private Charset charset = Charset.defaultCharset();
public JNotepadTab(String tabTitle) {
public MainTab(String tabTitle) {
this(tabTitle, new LineNumberTextArea());
}
public JNotepadTab(String tabTitle, LineNumberTextArea textArea) {
public MainTab(String tabTitle, LineNumberTextArea textArea) {
this(tabTitle, textArea, Charset.defaultCharset());
}
public JNotepadTab(String tabTitle, LineNumberTextArea textArea, Charset charset) {
public MainTab(String tabTitle, LineNumberTextArea textArea, Charset charset) {
super(tabTitle);
lineNumberTextArea = textArea;
this.setContent(lineNumberTextArea);

View File

@ -10,15 +10,15 @@ import org.jcnc.jnotepad.tool.SingletonUtil;
*
* @author songdragon
*/
public class JNotepadTabPane extends TabPane {
public class MainTabPane extends TabPane {
private static final JNotepadTabPane TAB_PANE = new JNotepadTabPane();
private static final MainTabPane TAB_PANE = new MainTabPane();
private JNotepadTabPane() {
private MainTabPane() {
initListeners();
}
public static JNotepadTabPane getInstance() {
public static MainTabPane getInstance() {
return TAB_PANE;
}
@ -44,7 +44,7 @@ public class JNotepadTabPane extends TabPane {
*
* @param tab 新标签页
*/
public void addNewTab(JNotepadTab tab) {
public void addNewTab(MainTab tab) {
if (tab == null) {
return;
}
@ -61,8 +61,8 @@ public class JNotepadTabPane extends TabPane {
*
* @return 当前选中的标签页
*/
public JNotepadTab getSelected() {
return (JNotepadTab) this.getSelectionModel().getSelectedItem();
public MainTab getSelected() {
return (MainTab) this.getSelectionModel().getSelectedItem();
}
/**
@ -70,7 +70,7 @@ public class JNotepadTabPane extends TabPane {
* 应用当前菜单上选中的自动换行设置
*/
public void fireTabSelected() {
JNotepadTab selectedTab = getSelected();
MainTab selectedTab = getSelected();
selectedTab.setAutoLine(SingletonUtil.getAppConfigController().getAutoLineConfig());
JNotepadStatusBox.getInstance().updateWhenTabSelected();
}

View File

@ -1,36 +0,0 @@
package org.jcnc.jnotepad.root.left.sidebar.tools;
import javafx.scene.control.Button;
import javafx.scene.control.ToolBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class JNotepadToolBar extends ToolBar {
private static final JNotepadToolBar INSTANCE = new JNotepadToolBar();
Button setButton = new Button();
private JNotepadToolBar() {
// 创建工具栏上的按钮
Image image = new Image("tools.png"); // 替换为你的图片文件路径
ImageView imageView = new ImageView(image);
imageView.setFitWidth(10);
imageView.setFitHeight(10);
imageView.setScaleX(2.5); // 设置水平缩放比例
imageView.setScaleY(2.5); // 设置垂直缩放比例
// 设置缩放比例
setButton.setGraphic(imageView);
// 将按钮添加到工具栏
getItems().addAll(setButton);
}
public static JNotepadToolBar getInstance() {
return INSTANCE;
}
public Button getSetButton() {
return setButton;
}
}

View File

@ -0,0 +1,61 @@
package org.jcnc.jnotepad.root.left.sidebar.tools;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
/**
* JNotepadToolBar JNotepad 应用程序的工具栏类
*
* <p>该类继承自 JavaFX ToolBar 并提供了一个单例实例用于管理工具栏上的按钮</p>
*
* <p>工具栏上的按钮用于执行不同的操作比如设置操作</p>
*
* @author luke
*/
public class ToolBar extends javafx.scene.control.ToolBar {
/**
* 单例模式保证只有一个 JNotepadToolBar实例
*/
private static final ToolBar INSTANCE = new ToolBar();
/**
* 工具栏上的设置按钮
*/
Button setButton = new Button();
private ToolBar() {
// 创建工具栏上的按钮
Image image = new Image("tools.png");
ImageView imageView = new ImageView(image);
imageView.setFitWidth(10);
imageView.setFitHeight(10);
// 设置水平缩放比例
imageView.setScaleX(2.5);
// 设置垂直缩放比例
imageView.setScaleY(2.5);
// 设置缩放比例
setButton.setGraphic(imageView);
// 将按钮添加到工具栏
getItems().addAll(setButton);
}
/**
* 获取 JNotepadToolBar 的单例实例
*
* @return JNotepadToolBar 的单例实例
*/
public static ToolBar getInstance() {
return INSTANCE;
}
/**
* 获取工具栏上的设置按钮
*
* @return 设置按钮
*/
public Button getSetButton() {
return setButton;
}
}

View File

@ -1,21 +0,0 @@
package org.jcnc.jnotepad.root.left.sidebar.tools;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
public class ToolHBox extends HBox {
private static final ToolHBox INSTANCE = new ToolHBox();
private ToolHBox() {
HBox.setHgrow(JNotepadToolBar.getInstance(), Priority.ALWAYS); // 设置子节点水平拉伸
getChildren().add(JNotepadToolBar.getInstance());
}
public static ToolHBox getInstance() {
return INSTANCE;
}
}

View File

@ -0,0 +1,38 @@
package org.jcnc.jnotepad.root.left.sidebar.tools;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import org.jcnc.jnotepad.ui.module.AbstractHorizontalBox;
/**
* ToolHBox JNotepad 应用程序的工具栏水平布局类
*
* <p>该类继承自 JavaFX HBox 用于将工具栏放置在水平布局中</p>
*
* <p>工具栏水平布局中包含一个 JNotepadToolBar 的单例实例并设置其子节点水平拉伸属性以确保工具栏在水平方向上充分占用空间</p>
*
* @author luke
*/
public class ToolHorizontalBox extends AbstractHorizontalBox {
/**
* 单例模式保证只有一个 ToolHBox 实例
*/
private static final ToolHorizontalBox INSTANCE = new ToolHorizontalBox();
private ToolHorizontalBox() {
// 设置子节点水平拉伸
HBox.setHgrow(ToolBar.getInstance(), Priority.ALWAYS);
// JNotepadToolBar 添加为子节点
getChildren().add(ToolBar.getInstance());
}
/**
* 获取 ToolHBox 的单例实例
*
* @return ToolHBox 的单例实例
*/
public static ToolHorizontalBox getInstance() {
return INSTANCE;
}
}

View File

@ -1,20 +0,0 @@
package org.jcnc.jnotepad.root.right;
import org.jcnc.jnotepad.ui.module.AbstractVBox;
public class RootRightSideBarVBox extends AbstractVBox {
private static final RootRightSideBarVBox INSTANCE = new RootRightSideBarVBox();
private RootRightSideBarVBox() {
initSidebarVBox();
}
public static RootRightSideBarVBox getInstance() {
return INSTANCE;
}
private void initSidebarVBox() {
}
}

View File

@ -0,0 +1,23 @@
package org.jcnc.jnotepad.root.right;
import org.jcnc.jnotepad.ui.module.AbstractVerticalBox;
/**
* @author 许轲
*/
public class RootRightSideBarVerticalBox extends AbstractVerticalBox {
private static final RootRightSideBarVerticalBox INSTANCE = new RootRightSideBarVerticalBox();
private RootRightSideBarVerticalBox() {
initSidebarVerticalBox();
}
private void initSidebarVerticalBox() {
}
public static RootRightSideBarVerticalBox getInstance() {
return INSTANCE;
}
}

View File

@ -3,28 +3,39 @@ package org.jcnc.jnotepad.root.top;
import org.jcnc.jnotepad.root.top.menu.JNotepadMenuBar;
import org.jcnc.jnotepad.ui.module.AbstractBorderPane;
/**
* MainBorderPane区域,用于显示文本框以及文本框周边
* RootTopBorderPane 类表示 JNotepad 应用程序的顶部边界面板
*
* <p>该边界面板用于显示文本框以及文本框周边的内容</p>
*
* @author 许轲
*/
public class RootTopBorderPane extends AbstractBorderPane {
/**
* 单例模式保证只有一个 RootTopBorderPane 实例
*/
private static final RootTopBorderPane INSTANCE = new RootTopBorderPane();
private RootTopBorderPane() {
initRootBorderPane();
}
/**
* 初始化 RootTopBorderPane
*
* <p>在顶部区域添加了 JNotepadMenuBar 的单例实例</p>
*/
private void initRootBorderPane() {
// 在顶部区域添加菜单栏
setTopComponent(JNotepadMenuBar.getInstance());
}
/**
* 获取 RootTopBorderPane 的单例实例
*
* @return RootTopBorderPane 的单例实例
*/
public static RootTopBorderPane getInstance() {
return INSTANCE;
}
private void initRootBorderPane() {
//文本框上面
setTopComponent(JNotepadMenuBar.getInstance());
}
}

View File

@ -7,12 +7,12 @@ import javafx.stage.Stage;
import org.jcnc.jnotepad.app.config.AppConfig;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.controller.event.handler.menuBar.*;
import org.jcnc.jnotepad.controller.event.handler.menubar.*;
import org.jcnc.jnotepad.controller.event.handler.tool.SetBtn;
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTab;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane;
import org.jcnc.jnotepad.root.left.sidebar.tools.JNotepadToolBar;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTab;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTabPane;
import org.jcnc.jnotepad.root.left.sidebar.tools.ToolBar;
import org.jcnc.jnotepad.tool.LogUtil;
import org.slf4j.Logger;
@ -35,13 +35,13 @@ public class JNotepadMenuBar extends MenuBar {
/**
* 标签页布局组件封装
*/
JNotepadTabPane jNotepadTabPane = JNotepadTabPane.getInstance();
MainTabPane mainTabPane = MainTabPane.getInstance();
AppConfigController appConfigController = AppConfigController.getInstance();
Logger logger = LogUtil.getLogger(this.getClass());
/**
* 工具栏
*/
JNotepadToolBar toolBar = JNotepadToolBar.getInstance();
ToolBar toolBar = ToolBar.getInstance();
/**
* 获取工具栏中的setButton
*/
@ -125,7 +125,6 @@ public class JNotepadMenuBar extends MenuBar {
* 设置当前语言选中状态
*
* @param language 语言
* @since 2023/8/25 22:49
*/
public void toggleLanguageCheck(String language) {
switch (language) {
@ -290,7 +289,7 @@ public class JNotepadMenuBar extends MenuBar {
// 1. 更新全局配置
AppConfigController.getInstance().setAutoLineConfig(after);
// 2. 对当前tab生效配置
jNotepadTabPane.fireTabSelected();
mainTabPane.fireTabSelected();
});
topItem.selectedProperty().addListener((observableValue, before, after) -> {
// 获取窗口容器
@ -323,7 +322,7 @@ public class JNotepadMenuBar extends MenuBar {
* 根据当前选中tab更新菜单选项
*/
public void updateMenuStatusBySelectedTab() {
JNotepadTab selectedTab = jNotepadTabPane.getSelected();
MainTab selectedTab = mainTabPane.getSelected();
lineFeedItem.selectedProperty().setValue(selectedTab.isAutoLine());
}
}

View File

@ -1,6 +1,5 @@
package org.jcnc.jnotepad.tool;
import com.ibm.icu.text.CharsetDetector;
import com.ibm.icu.text.CharsetMatch;
import org.slf4j.Logger;
@ -10,25 +9,25 @@ import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.Charset;
/**
* 编码检测工具类
*
* <p>该工具类用于检测文本文件的编码类型</p>
*
* @author 许轲
*/
public class EncodingDetector {
/**
* 编码侦测概率阈值50%
* 编码侦测概率阈值50%
*/
public static final int THRESHOLD_CONFIDENCE = 50;
private static final Logger LOG = LogUtil.getLogger(EncodingDetector.class);
private EncodingDetector() {
}
/**
* 检测文本编码
* 检测文本编码
*
* @param file 要检测的文件
* @return 字符串表示的编码如果检测失败则返回 "UNKNOWN"
@ -61,7 +60,7 @@ public class EncodingDetector {
}
/**
* 检测文本编码
* 检测文本编码
*
* @param file 文件
* @return Charset编码
@ -76,4 +75,4 @@ public class EncodingDetector {
return Charset.defaultCharset();
}
}
}
}

View File

@ -10,7 +10,9 @@ import org.jcnc.jnotepad.exception.AppException;
import static com.fasterxml.jackson.core.util.DefaultIndenter.SYS_LF;
/**
* jackson解析器的facade类主要提供objectMapper对象
* Jackson 解析器的外观类主要提供 ObjectMapper 对象
*
* <p>该类用于封装 Jackson 对象映射工具的配置和操作</p>
*
* @author songdragon
*/
@ -29,6 +31,13 @@ public class JsonUtil {
private JsonUtil() {
}
/**
* 将对象转换为 JSON 字符串
*
* @param o 要转换的对象
* @return 对象的 JSON 表示如果转换失败则抛出 AppException 异常
* @throws AppException 如果转换失败
*/
public static String toJsonString(Object o) {
try {
return OBJECT_MAPPER.writeValueAsString(o);

View File

@ -1,11 +1,12 @@
package org.jcnc.jnotepad.tool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 日志工具<br>注意使用该工具的方法时如果需要在JavaFx项目中调用日志请使用Platform.runLater()调用
* 日志工具
*
* <p>注意如果在JavaFX项目中需要调用日志请使用Platform.runLater()来调用</p>
*
* @author gewuyou
*/
@ -14,11 +15,13 @@ public class LogUtil {
}
/**
* 获取日志类
* 获取日志类
*
* @param currentClass 所要记录的类
* @return org.apache.logging.log4j.Logger 日志对象
* @apiNote 传入当前需要记录的类返回记录该类的日志类 <br>建议一个类调用超过两次这个方法时应当将该日志类变成成员对象而不是多次调用
* @return org.slf4j.Logger 日志对象
*
* <p>传入当前需要记录的类返回记录该类的日志类</p>
* <p>建议一个类调用超过两次这个方法时应当将该日志类变成成员对象而不是多次调用</p>
*/
public static Logger getLogger(Class<?> currentClass) {
return LoggerFactory.getLogger(currentClass);

View File

@ -13,11 +13,13 @@ public class PopUpUtil {
}
/**
* 获取错误弹窗
* 获取错误弹窗
*
* @param title 弹窗标题
* @param headerText 头文本
* @param message 信息
*
* <p>用于创建一个错误类型的弹窗显示给用户以指示发生了错误</p>
*/
public static void errorAlert(String title, String headerText, String message) {
Alert alert = new Alert(Alert.AlertType.ERROR);
@ -26,5 +28,4 @@ public class PopUpUtil {
alert.setContentText(message);
alert.showAndWait();
}
}

View File

@ -1,19 +1,18 @@
package org.jcnc.jnotepad.tool;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.controller.manager.Controller;
/**
* 单例工具<br>
* 封装了除UI组件外项目中所有需要的单例组件以减少单例带来的代码的复杂性
* 单例工具
*
* <p>封装了除UI组件外项目中所有需要的单例组件以减少单例带来的代码的复杂性</p>
*
* @author gewuyou
*/
public class SingletonUtil {
/**
* 控制器类
*/
@ -23,6 +22,7 @@ public class SingletonUtil {
* 应用程序配置控制器
*/
private static final AppConfigController APP_CONFIG_CONTROLLER = AppConfigController.getInstance();
/**
* UI资源绑定组件
*/
@ -32,30 +32,27 @@ public class SingletonUtil {
}
/**
* 获取控制器类
* 获取控制器类
*
* @return org.jcnc.jnotepad.controller.manager.Controller
* @since 2023/8/30 13:25
* @return org.jcnc.jnotepad.controller.manager.Controller 控制器对象
*/
public static Controller getController() {
return CONTROLLER;
}
/**
* 获取应用程序配置控制器
* 获取应用程序配置控制器
*
* @return org.jcnc.jnotepad.controller.config.AppConfigController
* @since 2023/8/30 12:48
* @return org.jcnc.jnotepad.controller.config.AppConfigController 应用程序配置控制器对象
*/
public static AppConfigController getAppConfigController() {
return APP_CONFIG_CONTROLLER;
}
/**
* 获取UI资源绑定组件
* 获取UI资源绑定组件
*
* @return org.jcnc.jnotepad.app.i18n.UiResourceBundle
* @since 2023/8/30 12:45
* @return org.jcnc.jnotepad.app.i18n.UiResourceBundle UI资源绑定对象
*/
public static UiResourceBundle getUiResourceBundle() {
return UI_RESOURCE_BUNDLE;

View File

@ -2,43 +2,127 @@ package org.jcnc.jnotepad.tool;
import javafx.scene.image.Image;
import javafx.stage.Window;
import org.jcnc.jnotepad.LunchApp;
import org.jcnc.jnotepad.constants.AppConstants;
import org.jcnc.jnotepad.root.center.main.bottom.status.StatusHorizontalBox;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTab;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTabPane;
import org.jcnc.jnotepad.root.top.menu.JNotepadMenuBar;
import org.jcnc.jnotepad.ui.setstage.SetStage;
import org.jcnc.jnotepad.view.manager.ViewManager;
import java.util.Objects;
/**
* UI工具
*
* <p>封装了项目中所有的UI组件以减少组件单例模式造成的代码复杂性</p>
*
* @author gewuyou
*/
public class UiUtil {
/**
* 标签页布局组件
*/
private static final MainTabPane TAB_PANE = MainTabPane.getInstance();
/**
* 视图管理组件
*/
private static final ViewManager VIEW_MANAGER = ViewManager.getInstance();
/**
* 状态栏组件
*/
private static final StatusHorizontalBox STATUS_BOX = StatusHorizontalBox.getInstance();
/**
* 菜单栏组件
*/
private static final JNotepadMenuBar MENU_BAR = JNotepadMenuBar.getInstance();
/**
* 应用程序图标
*/
private static final Image ICON = new Image(Objects.requireNonNull(UiUtil.class.getResource(AppConstants.APP_ICON)).toString());
/**
* 设置窗口
*/
private static final SetStage SET_STAGE = SetStage.getInstance();
private UiUtil() {
}
/**
* 获取应用程序图标
* 获取设置窗口
*
* @return javafx.scene.image.Image
* @since 2023/8/30 11:03
* @return org.jcnc.jnotepad.ui.setStage.SetStage 设置窗口对象
*/
public static SetStage getSetStage() {
return SET_STAGE;
}
/**
* 获取应用程序图标
*
* @return javafx.scene.image.Image 应用程序图标对象
*/
public static Image getIcon() {
return ICON;
}
/**
* 获取应用窗口
* 获取标签页布局组件
*
* @return javafx.stage.Window
* @return org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane 标签页布局组件对象
* @apiNote JNotepadTabPane.getInstance()
* @see MainTabPane
*/
public static MainTabPane getJnotepadTabPane() {
return TAB_PANE;
}
/**
* 获取标签页组件
*
* @return org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTab 标签页组件对象
* @apiNote JNotepadTabPane.getInstance().getSelected()<br>获取当前选中的标签页
* @see MainTabPane
*/
public static MainTab getJnotepadtab() {
return TAB_PANE.getSelected();
}
/**
* 获取应用窗口
*
* @return javafx.stage.Window 应用窗口对象
* @apiNote JNotepadTabPane.getInstance().getSelected().getTabPane().getScene().getWindow()
* @since 2023/8/29 14:12
*/
public static Window getAppWindow() {
return LunchApp.getWindow();
return TAB_PANE.getSelected().getTabPane().getScene().getWindow();
}
/**
* 获取视图管理组件
*
* @return org.jcnc.jnotepad.view.manager.ViewManager 视图管理组件对象
* @apiNote ViewManager.getInstance()
*/
public static ViewManager getViewManager() {
return VIEW_MANAGER;
}
/**
* 获取状态栏组件
*
* @return org.jcnc.jnotepad.root.center.main.bottom.status.JNotepadStatusBox 状态栏组件对象
*/
public static StatusHorizontalBox getStatusBox() {
return STATUS_BOX;
}
/**
* 获取菜单栏组件
*
* @return org.jcnc.jnotepad.root.top.menu.JNotepadMenuBar 菜单栏组件对象
*/
public static JNotepadMenuBar getMenuBar() {
return MENU_BAR;
}
}

View File

@ -7,27 +7,27 @@ import java.io.File;
/**
* 文件选择对话框工厂
*
* <p>该工厂接口用于创建文件选择对话框包括原始和详细两种类型</p>
*
* @author gewuyou
*/
public interface FileChooserFactory {
/**
* 创建原始文件选择对话框
* 创建原始文件选择对话框
*
* @return javafx.stage.FileChooser
* @since 2023/8/31 20:29
* @return javafx.stage.FileChooser 原始文件选择对话框对象
*/
FileChooser createFileChooser();
/**
* 创建详细的文件选择对话框
* 创建详细的文件选择对话框
*
* @param title 对话框名字
* @param filename 选中的文件名
* @param title 对话框标题
* @param filename 默认选中的文件名
* @param directory 初始目录
* @param extensionFilter 文件类型数组
* @return javafx.stage.FileChooser
* @apiNote
* @since 2023/8/31 20:35
* @param extensionFilter 文件类型过滤器
* @return javafx.stage.FileChooser 详细文件选择对话框对象
* @apiNote 该方法用于创建一个带有标题默认文件名初始目录和文件类型过滤器的详细文件选择对话框
*/
FileChooser createFileChooser(String title, String filename, File directory, FileChooser.ExtensionFilter extensionFilter);
}

View File

@ -27,7 +27,6 @@ public class TextFileChooserFactory implements FileChooserFactory {
* 创建原始文件选择对话框
*
* @return javafx.stage.FileChooser
* @since 2023/8/31 20:29
*/
@Override
public FileChooser createFileChooser() {
@ -43,7 +42,6 @@ public class TextFileChooserFactory implements FileChooserFactory {
* @param extensionFilter 文件类型数组
* @return javafx.stage.FileChooser
* @apiNote
* @since 2023/8/31 20:35
*/
@Override
public FileChooser createFileChooser(String title, String filename, File directory, FileChooser.ExtensionFilter extensionFilter) {

View File

@ -2,8 +2,15 @@ package org.jcnc.jnotepad.ui.module;
import javafx.scene.Node;
import javafx.scene.layout.BorderPane;
import org.jcnc.jnotepad.Interface.BorderPaneAble;
import org.jcnc.jnotepad.interfaces.BorderPaneAble;
/**
* 抽象边界面板类
*
* <p>这个抽象类继承自JavaFX的BorderPane类实现了BorderPaneAble接口用于管理UI组件的布局</p>
*
* @author luke
*/
public abstract class AbstractBorderPane extends BorderPane implements BorderPaneAble {
@Override
@ -30,5 +37,4 @@ public abstract class AbstractBorderPane extends BorderPane implements BorderPan
public void setCenterComponent(Node node) {
setCenter(node);
}
}

View File

@ -2,12 +2,19 @@ package org.jcnc.jnotepad.ui.module;
import javafx.scene.Node;
import javafx.scene.layout.HBox;
import org.jcnc.jnotepad.Interface.HBoxAble;
import org.jcnc.jnotepad.interfaces.HorizontalBoxAble;
public abstract class AbstractHBox extends HBox implements HBoxAble {
/**
* 抽象水平盒子类
*
* <p>这个抽象类继承自JavaFX的HBox类实现了HBoxAble接口用于管理水平排列的UI组件</p>
*
* @author luke
*/
public abstract class AbstractHorizontalBox extends HBox implements HorizontalBoxAble {
private final HBox hBox;
public AbstractHBox() {
public AbstractHorizontalBox() {
hBox = new HBox();
}
@ -22,7 +29,7 @@ public abstract class AbstractHBox extends HBox implements HBoxAble {
}
@Override
public HBox getHBox() {
public HBox getHorizontalBox() {
return hBox;
}
}

View File

@ -2,13 +2,20 @@ package org.jcnc.jnotepad.ui.module;
import javafx.scene.Node;
import javafx.scene.layout.VBox;
import org.jcnc.jnotepad.Interface.VBoxAble;
import org.jcnc.jnotepad.interfaces.VerticalBoxAble;
public abstract class AbstractVBox extends VBox implements VBoxAble {
/**
* 抽象垂直盒子类
*
* <p>这个抽象类继承自JavaFX的VBox类实现了VBoxAble接口用于管理垂直排列的UI组件</p>
*
* @author luke
*/
public abstract class AbstractVerticalBox extends VBox implements VerticalBoxAble {
private final VBox vBox;
public AbstractVBox() {
public AbstractVerticalBox() {
vBox = new VBox();
}
@ -23,7 +30,7 @@ public abstract class AbstractVBox extends VBox implements VBoxAble {
}
@Override
public VBox getVBox() {
public VBox getVerticalBox() {
return vBox;
}
}

View File

@ -3,11 +3,10 @@ package org.jcnc.jnotepad.ui.module;
import javafx.beans.property.StringProperty;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import org.jcnc.jnotepad.root.center.main.bottom.status.JNotepadStatusBox;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTab;
import org.jcnc.jnotepad.root.center.main.center.tab.JNotepadTabPane;
import org.jcnc.jnotepad.root.center.main.center.tab.MainTab;
import org.jcnc.jnotepad.tool.LogUtil;
import org.jcnc.jnotepad.tool.SingletonUtil;
import org.jcnc.jnotepad.tool.UiUtil;
import org.slf4j.Logger;
import java.io.BufferedWriter;
@ -16,13 +15,17 @@ import java.io.FileWriter;
import java.io.IOException;
/**
* @author 许轲
* 行号文本区域
*
* <p>这个类继承自JavaFX的BorderPane类用于显示带有行号的文本区域它包括主要文本区域和行号文本区域</p>
*
* @author luke
*/
public class LineNumberTextArea extends BorderPane {
private static final Logger logger = LogUtil.getLogger(LineNumberTextArea.class);
static final int[] SIZE_TABLE = {9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE};
private static final Logger logger = LogUtil.getLogger(LineNumberTextArea.class);
private static final int MIN_LINE_NUMBER_WIDTH = 30;
private final TextArea mainTextArea;
private final TextArea lineNumberArea;
@ -47,8 +50,6 @@ public class LineNumberTextArea extends BorderPane {
setCenter(mainTextArea);
setLeft(lineNumberArea);
}
private void initListeners() {
@ -60,12 +61,12 @@ public class LineNumberTextArea extends BorderPane {
lineNumberArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberWidth());
this.mainTextArea.caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> JNotepadStatusBox.getInstance().updateWordCountStatusLabel());
this.mainTextArea.caretPositionProperty().addListener((caretObservable, oldPosition, newPosition) -> UiUtil.getStatusBox().updateWordCountStatusLabel());
this.textProperty().addListener((observable, oldValue, newValue) -> {
// 更新行号
updateLineNumberArea();
// 更新状态栏
JNotepadStatusBox.getInstance().updateWordCountStatusLabel();
UiUtil.getStatusBox().updateWordCountStatusLabel();
// 自动保存
save();
});
@ -75,7 +76,7 @@ public class LineNumberTextArea extends BorderPane {
* 以原文件编码格式写回文件
*/
public void save() {
JNotepadTab tab = JNotepadTabPane.getInstance().getSelected();
MainTab tab = UiUtil.getJnotepadtab();
if (tab == null) {
return;
}
@ -114,7 +115,6 @@ public class LineNumberTextArea extends BorderPane {
return mainTextArea.textProperty();
}
private void updateLineNumberArea() {
// 保存当前的滚动位置
/*
@ -138,6 +138,4 @@ public class LineNumberTextArea extends BorderPane {
public TextArea getMainTextArea() {
return mainTextArea;
}
}

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.ui.setStage;
package org.jcnc.jnotepad.ui.setstage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
@ -12,6 +12,8 @@ import org.jcnc.jnotepad.tool.UiUtil;
/**
* 设置窗口管理类实现了单例模式
*
* <p>该类用于管理设置窗口的显示和内容</p>
*
* @author 许轲
*/
public class SetStage {
@ -22,8 +24,6 @@ public class SetStage {
private static final SetStage SET_STAGE = new SetStage();
private StackPane contentDisplay;
private TreeView<String> settingsTreeView;
private SetStage() {
// 私有构造方法以实现单例模式
}
@ -45,7 +45,7 @@ public class SetStage {
contentDisplay = new StackPane(new Label("从左侧选择设置以显示内容"));
// 创建 TreeView并初始化设置项
settingsTreeView = createTreeView();
TreeView<String> settingsTreeView = createTreeView();
// 创建一个分割面板左侧是设置树右侧是内容显示区域
SplitPane splitPane = new SplitPane(settingsTreeView, contentDisplay);
@ -82,7 +82,6 @@ public class SetStage {
appearanceItem.getChildren().add(new TreeItem<>("外观设置项1"));
appearanceItem.getChildren().add(new TreeItem<>("外观设置项2"));
securityItem.getChildren().add(new TreeItem<>("安全设置项1"));
securityItem.getChildren().add(new TreeItem<>("安全设置项2"));

View File

@ -10,11 +10,12 @@ import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Duration;
/*
* 自定义的标题栏,没有完善好,暂时搁置
* */
/**
* 自定义标题栏组件用于自定义窗口标题栏的显示和交互
* 该类提供了窗口图标标题文本以及最小化最大化和关闭按钮的功能
*
* @author 许轲
*/
public class CustomTitleBar extends HBox {
private static CustomTitleBar instance;
@ -23,9 +24,9 @@ public class CustomTitleBar extends HBox {
this.setAlignment(Pos.CENTER);
// 左侧图标
ImageView iconView = new ImageView(new Image("icon.png"));
iconView.setFitWidth(30);
iconView.setFitHeight(30);
ImageView iconImageView = new ImageView(new Image("icon.png"));
iconImageView.setFitWidth(30);
iconImageView.setFitHeight(30);
Label titleLabel = new Label("自定义标题栏");
titleLabel.setStyle("-fx-font-size: 18px;");
@ -34,14 +35,15 @@ public class CustomTitleBar extends HBox {
HBox buttonBox = new HBox(5);
buttonBox.setAlignment(Pos.CENTER_RIGHT);
// 最小化按钮
Button minimizeButton = new Button("-");
minimizeButton.setStyle("-fx-background-color: transparent; ");
minimizeButton.setOnAction(event -> {
Stage stage = (Stage) this.getScene().getWindow();
stage.setIconified(true); // 最小化窗口
});
// 最大化/还原按钮
Button maximizeButton = new Button("");
maximizeButton.setStyle("-fx-background-color: transparent;");
maximizeButton.setOnAction(event -> {
@ -49,6 +51,7 @@ public class CustomTitleBar extends HBox {
stage.setMaximized(!stage.isMaximized()); // 最大化/还原窗口
});
// 关闭按钮
Button closeButton = new Button("X");
closeButton.setStyle("-fx-background-color: transparent;");
closeButton.setOnAction(event -> {
@ -58,9 +61,14 @@ public class CustomTitleBar extends HBox {
buttonBox.getChildren().addAll(minimizeButton, maximizeButton, closeButton);
this.getChildren().addAll(iconView, titleLabel, buttonBox);
this.getChildren().addAll(iconImageView, titleLabel, buttonBox);
}
/**
* 获取标题栏的单例实例
*
* @return CustomTitleBar的单例实例
*/
public static CustomTitleBar getInstance() {
if (instance == null) {
instance = new CustomTitleBar();
@ -68,11 +76,16 @@ public class CustomTitleBar extends HBox {
return instance;
}
/**
* 使窗口可拖动
*
* @param stage 要拖动的窗口的Stage对象
*/
public void makeDraggable(Stage stage) {
// 创建一个平移动画设置持续时间和目标位置
TranslateTransition minimizeAnimation = new TranslateTransition(Duration.seconds(0.3), stage.getScene().getRoot());
minimizeAnimation.setToY(stage.getHeight()); // 将根节点向下平移使窗口消失
// 将根节点向下平移使窗口消失
minimizeAnimation.setToY(stage.getHeight());
final Delta dragDelta = new Delta();
@ -92,4 +105,4 @@ public class CustomTitleBar extends HBox {
private static class Delta {
double x, y;
}
}
}

View File

@ -5,9 +5,10 @@ import javafx.scene.layout.BorderPane;
import org.jcnc.jnotepad.exception.AppException;
import org.jcnc.jnotepad.root.RootBorderPane;
/**
* 该类管理记事本应用程序的视图组件
* 视图管理器类用于管理记事本应用程序的视图组件
*
* <p>该类负责管理应用程序的视图组件包括主界面布局和标签页索引等</p>
*
* @author 许轲
*/
@ -15,30 +16,27 @@ public class ViewManager {
private static ViewManager instance = null;
// 主界面布局
private int tabIndex = 0;
/**
* 主布局
*/
private BorderPane root;
/**
* 构造函数设置场景和根布局
* 私有构造函数设置场景和根布局
*
* @param scene 与视图相关联的JavaFX场景
* @param scene 与视图相关联的 JavaFX 场景
*/
private ViewManager(Scene scene) {
root = new BorderPane();
scene.setRoot(root);
}
/**
* 获取ViewManager的实例如果实例不存在则创建一个新实例
* 获取 ViewManager 的实例如果实例不存在则创建一个新实例
*
* @param scene 与视图相关联的JavaFX场景
* @return ViewManager的实例
* @param scene 与视图相关联的 JavaFX 场景
* @return ViewManager 的实例
*/
public static ViewManager getInstance(Scene scene) {
if (instance == null) {
@ -47,18 +45,24 @@ public class ViewManager {
return instance;
}
/**
* 获取 ViewManager 的实例
*
* @return ViewManager 的实例
* @throws AppException 如果实例未初始化
*/
public static ViewManager getInstance() {
if (instance != null) {
return instance;
} else {
throw new AppException("ViewManager的实例未初始化!");
throw new AppException("ViewManager 的实例未初始化!");
}
}
/**
* 自增并获取标签页索引
* 自增并获取标签页索引
*
* @return int 标签页索引
* @return 自增后的标签页索引
* @apiNote ++tabIndex
*/
public int selfIncreaseAndGetTabIndex() {
@ -68,13 +72,13 @@ public class ViewManager {
/**
* 初始化屏幕组件
*
* @param scene 与视图相关联的JavaFX场景
* @param scene 与视图相关联的 JavaFX 场景
*/
public void initScreen(Scene scene) {
// 创建主界面布局
root = new BorderPane();
//root.setTop(CustomTitleBar.getInstance());
/*root.setTop(CustomTitleBar.getInstance());*/
root.setCenter(RootBorderPane.getInstance());
scene.setRoot(root);