♻️ 重构代码:重构项目代码,让项目更符合规范

This commit is contained in:
gewuyou 2023-08-21 16:38:51 +08:00
parent f1811216dd
commit b1662b717a
20 changed files with 318 additions and 136 deletions

View File

@ -2,6 +2,9 @@ package org.jcnc.jnotepad.Interface;
import java.util.Properties; import java.util.Properties;
/**
* @author 许轲
*/
public interface ConfigInterface { public interface ConfigInterface {
void showErrorAlert(); void showErrorAlert();
Properties readPropertiesFromFile(); Properties readPropertiesFromFile();

View File

@ -9,6 +9,7 @@ import java.util.List;
/** /**
* 控制器接口类 * 控制器接口类
* @author 许轲
*/ */
public interface ControllerInterface { public interface ControllerInterface {

View File

@ -2,9 +2,8 @@ package org.jcnc.jnotepad.Interface;
/** /**
* @author 一个大转盘 * @author 一个大转盘
* @date 2023/8/18
*/ */
public interface ShortcutKeyInterface { public interface ShortcutKeyInterface {
public void createShortcutKeyByConfig(); void createShortcutKeyByConfig();
} }

View File

@ -7,7 +7,7 @@ import javafx.scene.Scene;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.jcnc.jnotepad.constants.Constants; import org.jcnc.jnotepad.constants.AppConstants;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.init.Config; import org.jcnc.jnotepad.init.Config;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
@ -20,9 +20,16 @@ import java.util.Properties;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
/**
* 启动程序
*
* @author 许轲
*/
public class LunchApp extends Application { 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(); Controller controller = Controller.getInstance();
Scene scene; Scene scene;
@ -42,9 +49,9 @@ public class LunchApp extends Application {
Pane root = new Pane(); Pane root = new Pane();
double width = Constants.SCREEN_WIDTH; double width = AppConstants.SCREEN_WIDTH;
double length = Constants.SCREEN_LENGTH; double length = AppConstants.SCREEN_LENGTH;
String icon = Constants.APP_ICON; String icon = AppConstants.APP_ICON;
scene = new Scene(root, width, length); scene = new Scene(root, width, length);
Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet()); Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
@ -65,11 +72,10 @@ public class LunchApp extends Application {
view.initTabPane(); view.initTabPane();
view.initShortcutKey(); view.initShortcutKey();
if (isRelevance) { if (controller.isRelevance()) {
// 使用线程池加载关联文件并创建文本区域 // 使用线程池加载关联文件并创建文本区域
List<String> rawParameters = getParameters().getRaw(); List<String> rawParameters = getParameters().getRaw();
threadPool.execute(() -> { THREAD_POOL.execute(() -> {
LineNumberTextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters); LineNumberTextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters);
if (!Objects.isNull(textArea)) { if (!Objects.isNull(textArea)) {
Platform.runLater(() -> controller.updateUiWithNewTextArea(textArea)); Platform.runLater(() -> controller.updateUiWithNewTextArea(textArea));
@ -82,7 +88,7 @@ public class LunchApp extends Application {
@Override @Override
public void stop() { public void stop() {
// 关闭线程池 // 关闭线程池
threadPool.shutdownNow(); THREAD_POOL.shutdownNow();
} }
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -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";
}

View File

@ -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"; //配置文件名字
}

View File

@ -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";
}

View File

@ -8,6 +8,7 @@ import org.jcnc.jnotepad.ui.LineNumberTextArea;
* 换行程序 * 换行程序
* <p> * <p>
* 用于在文本区域中插入一个换行符 * 用于在文本区域中插入一个换行符
* @author 许轲
*/ */
public class LineFeed implements EventHandler<ActionEvent> { public class LineFeed implements EventHandler<ActionEvent> {
private final LineNumberTextArea textArea; private final LineNumberTextArea textArea;

View File

@ -3,16 +3,17 @@ package org.jcnc.jnotepad.controller.event.handler;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.view.manager.ViewManager;
import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane;
/** /**
* 新建文件事件的事件处理程序 * 新建文件事件的事件处理程序
* <p> * <p>
* 当用户选择新建文件时候,将创建一个新的文本编辑区并在Tab页中显示 * 当用户选择新建文件时候,将创建一个新的文本编辑区并在Tab页中显示
*
* @author 许轲
*/ */
public class NewFile implements EventHandler<ActionEvent> { public class NewFile implements EventHandler<ActionEvent> {
/** /**
@ -28,24 +29,22 @@ public class NewFile implements EventHandler<ActionEvent> {
// 创建一个新的文本编辑区 // 创建一个新的文本编辑区
LineNumberTextArea textArea = new LineNumberTextArea(); LineNumberTextArea textArea = new LineNumberTextArea();
textArea.setStyle( textArea.setStyle(
"-fx-border-color:white ;-fx-background-color:white;" "-fx-border-color:white ;-fx-background-color:white;"
); );
//TODO: refactor统一TextArea新建绑定监听器入口 // TODO: refactor统一TextArea新建绑定监听器入口
// 增加autoSave监听器绑定 // 增加autoSave监听器绑定
controller.autoSave(textArea); controller.autoSave(textArea);
ViewManager viewManager = ViewManager.getInstance();
// 创建一个新的Tab页 // 创建一个新的Tab页
Tab tab = new Tab("新建文本 " + ++ViewManager.tabIndex); Tab tab = new Tab("新建文本 " + viewManager.selfIncreaseAndGetTabIndex());
tab.setContent(textArea); tab.setContent(textArea);
// 将Tab页添加到TabPane中 // 将Tab页添加到TabPane中
tabPane.getTabs().add(tab); viewManager.getTabPane().getTabs().add(tab);
// 将新建的Tab页设置为选中状态 // 将新建的Tab页设置为选中状态
tabPane.getSelectionModel().select(tab); viewManager.getTabPane().getSelectionModel().select(tab);
// 更新状态标签 // 更新状态标签
controller.updateStatusLabel(textArea); controller.updateStatusLabel(textArea);

View File

@ -3,19 +3,19 @@ package org.jcnc.jnotepad.controller.event.handler;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.view.manager.ViewManager;
import java.io.File; import java.io.File;
import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane;
/** /**
* 打开文件的事件处理程序 * 打开文件的事件处理程序
* <p> * <p>
* 当用户选择打开文件时将创建一个新的文本编辑区并在Tab页中显示 * 当用户选择打开文件时将创建一个新的文本编辑区并在Tab页中显示
* @author 许轲
*/ */
public class OpenFile implements EventHandler<ActionEvent> { public class OpenFile implements EventHandler<ActionEvent> {
/** /**
@ -25,6 +25,8 @@ public class OpenFile implements EventHandler<ActionEvent> {
*/ */
@Override @Override
public void handle(ActionEvent event) { public void handle(ActionEvent event) {
// 获取ViewManager的实例
ViewManager viewManager = ViewManager.getInstance();
// 获取控制器 // 获取控制器
Controller controller = Controller.getInstance(); Controller controller = Controller.getInstance();
// 创建文件选择器 // 创建文件选择器
@ -39,7 +41,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
// 调用控制器的getText方法读取文件内容 // 调用控制器的getText方法读取文件内容
controller.getText(file); controller.getText(file);
// 更新编码标签 // 更新编码标签
controller.upDateEncodingLabel(((LineNumberTextArea) tabPane.getSelectionModel().getSelectedItem().getContent()).getMainTextArea().getText()); controller.upDateEncodingLabel(((LineNumberTextArea) viewManager.getTabPane().getSelectionModel().getSelectedItem().getContent()).getMainTextArea().getText());
return null; return null;
} }
}; };

View File

@ -5,13 +5,13 @@ import javafx.event.EventHandler;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.view.manager.ViewManager;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane;
/** /**
* 保存文件事件处理器 * 保存文件事件处理器
@ -20,6 +20,8 @@ import static org.jcnc.jnotepad.view.manager.ViewManager.tabPane;
* 会弹出一个保存文件对话框用户选择保存位置和文件名后 * 会弹出一个保存文件对话框用户选择保存位置和文件名后
* 将当前文本编辑区的内容保存到指定文件中 * 将当前文本编辑区的内容保存到指定文件中
* 并更新Tab页上的文件名和UserData * 并更新Tab页上的文件名和UserData
*
* @author 许轲
*/ */
public class SaveAsFile implements EventHandler<ActionEvent> { public class SaveAsFile implements EventHandler<ActionEvent> {
/** /**
@ -29,23 +31,25 @@ public class SaveAsFile implements EventHandler<ActionEvent> {
*/ */
@Override @Override
public void handle(ActionEvent event) { public void handle(ActionEvent event) {
Tab selectedTab = tabPane.getSelectionModel().getSelectedItem(); ViewManager viewManager = ViewManager.getInstance();
Tab selectedTab = viewManager.getTabPane().getSelectionModel().getSelectedItem();
if (selectedTab != null) { if (selectedTab != null) {
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
fileChooser.setInitialFileName(selectedTab.getText()); fileChooser.setInitialFileName(selectedTab.getText());
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt")); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt"));
File file = fileChooser.showSaveDialog(null); File file = fileChooser.showSaveDialog(null);
if (file != null) { if (file != null) {
try { try (
BufferedWriter writer = new BufferedWriter(new FileWriter(file)); BufferedWriter writer = new BufferedWriter(new FileWriter(file))
) {
LineNumberTextArea textArea = (LineNumberTextArea) selectedTab.getContent(); // 获取当前Tab页的文本编辑区 LineNumberTextArea textArea = (LineNumberTextArea) selectedTab.getContent(); // 获取当前Tab页的文本编辑区
String text = textArea.getMainTextArea().getText(); String text = textArea.getMainTextArea().getText();
writer.write(text); // 写入文件内容 writer.write(text); // 写入文件内容
writer.flush(); writer.flush();
writer.close();
selectedTab.setText(file.getName()); // 更新Tab页标签上的文件名 selectedTab.setText(file.getName()); // 更新Tab页标签上的文件名
selectedTab.setUserData(file); // 将文件对象保存到Tab页的UserData中 selectedTab.setUserData(file); // 将文件对象保存到Tab页的UserData中
} catch (IOException ignored) { } catch (IOException ignored) {
System.out.println("已忽视IO异常!");
} }
} }
} }

View File

@ -6,7 +6,6 @@ import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import org.jcnc.jnotepad.Interface.ControllerInterface; 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.LineFeed;
import org.jcnc.jnotepad.controller.event.handler.NewFile; import org.jcnc.jnotepad.controller.event.handler.NewFile;
import org.jcnc.jnotepad.controller.event.handler.OpenFile; import org.jcnc.jnotepad.controller.event.handler.OpenFile;
@ -26,8 +25,15 @@ import java.util.List;
* @author 许轲 * @author 许轲
*/ */
public class Controller implements ControllerInterface { public class Controller implements ControllerInterface {
private static final Controller INSTANCE = new Controller(); private static final Controller INSTANCE = new Controller();
/**
* 是否关联
*/
private boolean isRelevance = true;
public boolean isRelevance() {
return isRelevance;
}
private Controller() { private Controller() {
} }
@ -95,7 +101,7 @@ public class Controller implements ControllerInterface {
@Override @Override
public void autoSave(LineNumberTextArea textArea) { public void autoSave(LineNumberTextArea textArea) {
textArea.getMainTextArea().textProperty().addListener((observable, oldValue, newValue) -> { textArea.getMainTextArea().textProperty().addListener((observable, oldValue, newValue) -> {
Tab tab = ViewManager.tabPane.getSelectionModel().getSelectedItem(); Tab tab = ViewManager.getInstance().getTabPane().getSelectionModel().getSelectedItem();
if (tab != null) { if (tab != null) {
File file = (File) tab.getUserData(); File file = (File) tab.getUserData();
if (file != null) { if (file != null) {
@ -103,7 +109,7 @@ public class Controller implements ControllerInterface {
writer.write(newValue); writer.write(newValue);
System.out.println("正在自动保存---"); System.out.println("正在自动保存---");
} catch (IOException ignored) { } catch (IOException ignored) {
System.out.println("已忽视IO异常!");
} }
} }
} }
@ -131,7 +137,7 @@ public class Controller implements ControllerInterface {
int row = getRow(caretPosition, textArea.getMainTextArea().getText()); int row = getRow(caretPosition, textArea.getMainTextArea().getText());
int column = getColumn(caretPosition, textArea.getMainTextArea().getText()); int column = getColumn(caretPosition, textArea.getMainTextArea().getText());
int length = textArea.getMainTextArea().getLength(); int length = textArea.getMainTextArea().getLength();
ViewManager.statusLabel.setText("行: " + row + " \t列: " + column + " \t字数: " + length); ViewManager.getInstance().getStatusLabel().setText("行: " + row + " \t列: " + column + " \t字数: " + length);
} }
/** /**
@ -143,7 +149,7 @@ public class Controller implements ControllerInterface {
public void openAssociatedFile(String filePath) { public void openAssociatedFile(String filePath) {
File file = new File(filePath); File file = new File(filePath);
if (file.exists() && file.isFile()) { if (file.exists() && file.isFile()) {
LunchApp.isRelevance = false; isRelevance = false;
openFile(file); openFile(file);
} }
} }
@ -155,6 +161,7 @@ public class Controller implements ControllerInterface {
*/ */
@Override @Override
public void getText(File file) { public void getText(File file) {
ViewManager viewManager = ViewManager.getInstance();
LineNumberTextArea textArea = createNewTextArea(); LineNumberTextArea textArea = createNewTextArea();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
StringBuilder textBuilder = new StringBuilder(); StringBuilder textBuilder = new StringBuilder();
@ -169,15 +176,15 @@ public class Controller implements ControllerInterface {
Tab tab = createNewTab(file.getName(), textArea); Tab tab = createNewTab(file.getName(), textArea);
tab.setUserData(file); tab.setUserData(file);
ViewManager.tabPane.getTabs().add(tab); viewManager.getTabPane().getTabs().add(tab);
// ViewManager.tabPane.sets // ViewManager.tabPane.sets
ViewManager.tabPane.getSelectionModel().select(tab); viewManager.getTabPane().getSelectionModel().select(tab);
updateStatusLabel(textArea); updateStatusLabel(textArea);
autoSave(textArea); autoSave(textArea);
}); });
} catch (IOException ignored) { } catch (IOException ignored) {
System.out.println("已忽视IO异常!");
} }
} }
@ -189,7 +196,7 @@ public class Controller implements ControllerInterface {
@Override @Override
public void upDateEncodingLabel(String text) { public void upDateEncodingLabel(String text) {
String encoding = EncodingDetector.detectEncoding(text); String encoding = EncodingDetector.detectEncoding(text);
ViewManager.enCodingLabel.setText("\t编码: " + encoding); ViewManager.getInstance().getEnCodingLabel().setText("\t编码: " + encoding);
} }
/** /**
@ -230,7 +237,7 @@ public class Controller implements ControllerInterface {
@Override @Override
public void initTabPane() { public void initTabPane() {
Controller controller = new Controller(); Controller controller = new Controller();
ViewManager.tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { ViewManager.getInstance().getTabPane().getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> {
LineNumberTextArea textArea; LineNumberTextArea textArea;
if (newTab != null) { if (newTab != null) {
// 获取新选定的标签页并关联的文本区域 // 获取新选定的标签页并关联的文本区域
@ -253,16 +260,17 @@ public class Controller implements ControllerInterface {
/** /**
* 更新UI和标签页 * 更新UI和标签页
* *
* @param textArea 文本域 * @param textArea 文本域
* @apiNote * @apiNote
* @since 2023/8/20 12:40 * @since 2023/8/20 12:40
*/ */
@Override @Override
public void updateUiWithNewTextArea(LineNumberTextArea textArea) { public void updateUiWithNewTextArea(LineNumberTextArea textArea) {
Tab tab = new Tab("新建文件 " + (++ViewManager.tabIndex)); ViewManager viewManager = ViewManager.getInstance();
Tab tab = new Tab("新建文件 " + viewManager.selfIncreaseAndGetTabIndex());
tab.setContent(textArea); tab.setContent(textArea);
ViewManager.tabPane.getTabs().add(tab); viewManager.getTabPane().getTabs().add(tab);
ViewManager.tabPane.getSelectionModel().select(tab); viewManager.getTabPane().getSelectionModel().select(tab);
updateStatusLabel(textArea); updateStatusLabel(textArea);
} }

View File

@ -6,28 +6,27 @@ import com.google.gson.reflect.TypeToken;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyCombination;
import org.jcnc.jnotepad.Interface.ShortcutKeyInterface; import org.jcnc.jnotepad.Interface.ShortcutKeyInterface;
import org.jcnc.jnotepad.tool.FileUtil;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.view.manager.ViewManager;
import java.io.*; import java.io.*;
import java.net.URL;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import static org.jcnc.jnotepad.constants.PathConstants.SHORTCUT_KEY_CONFIGURATION_FILE_PATH;
/** /**
* @author 一个大转盘 * @author 一个大转盘<br>
* @date 2023/8/18
*/ */
public class ShortcutKey implements ShortcutKeyInterface { public class ShortcutKey implements ShortcutKeyInterface {
@Override @Override
public void createShortcutKeyByConfig() { public void createShortcutKeyByConfig() {
String rootPath =System.getProperty("user.dir"); String rootPath = System.getProperty("user.dir");
// 构建JSON文件路径 // 构建JSON文件路径
String jsonFilePath = rootPath +"/config/shortcutKey.json"; String jsonFilePath = rootPath + SHORTCUT_KEY_CONFIGURATION_FILE_PATH;
InputStream inputStream = getClass().getResourceAsStream("/config/shortcutKey.json"); InputStream inputStream = getClass().getResourceAsStream(SHORTCUT_KEY_CONFIGURATION_FILE_PATH);
StringBuffer jsonData = new StringBuffer(); StringBuffer jsonData = new StringBuffer();
File file = new File(jsonFilePath); File file = new File(jsonFilePath);
if(file.exists()){ if (file.exists()) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
@ -36,7 +35,8 @@ public class ShortcutKey implements ShortcutKeyInterface {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
}else { } else {
// todo new InputStreamReader(inputStream) 实参 'inputStream' 可能为null
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
@ -54,16 +54,13 @@ public class ShortcutKey implements ShortcutKeyInterface {
}.getType()); }.getType());
for (Map.Entry<String, String> stringObjectEntry : shortcutKeyConfig.entrySet()) { for (Map.Entry<String, String> stringObjectEntry : shortcutKeyConfig.entrySet()) {
// 保证json的key必须和变量名一致 // 保证json的key必须和变量名一致
MenuItem menuItem = ViewManager.itemMap.get(stringObjectEntry.getKey()); MenuItem menuItem = ViewManager.getInstance().getItemMap().get(stringObjectEntry.getKey());
String shortKeyValue = stringObjectEntry.getValue(); String shortKeyValue = stringObjectEntry.getValue();
if ("".equals(shortKeyValue) || Objects.isNull(menuItem)) { if ("".equals(shortKeyValue) || Objects.isNull(menuItem)) {
continue; continue;
} }
// 动态添加快捷键 // 动态添加快捷键
menuItem.setAccelerator(KeyCombination.keyCombination(shortKeyValue)); menuItem.setAccelerator(KeyCombination.keyCombination(shortKeyValue));
} }
} }
} }

View File

@ -6,8 +6,11 @@ import org.jcnc.jnotepad.Interface.ConfigInterface;
import java.io.*; import java.io.*;
import java.util.Properties; 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 class Config implements ConfigInterface {
public Properties readPropertiesFromFile() { public Properties readPropertiesFromFile() {
Properties properties = new Properties(); Properties properties = new Properties();

View File

@ -8,8 +8,12 @@ import java.nio.charset.StandardCharsets;
/** /**
* 编码检测工具类 * 编码检测工具类
*
* @author 许轲
*/ */
public class EncodingDetector { public class EncodingDetector {
private EncodingDetector() {
}
/** /**
* 检测 TextArea 中的文本编码 * 检测 TextArea 中的文本编码
@ -19,7 +23,6 @@ public class EncodingDetector {
*/ */
public static String detectEncoding(LineNumberTextArea textArea) { public static String detectEncoding(LineNumberTextArea textArea) {
String text = textArea.getMainTextArea().getText(); String text = textArea.getMainTextArea().getText();
return detectEncoding(text); return detectEncoding(text);
} }

View File

@ -5,28 +5,28 @@ import java.nio.charset.StandardCharsets;
/** /**
* @author 一个大转盘 * @author 一个大转盘
* @date 2023/8/18
*/ */
public class FileUtil { public class FileUtil {
private FileUtil() {
}
/** /**
* 把一个文件中的内容读取成一个String字符串 * 把一个文件中的内容读取成一个String字符串
* @date 2023/8/18 0:54 *
* @param jsonFile * @param jsonFile json文件
* @return String * @return String
*/ */
public static String getJsonStr(File jsonFile){ public static String getJsonStr(File jsonFile) {
String jsonStr = ""; String jsonStr;
try { try (
FileReader fileReader = new FileReader(jsonFile); Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8)
Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8); ) {
int ch = 0;
int ch;
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
while ((ch = reader.read()) != -1) { while ((ch = reader.read()) != -1) {
sb.append((char) ch); sb.append((char) ch);
} }
fileReader.close();
reader.close();
jsonStr = sb.toString(); jsonStr = sb.toString();
return jsonStr; return jsonStr;
} catch (IOException e) { } catch (IOException e) {

View File

@ -4,13 +4,14 @@ import javafx.beans.property.StringProperty;
import javafx.scene.control.TextArea; import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
/**
* @author 许轲
*/
public class LineNumberTextArea extends BorderPane { public class LineNumberTextArea extends BorderPane {
private final TextArea mainTextArea; private final TextArea mainTextArea;
private final TextArea lineNumberArea; 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}; 99999999, 999999999, Integer.MAX_VALUE};
private static final int MIN_LINE_NUMBER_WIDTH = 30; 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.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumberArea());
// 当主要文本区域的垂直滚动位置发生变化时使行号文本区域的滚动位置保持一致 // 当主要文本区域的垂直滚动位置发生变化时使行号文本区域的滚动位置保持一致
mainTextArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> { mainTextArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> lineNumberArea.setScrollTop(mainTextArea.getScrollTop()));
lineNumberArea.setScrollTop(mainTextArea.getScrollTop());
});
// 当行号文本区域的垂直滚动位置发生变化时使主要文本区域的滚动位置保持一致 // 当行号文本区域的垂直滚动位置发生变化时使主要文本区域的滚动位置保持一致
lineNumberArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> { lineNumberArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> mainTextArea.setScrollTop(lineNumberArea.getScrollTop()));
mainTextArea.setScrollTop(lineNumberArea.getScrollTop());
});
setCenter(mainTextArea); setCenter(mainTextArea);
setLeft(lineNumberArea); setLeft(lineNumberArea);
} }
@ -43,13 +39,13 @@ public class LineNumberTextArea extends BorderPane {
private void updateLineNumberWidth() { private void updateLineNumberWidth() {
int numOfLines = mainTextArea.getParagraphs().size(); int numOfLines = mainTextArea.getParagraphs().size();
int count = 1; int count = 1;
for (int i = 0; i < sizeTable.length; i++) { for (int i = 0; i < SIZE_TABLE.length; i++) {
if (numOfLines <= sizeTable[i]) { if (numOfLines <= SIZE_TABLE[i]) {
count = i + 1; count = i + 1;
break; break;
} }
} }
//单数字宽度10像素4为padding=左3+右1 // 单数字宽度10像素4为padding=左3+右1
int actualWidth = Math.max(count * 10 + 11, MIN_LINE_NUMBER_WIDTH); int actualWidth = Math.max(count * 10 + 11, MIN_LINE_NUMBER_WIDTH);
if (actualWidth != lineNumberArea.getWidth()) { if (actualWidth != lineNumberArea.getWidth()) {
lineNumberArea.setPrefWidth(actualWidth); lineNumberArea.setPrefWidth(actualWidth);

View File

@ -2,28 +2,32 @@ package org.jcnc.jnotepad.view.init;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.controller.manager.ShortcutKey; import org.jcnc.jnotepad.controller.manager.ShortcutKey;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.view.manager.ViewManager;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.jcnc.jnotepad.view.manager.ViewManager.*;
/**
* @author 许轲
*/
public class View { public class View {
private static Map<String, Object> itmeMap = new HashMap<>(); // todo 这个东西干嘛的都没用过
private static Map<String, Object> itmeMap = new HashMap<>();
public void initItem() { public void initItem() {
ViewManager viewManager = ViewManager.getInstance();
// 初始化菜单项的事件处理器 // 初始化菜单项的事件处理器
EventHandler<ActionEvent> newFileEventHandler = Controller.getInstance().getNewFileEventHandler(new LineNumberTextArea()); EventHandler<ActionEvent> newFileEventHandler = Controller.getInstance().getNewFileEventHandler(new LineNumberTextArea());
newItem.setOnAction(newFileEventHandler); viewManager.getNewItem().setOnAction(newFileEventHandler);
EventHandler<ActionEvent> openFileEventHandler = Controller.getInstance().getOpenFileEventHandler(); EventHandler<ActionEvent> openFileEventHandler = Controller.getInstance().getOpenFileEventHandler();
openItem.setOnAction(openFileEventHandler); viewManager.getOpenItem().setOnAction(openFileEventHandler);
EventHandler<ActionEvent> saveAsFileEventHandler = Controller.getInstance().getSaveAsFileEventHandler(); EventHandler<ActionEvent> saveAsFileEventHandler = Controller.getInstance().getSaveAsFileEventHandler();
saveAsItem.setOnAction(saveAsFileEventHandler); viewManager.getSaveAsItem().setOnAction(saveAsFileEventHandler);
lineFeedItem.setOnAction(Controller.getInstance().getLineFeedEventHandler(new LineNumberTextArea())); viewManager.getLineFeedItem().setOnAction(Controller.getInstance().getLineFeedEventHandler(new LineNumberTextArea()));
} }
public void initTabPane() { public void initTabPane() {
@ -31,7 +35,7 @@ public class View {
} }
// 初始化快捷键 // 初始化快捷键
public void initShortcutKey(){ public void initShortcutKey() {
new ShortcutKey().createShortcutKeyByConfig(); new ShortcutKey().createShortcutKeyByConfig();
} }

View File

@ -8,39 +8,157 @@ import javafx.scene.layout.HBox;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* 该类管理记事本应用程序的视图组件 * 该类管理记事本应用程序的视图组件
*
* @author 许轲
*/ */
public class ViewManager { 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;
// 菜单栏组件 /// 菜单栏组件
public static MenuBar menuBar; //菜单栏
public static Menu fileMenu, setMenu, pluginMenu; //文件菜单//设置菜单//插件菜单 菜单
public static MenuItem newItem, openItem, saveAsItem, addItem, countItem; //新建/打开/保存/保存至//增加//查看 菜单按钮
public static CheckMenuItem lineFeedItem; //自动换行点击菜单按钮 /**
* 菜单栏
*/
private MenuBar menuBar;
/**
* 文件菜单
*/
private Menu fileMenu;
/**
* 插件菜单
*/
private Menu setMenu;
/**
* 插件菜单
*/
private Menu pluginMenu;
/// 菜单按钮
/**
* 新建
*/
private MenuItem newItem;
/**
* 打开
*/
private MenuItem openItem;
/**
* 保存
*/
private MenuItem saveAsItem;
/**
* 增加
*/
private MenuItem addItem;
/**
* 查看
*/
private MenuItem countItem;
private CheckMenuItem lineFeedItem; // 自动换行点击菜单按钮
// 主界面布局 // 主界面布局
public static BorderPane root; //主布局 private BorderPane root; // 主布局
// 多个标签页 // 多个标签页
public static TabPane tabPane; //标签页栏 private TabPane tabPane; // 标签页栏
// 状态栏 // 状态栏
public static Label statusLabel; private Label statusLabel;
private static ViewManager instance = null; private static ViewManager instance = null;
public static Map<String, MenuItem> itemMap = new HashMap<>(); private Map<String, MenuItem> 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<String, MenuItem> getItemMap() {
return itemMap;
}
/** /**
* 获取ViewManager的实例如果实例不存在则创建一个新实例 * 获取ViewManager的实例如果实例不存在则创建一个新实例
@ -49,13 +167,20 @@ public class ViewManager {
* @return ViewManager的实例 * @return ViewManager的实例
*/ */
public static ViewManager getInstance(Scene scene) { public static ViewManager getInstance(Scene scene) {
if (instance == null) { if (instance == null) {
instance = new ViewManager(scene); instance = new ViewManager(scene);
} }
return instance; return instance;
} }
public static ViewManager getInstance() {
if (instance != null) {
return instance;
} else {
throw new RuntimeException("ViewManager的实例未初始化!");
}
}
/** /**
* 构造函数设置场景和根布局 * 构造函数设置场景和根布局
* *
@ -63,8 +188,6 @@ public class ViewManager {
*/ */
private ViewManager(Scene scene) { private ViewManager(Scene scene) {
root = new BorderPane(); root = new BorderPane();
scene.setRoot(root); scene.setRoot(root);
} }
@ -78,7 +201,7 @@ public class ViewManager {
// 创建菜单栏并添加菜单项 // 创建菜单栏并添加菜单项
menuBar = new MenuBar(); menuBar = new MenuBar();
//文件菜单 // 文件菜单
fileMenu = new Menu("文件"); fileMenu = new Menu("文件");
newItem = new MenuItem("新建"); newItem = new MenuItem("新建");
@ -92,7 +215,7 @@ public class ViewManager {
fileMenu.getItems().addAll(newItem, openItem, saveAsItem); fileMenu.getItems().addAll(newItem, openItem, saveAsItem);
//设置菜单 // 设置菜单
setMenu = new Menu("设置"); setMenu = new Menu("设置");
lineFeedItem = new CheckMenuItem("自动换行"); lineFeedItem = new CheckMenuItem("自动换行");
@ -101,7 +224,7 @@ public class ViewManager {
setMenu.getItems().addAll(lineFeedItem); setMenu.getItems().addAll(lineFeedItem);
//插件菜单 // 插件菜单
pluginMenu = new Menu("插件"); pluginMenu = new Menu("插件");
addItem = new MenuItem("增加插件"); addItem = new MenuItem("增加插件");
itemMap.put("addItem", addItem); itemMap.put("addItem", addItem);
@ -111,7 +234,7 @@ public class ViewManager {
pluginMenu.getItems().addAll(addItem, countItem); pluginMenu.getItems().addAll(addItem, countItem);
//菜单栏 // 菜单栏
menuBar.getMenus().addAll(fileMenu, setMenu, pluginMenu); menuBar.getMenus().addAll(fileMenu, setMenu, pluginMenu);
// 创建主界面布局 // 创建主界面布局
@ -131,8 +254,5 @@ public class ViewManager {
BorderPane.setMargin(statusBox, new Insets(5, 10, 5, 10)); BorderPane.setMargin(statusBox, new Insets(5, 10, 5, 10));
scene.setRoot(root); scene.setRoot(root);
} }
} }

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="67px" height="67px" viewBox="0 0 67 67" enable-background="new 0 0 67 67" xml:space="preserve"> <image id="image0" width="67" height="67" x="0" y="0" <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="67px" height="67px"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAABDCAMAAADwFEhBAAAABGdBTUEAALGPC/xhBQAAACBjSFJN viewBox="0 0 67 67" enable-background="new 0 0 67 67" xml:space="preserve"> <image id="image0" width="67" height="67" x="0" y="0"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAABDCAMAAADwFEhBAAAABGdBTUEAALGPC/xhBQAAACBjSFJN
AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAQlBMVEUAAABpzLppy7lqzLpq AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAQlBMVEUAAABpzLppy7lqzLpq
zLpqy7lqzLrg9PHi9fF30MD+//7///960sKZ3NDM7efY8u1vzry05dzG7OWa3dDN7uin4dYGHsA1 zLpqy7lqzLrg9PHi9fF30MD+//7///960sKZ3NDM7efY8u1vzry05dzG7OWa3dDN7uin4dYGHsA1
AAAABnRSTlMAyPPm062MDfhZAAAAAWJLR0QLH9fEwAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0 AAAABnRSTlMAyPPm062MDfhZAAAAAWJLR0QLH9fEwAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB