!41 refactor: #I7VLH0 统一配置入口
Merge pull request !41 from songdragon/refactor-I7VLH0
This commit is contained in:
commit
c81517b96b
@ -18,13 +18,9 @@ module org.jcnc.jnotepad {
|
|||||||
exports org.jcnc.jnotepad.Interface;
|
exports org.jcnc.jnotepad.Interface;
|
||||||
exports org.jcnc.jnotepad.controller.event.handler;
|
exports org.jcnc.jnotepad.controller.event.handler;
|
||||||
exports org.jcnc.jnotepad.controller.manager;
|
exports org.jcnc.jnotepad.controller.manager;
|
||||||
exports org.jcnc.jnotepad.view.init;
|
|
||||||
exports org.jcnc.jnotepad.view.manager;
|
exports org.jcnc.jnotepad.view.manager;
|
||||||
exports org.jcnc.jnotepad.constants;
|
exports org.jcnc.jnotepad.constants;
|
||||||
exports org.jcnc.jnotepad.ui;
|
exports org.jcnc.jnotepad.ui;
|
||||||
exports org.jcnc.jnotepad.app.init;
|
exports org.jcnc.jnotepad.controller.i18n;
|
||||||
// 导出 JSON 相关的包,以便 Jackson 库可以访问
|
opens org.jcnc.jnotepad.app.config;
|
||||||
exports org.jcnc.jnotepad.json;
|
|
||||||
// 打开 JSON 相关的包,以便 Jackson 库可以使用反射
|
|
||||||
opens org.jcnc.jnotepad.json;
|
|
||||||
}
|
}
|
||||||
@ -7,6 +7,7 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 控制器接口类
|
* 控制器接口类
|
||||||
|
*
|
||||||
* @author 许轲
|
* @author 许轲
|
||||||
*/
|
*/
|
||||||
public interface ControllerInterface {
|
public interface ControllerInterface {
|
||||||
@ -17,7 +18,7 @@ public interface ControllerInterface {
|
|||||||
* @param rawParameters 原始参数列表
|
* @param rawParameters 原始参数列表
|
||||||
* @return 创建的 TextArea
|
* @return 创建的 TextArea
|
||||||
*/
|
*/
|
||||||
LineNumberTextArea openAssociatedFileAndCreateTextArea(List<String> rawParameters);
|
void openAssociatedFileAndCreateTextArea(List<String> rawParameters);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开关联文件
|
* 打开关联文件
|
||||||
@ -26,20 +27,4 @@ public interface ControllerInterface {
|
|||||||
*/
|
*/
|
||||||
void openAssociatedFile(String filePath);
|
void openAssociatedFile(String filePath);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取文件内容
|
|
||||||
*
|
|
||||||
* @param file 文件
|
|
||||||
*/
|
|
||||||
void getText(File file);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新UI和标签页
|
|
||||||
*
|
|
||||||
* @param textArea 文本域
|
|
||||||
* @apiNote
|
|
||||||
* @since 2023/8/20 12:40
|
|
||||||
*/
|
|
||||||
|
|
||||||
void updateUiWithNewTextArea(LineNumberTextArea textArea);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,24 +3,18 @@ package org.jcnc.jnotepad;
|
|||||||
|
|
||||||
import atlantafx.base.theme.PrimerLight;
|
import atlantafx.base.theme.PrimerLight;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.scene.Scene;
|
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.app.i18n.UIResourceBundle;
|
import org.jcnc.jnotepad.app.i18n.UIResourceBundle;
|
||||||
import org.jcnc.jnotepad.app.init.LoadJnotepadConfig;
|
|
||||||
import org.jcnc.jnotepad.app.init.LoadLanguageConfig;
|
|
||||||
import org.jcnc.jnotepad.app.init.LoadShortcutKeyConfig;
|
|
||||||
import org.jcnc.jnotepad.constants.AppConstants;
|
import org.jcnc.jnotepad.constants.AppConstants;
|
||||||
import org.jcnc.jnotepad.constants.TextConstants;
|
import org.jcnc.jnotepad.constants.TextConstants;
|
||||||
|
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
|
||||||
import org.jcnc.jnotepad.controller.manager.Controller;
|
import org.jcnc.jnotepad.controller.manager.Controller;
|
||||||
import org.jcnc.jnotepad.manager.ThreadPoolManager;
|
import org.jcnc.jnotepad.manager.ThreadPoolManager;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
|
||||||
import org.jcnc.jnotepad.view.init.View;
|
|
||||||
import org.jcnc.jnotepad.view.manager.ViewManager;
|
import org.jcnc.jnotepad.view.manager.ViewManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@ -38,26 +32,6 @@ public class LunchApp extends Application {
|
|||||||
private final ExecutorService threadPool = ThreadPoolManager.getThreadPool();
|
private final ExecutorService threadPool = ThreadPoolManager.getThreadPool();
|
||||||
Controller controller = Controller.getInstance();
|
Controller controller = Controller.getInstance();
|
||||||
Scene scene;
|
Scene scene;
|
||||||
/**
|
|
||||||
* 配置文件数组
|
|
||||||
*/
|
|
||||||
private static final List<LoadJnotepadConfig<?>> LOAD_JNOTEPAD_CONFIGS = new ArrayList<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
// 语言配置文件
|
|
||||||
LOAD_JNOTEPAD_CONFIGS.add(new LoadLanguageConfig());
|
|
||||||
// 快捷键配置文件
|
|
||||||
LOAD_JNOTEPAD_CONFIGS.add(new LoadShortcutKeyConfig());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取配置文件数组
|
|
||||||
*
|
|
||||||
* @since 2023/8/26 16:05
|
|
||||||
*/
|
|
||||||
public static List<LoadJnotepadConfig<?>> getLocalizationConfigs() {
|
|
||||||
return LOAD_JNOTEPAD_CONFIGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) {
|
public void start(Stage primaryStage) {
|
||||||
@ -68,19 +42,9 @@ public class LunchApp extends Application {
|
|||||||
scene = new Scene(root, width, length);
|
scene = new Scene(root, width, length);
|
||||||
Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
|
Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
|
||||||
scene.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/css/styles.css")).toExternalForm());
|
scene.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/css/styles.css")).toExternalForm());
|
||||||
|
initUIComponents();
|
||||||
|
|
||||||
|
|
||||||
// 使用线程池加载关联文件并创建文本区域
|
|
||||||
List<String> rawParameters = getParameters().getRaw();
|
|
||||||
threadPool.execute(() -> {
|
|
||||||
LineNumberTextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters);
|
|
||||||
if (!Objects.isNull(textArea)) {
|
|
||||||
Platform.runLater(() -> controller.updateUiWithNewTextArea(textArea));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ViewManager viewManager = ViewManager.getInstance(scene);
|
|
||||||
viewManager.initScreen(scene);
|
|
||||||
// 加载配置文件
|
|
||||||
View.getInstance().initJnotepadConfigs(LOAD_JNOTEPAD_CONFIGS);
|
|
||||||
UIResourceBundle.bindStringProperty(primaryStage.titleProperty(), TextConstants.TITLE);
|
UIResourceBundle.bindStringProperty(primaryStage.titleProperty(), TextConstants.TITLE);
|
||||||
primaryStage.setWidth(width);
|
primaryStage.setWidth(width);
|
||||||
primaryStage.setHeight(length);
|
primaryStage.setHeight(length);
|
||||||
@ -89,6 +53,20 @@ public class LunchApp extends Application {
|
|||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initUIComponents() {
|
||||||
|
|
||||||
|
//1. 加载语言
|
||||||
|
LocalizationController.initLocal();
|
||||||
|
|
||||||
|
//2. 加载组件
|
||||||
|
ViewManager viewManager = ViewManager.getInstance(scene);
|
||||||
|
viewManager.initScreen(scene);
|
||||||
|
|
||||||
|
// 使用线程池加载关联文件并创建文本区域
|
||||||
|
List<String> rawParameters = getParameters().getRaw();
|
||||||
|
controller.openAssociatedFileAndCreateTextArea(rawParameters);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
// 关闭线程池
|
// 关闭线程池
|
||||||
|
|||||||
112
src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java
Normal file
112
src/main/java/org/jcnc/jnotepad/app/config/AppConfig.java
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package org.jcnc.jnotepad.app.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据模型类,用于表示 MyData 对象的数据结构。
|
||||||
|
*
|
||||||
|
* @author 许轲
|
||||||
|
*/
|
||||||
|
public class AppConfig {
|
||||||
|
private String language;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private boolean textWrap;
|
||||||
|
|
||||||
|
private List<ShortcutKey> shortcutKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShortcutKey 类,用于表示快捷键信息。
|
||||||
|
*/
|
||||||
|
public static class ShortcutKey {
|
||||||
|
private String buttonName;
|
||||||
|
private String shortcutKeyValue;
|
||||||
|
|
||||||
|
public String getButtonName() {
|
||||||
|
return buttonName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonName(String buttonName) {
|
||||||
|
this.buttonName = buttonName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getShortcutKeyValue() {
|
||||||
|
return shortcutKeyValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShortcutKeyValue(String shortcutKeyValue) {
|
||||||
|
this.shortcutKeyValue = shortcutKeyValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLanguage() {
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLanguage(String language) {
|
||||||
|
this.language = language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ShortcutKey> getShortcutKey() {
|
||||||
|
return shortcutKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShortcutKey(List<ShortcutKey> shortcutKey) {
|
||||||
|
this.shortcutKey = shortcutKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String CTRL_N = "ctrl+n";
|
||||||
|
private static final String CTRL_O = "ctrl+o";
|
||||||
|
private static final String CTRL_S = "ctrl+s";
|
||||||
|
private static final String CTRL_ALT_S = "ctrl+alt+s";
|
||||||
|
private static final String ALT_S = "alt+s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成默认应用配置对象。
|
||||||
|
*
|
||||||
|
* @return 默认应用配置对象
|
||||||
|
*/
|
||||||
|
public static AppConfig generateDefaultAppConfig() {
|
||||||
|
AppConfig myData = new AppConfig();
|
||||||
|
myData.setLanguage("chinese");
|
||||||
|
myData.setTextWrap(false);
|
||||||
|
|
||||||
|
List<AppConfig.ShortcutKey> shortcutKeys = new ArrayList<>();
|
||||||
|
shortcutKeys.add(createShortcutKey("newItem", CTRL_N));
|
||||||
|
shortcutKeys.add(createShortcutKey("openItem", CTRL_O));
|
||||||
|
shortcutKeys.add(createShortcutKey("saveItem", CTRL_S));
|
||||||
|
shortcutKeys.add(createShortcutKey("saveAsItem", CTRL_ALT_S));
|
||||||
|
shortcutKeys.add(createShortcutKey("lineFeedItem", ""));
|
||||||
|
shortcutKeys.add(createShortcutKey("openConfigItem", ALT_S));
|
||||||
|
shortcutKeys.add(createShortcutKey("addItem", ""));
|
||||||
|
shortcutKeys.add(createShortcutKey("countItem", ""));
|
||||||
|
|
||||||
|
myData.setShortcutKey(shortcutKeys);
|
||||||
|
return myData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 ShortcutKey 对象。
|
||||||
|
*
|
||||||
|
* @param buttonName 按钮名称
|
||||||
|
* @param shortcutKeyValue 快捷键值
|
||||||
|
* @return ShortcutKey 对象
|
||||||
|
*/
|
||||||
|
private static AppConfig.ShortcutKey createShortcutKey(String buttonName, String shortcutKeyValue) {
|
||||||
|
AppConfig.ShortcutKey shortcutKey = new AppConfig.ShortcutKey();
|
||||||
|
shortcutKey.setButtonName(buttonName);
|
||||||
|
shortcutKey.setShortcutKeyValue(shortcutKeyValue);
|
||||||
|
return shortcutKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTextWrap() {
|
||||||
|
return textWrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextWrap(boolean textWrap) {
|
||||||
|
this.textWrap = textWrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,35 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.app.config;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 内存中,运行过程中的全局配置项
|
|
||||||
*
|
|
||||||
* @author zhaoteng.song
|
|
||||||
*/
|
|
||||||
public class GlobalConfig {
|
|
||||||
|
|
||||||
private static final GlobalConfig APP_GLOBAL_CONFIG = new GlobalConfig();
|
|
||||||
LocalizationConfig localizationConfig = LocalizationConfig.getLocalizationConfig();
|
|
||||||
|
|
||||||
private GlobalConfig() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取自动换行设置,默认自动换行
|
|
||||||
*
|
|
||||||
* @return true, 自动换行;false,不自动换行
|
|
||||||
*/
|
|
||||||
public boolean getAutoLineConfig() {
|
|
||||||
return Boolean.parseBoolean(localizationConfig.getTextWrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAutoLineConfig(boolean isAutoLine) {
|
|
||||||
String autoLineConfig = String.valueOf(isAutoLine);
|
|
||||||
localizationConfig.setTextWrap(autoLineConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalConfig getConfig() {
|
|
||||||
return APP_GLOBAL_CONFIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -6,7 +6,6 @@ import javafx.beans.property.ObjectProperty;
|
|||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import org.jcnc.jnotepad.app.config.LocalizationConfig;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
@ -34,7 +33,7 @@ public class UIResourceBundle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private UIResourceBundle() {
|
private UIResourceBundle() {
|
||||||
this.resetLocal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,11 +61,11 @@ public class UIResourceBundle {
|
|||||||
/**
|
/**
|
||||||
* 重置当前local
|
* 重置当前local
|
||||||
*/
|
*/
|
||||||
public final void resetLocal() {
|
public final void resetLocal(Locale toLocal) {
|
||||||
if (this.currentLocale == LocalizationConfig.getCurrentLocal()) {
|
if (this.currentLocale == toLocal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.currentLocale = LocalizationConfig.getCurrentLocal();
|
this.currentLocale = toLocal;
|
||||||
ResourceBundle resourceBundle = ResourceBundle.getBundle(BASENAME, currentLocale);
|
ResourceBundle resourceBundle = ResourceBundle.getBundle(BASENAME, currentLocale);
|
||||||
this.setResources(resourceBundle);
|
this.setResources(resourceBundle);
|
||||||
|
|
||||||
|
|||||||
@ -1,96 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.app.init;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.jcnc.jnotepad.exception.AppException;
|
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
|
||||||
import org.jcnc.jnotepad.tool.PopUpUtil;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
import static org.jcnc.jnotepad.constants.AppConstants.CONFIG_NAME;
|
|
||||||
import static org.jcnc.jnotepad.constants.TextConstants.JNOTEPAD_CONFIG;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载应用配置类
|
|
||||||
* <br/>空出了加载文件的具体实现
|
|
||||||
*
|
|
||||||
* @author gewuyou
|
|
||||||
*/
|
|
||||||
public abstract class LoadJnotepadConfig<T> {
|
|
||||||
Logger logger = LogUtil.getLogger(this.getClass());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回json配置文件的json节点
|
|
||||||
*
|
|
||||||
* @param inputStream 输入流
|
|
||||||
* @return java.lang.String
|
|
||||||
* @apiNote
|
|
||||||
* @since 2023/8/25 17:17
|
|
||||||
*/
|
|
||||||
protected JsonNode getConfigJson(InputStream inputStream) {
|
|
||||||
StringBuffer jsonData = new StringBuffer();
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
jsonData.append(line);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
PopUpUtil.errorAlert("错误", "读写错误", "配置文件读写错误!");
|
|
||||||
}
|
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
JsonNode jsonNode;
|
|
||||||
try {
|
|
||||||
jsonNode = objectMapper.readTree(jsonData.toString());
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new AppException(e.getMessage());
|
|
||||||
}
|
|
||||||
return jsonNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void load() {
|
|
||||||
// 判断是否存在这个配置文件
|
|
||||||
try (InputStream inputStream = new FileInputStream(CONFIG_NAME)) {
|
|
||||||
logger.info("正在加载配置文件...");
|
|
||||||
// 存在则加载
|
|
||||||
loadConfig(inputStream);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.info("未检测到配置文件!");
|
|
||||||
// 不存在则创建
|
|
||||||
createConfig();
|
|
||||||
try {
|
|
||||||
// 创建后重新加载
|
|
||||||
loadConfig(new FileInputStream(CONFIG_NAME));
|
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
throw new AppException(ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析配置文件
|
|
||||||
*
|
|
||||||
* @param inputStream 输入流
|
|
||||||
* @return T
|
|
||||||
* @since 2023/8/25 15:18
|
|
||||||
*/
|
|
||||||
protected abstract T parseConfig(InputStream inputStream);
|
|
||||||
|
|
||||||
private void createConfig() {
|
|
||||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(CONFIG_NAME))) {
|
|
||||||
writer.write(JNOTEPAD_CONFIG);
|
|
||||||
} catch (IOException e) {
|
|
||||||
PopUpUtil.errorAlert("错误", "读写错误", "配置文件读写错误!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载配置文件
|
|
||||||
*
|
|
||||||
* @param inputStream 配置文件的输入流
|
|
||||||
*/
|
|
||||||
protected abstract void loadConfig(InputStream inputStream);
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.app.init;
|
|
||||||
|
|
||||||
import org.jcnc.jnotepad.app.config.LocalizationConfig;
|
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
|
||||||
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
|
||||||
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载语言配置文件
|
|
||||||
*
|
|
||||||
* @author gewuyou
|
|
||||||
*/
|
|
||||||
public class LoadLanguageConfig extends LoadJnotepadConfig<String> {
|
|
||||||
Logger log = LogUtil.getLogger(this.getClass());
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String parseConfig(InputStream inputStream) {
|
|
||||||
return getConfigJson(inputStream).get("language").asText();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void loadConfig(InputStream inputStream) {
|
|
||||||
log.info("正在加载语言配置文件...");
|
|
||||||
String language = parseConfig(inputStream);
|
|
||||||
if (!"".equals(language) && language != null) {
|
|
||||||
log.info("正在加载语言包:{}", language);
|
|
||||||
// 刷新语言包
|
|
||||||
LocalizationConfig.setCurrentLocal(language);
|
|
||||||
JNotepadMenuBar jNotepadMenuBar = JNotepadMenuBar.getMenuBar();
|
|
||||||
// 刷新菜单栏
|
|
||||||
jNotepadMenuBar.toggleLanguageCheck(language);
|
|
||||||
JNotepadStatusBox.getInstance().initStatusBox();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.app.init;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import javafx.scene.control.MenuItem;
|
|
||||||
import javafx.scene.input.KeyCombination;
|
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
|
||||||
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static org.jcnc.jnotepad.constants.AppConstants.CONFIG_SHORTCUT_KEY_NAME;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载快捷键实现
|
|
||||||
*
|
|
||||||
* @author gewuyou 一个大转盘
|
|
||||||
*/
|
|
||||||
public class LoadShortcutKeyConfig extends LoadJnotepadConfig<List<LinkedHashMap<String, String>>> {
|
|
||||||
Logger log = LogUtil.getLogger(this.getClass());
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<LinkedHashMap<String, String>> parseConfig(InputStream inputStream) {
|
|
||||||
JsonNode shortcutKeyNode = getConfigJson(inputStream).get(CONFIG_SHORTCUT_KEY_NAME);
|
|
||||||
if (shortcutKeyNode == null || !shortcutKeyNode.isArray()) {
|
|
||||||
logger.error("未获取到主要配置文件!");
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
List<LinkedHashMap<String, String>> shortcutKeyList = new ArrayList<>();
|
|
||||||
for (JsonNode node : shortcutKeyNode) {
|
|
||||||
if (node.isObject()) {
|
|
||||||
LinkedHashMap<String, String> shortcutKey = new LinkedHashMap<>();
|
|
||||||
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
|
|
||||||
while (fields.hasNext()) {
|
|
||||||
Map.Entry<String, JsonNode> entry = fields.next();
|
|
||||||
shortcutKey.put(entry.getKey(), entry.getValue().asText());
|
|
||||||
|
|
||||||
}
|
|
||||||
shortcutKeyList.add(shortcutKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return shortcutKeyList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void loadConfig(InputStream inputStream) {
|
|
||||||
List<LinkedHashMap<String, String>> configData = parseConfig(inputStream);
|
|
||||||
for (LinkedHashMap<String, String> shortcutKey : configData) {
|
|
||||||
// 保证json的key必须和变量名一致
|
|
||||||
MenuItem menuItem = JNotepadMenuBar.getMenuBar().getItemMap().get(shortcutKey.get("buttonName"));
|
|
||||||
String shortKeyValue = shortcutKey.get("shortcutKeyValue");
|
|
||||||
if ("".equals(shortKeyValue) || Objects.isNull(menuItem)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
log.info("功能名称:{}->快捷键:{}", menuItem.getText(), shortKeyValue);
|
|
||||||
// 动态添加快捷键
|
|
||||||
menuItem.setAccelerator(KeyCombination.keyCombination(shortKeyValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -23,13 +23,4 @@ public class AppConstants {
|
|||||||
*/
|
*/
|
||||||
public static final String APP_ICON = "/img/icon.png";
|
public static final String APP_ICON = "/img/icon.png";
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置文件名
|
|
||||||
*/
|
|
||||||
public static final String CONFIG_NAME = "jnotepadConfig.json";
|
|
||||||
/**
|
|
||||||
* 快捷键
|
|
||||||
*/
|
|
||||||
public static final String CONFIG_SHORTCUT_KEY_NAME = "shortcutKey";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.constants;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 路径常量<br>
|
|
||||||
* @author gewuyou
|
|
||||||
*/
|
|
||||||
public class PathConstants {
|
|
||||||
private PathConstants() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +1,6 @@
|
|||||||
package org.jcnc.jnotepad.constants;
|
package org.jcnc.jnotepad.constants;
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import org.jcnc.jnotepad.exception.AppException;
|
|
||||||
import org.jcnc.jnotepad.json.DataGenerator;
|
|
||||||
import org.jcnc.jnotepad.json.MyData;
|
|
||||||
import org.jcnc.jnotepad.tool.JsonUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文本常量,被多处使用的常量放到此处。如果只有一个class使用,在class中使用private static final声明。
|
* 文本常量,被多处使用的常量放到此处。如果只有一个class使用,在class中使用private static final声明。
|
||||||
*
|
*
|
||||||
@ -50,38 +41,4 @@ public class TextConstants {
|
|||||||
|
|
||||||
public static final String CHINESE = "chinese";
|
public static final String CHINESE = "chinese";
|
||||||
|
|
||||||
public static final String LOWER_LANGUAGE = "language";
|
|
||||||
|
|
||||||
/// 配置文件文本常量
|
|
||||||
/**
|
|
||||||
* 内置配置文件
|
|
||||||
*/
|
|
||||||
public static final String JNOTEPAD_CONFIG;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
JNOTEPAD_CONFIG = createShortcutKeyJsonString();
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new AppException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createShortcutKeyJsonString() throws JsonProcessingException {
|
|
||||||
return JsonUtil.toJsonString(createShortcutKeyJson());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ObjectNode createShortcutKeyJson() throws JsonProcessingException {
|
|
||||||
MyData myData = DataGenerator.generateMyData();
|
|
||||||
|
|
||||||
// 创建 ObjectMapper 和 ObjectWriter 来将对象转换为 JSON
|
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
ObjectWriter writer = objectMapper.writerWithDefaultPrettyPrinter();
|
|
||||||
|
|
||||||
// 将 MyData 对象转换为 JSON 字符串
|
|
||||||
String json = writer.writeValueAsString(myData);
|
|
||||||
|
|
||||||
// 将 JSON 字符串转换为 ObjectNode 对象
|
|
||||||
|
|
||||||
return objectMapper.readValue(json, ObjectNode.class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,154 @@
|
|||||||
|
package org.jcnc.jnotepad.controller.config;
|
||||||
|
|
||||||
|
import org.jcnc.jnotepad.app.config.AppConfig;
|
||||||
|
import org.jcnc.jnotepad.exception.AppException;
|
||||||
|
import org.jcnc.jnotepad.tool.JsonUtil;
|
||||||
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
|
import org.jcnc.jnotepad.tool.PopUpUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AppConfigController {
|
||||||
|
|
||||||
|
private static final Logger logger = LogUtil.getLogger(AppConfigController.class);
|
||||||
|
|
||||||
|
private static final AppConfigController INSTANCE = new AppConfigController();
|
||||||
|
|
||||||
|
public static AppConfigController getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置文件名
|
||||||
|
*/
|
||||||
|
public static final String CONFIG_NAME = "jnotepadConfig.json";
|
||||||
|
|
||||||
|
private AppConfig appConfig;
|
||||||
|
private String dir;
|
||||||
|
|
||||||
|
private AppConfigController() {
|
||||||
|
setDir(Paths.get(System.getProperty("user.home"), ".jnotepad").toString());
|
||||||
|
loadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载配置文件内容
|
||||||
|
*/
|
||||||
|
public void loadConfig() {
|
||||||
|
createConfigIfNotExists();
|
||||||
|
Path configPath = getConfigPath();
|
||||||
|
|
||||||
|
try {
|
||||||
|
logger.info("正在加载配置文件...");
|
||||||
|
// 存在则加载
|
||||||
|
String configContent = Files.readString(configPath);
|
||||||
|
appConfig = JsonUtil.OBJECT_MAPPER.readValue(configContent, AppConfig.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("加载配置文件错误", e);
|
||||||
|
throw new AppException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置文件持久化
|
||||||
|
*/
|
||||||
|
public void writeAppConfig() {
|
||||||
|
createConfigIfNotExists();
|
||||||
|
writeAppConfig(this.appConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将appConfig对象持久化到配置文件中
|
||||||
|
*
|
||||||
|
* @param appConfig 应用配置对象
|
||||||
|
*/
|
||||||
|
private void writeAppConfig(AppConfig appConfig) {
|
||||||
|
try (BufferedWriter writer = new BufferedWriter(new FileWriter(getConfigPath().toString()))) {
|
||||||
|
if (appConfig == null) {
|
||||||
|
appConfig = createShortcutKeyJson();
|
||||||
|
}
|
||||||
|
writer.write(JsonUtil.toJsonString(appConfig));
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("", e);
|
||||||
|
PopUpUtil.errorAlert("错误", "读写错误", "配置文件读写错误!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createConfigIfNotExists() {
|
||||||
|
Path configPath = getConfigPath();
|
||||||
|
if (configPath.toFile().exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File directory = new File(dir);
|
||||||
|
if (!directory.exists()) {
|
||||||
|
directory.mkdirs();
|
||||||
|
}
|
||||||
|
writeAppConfig(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getConfigPath() {
|
||||||
|
return Paths.get(getDir(), CONFIG_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppConfig createShortcutKeyJson() {
|
||||||
|
return AppConfig.generateDefaultAppConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前配置文件所在目录
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getDir() {
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDir(String dir) {
|
||||||
|
this.dir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppConfig getAppConfig() {
|
||||||
|
return appConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取自动换行设置,默认自动换行
|
||||||
|
*
|
||||||
|
* @return true, 自动换行;false,不自动换行
|
||||||
|
*/
|
||||||
|
public boolean getAutoLineConfig() {
|
||||||
|
return getAppConfig().isTextWrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoLineConfig(boolean isAutoLine) {
|
||||||
|
getAppConfig().setTextWrap(isAutoLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新配置文件中的语言设置
|
||||||
|
*
|
||||||
|
* @param language 更新后的语言设置
|
||||||
|
*/
|
||||||
|
public void updateLanguage(String language) {
|
||||||
|
if (getLanguage().equals(language)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.appConfig.setLanguage(language);
|
||||||
|
writeAppConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLanguage() {
|
||||||
|
return this.appConfig.getLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AppConfig.ShortcutKey> getShortcutKey() {
|
||||||
|
return this.appConfig.getShortcutKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.controller.event.handler;
|
|
||||||
|
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.event.EventHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本地化处理抽象类
|
|
||||||
*
|
|
||||||
* @author gewuyou
|
|
||||||
*/
|
|
||||||
public abstract class LocalizationHandler implements EventHandler<ActionEvent> {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -27,10 +27,15 @@ public class NewFile implements EventHandler<ActionEvent> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void handle(ActionEvent event) {
|
public void handle(ActionEvent event) {
|
||||||
|
addNewFileTab();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNewFileTab() {
|
||||||
// 创建一个新的文本编辑区
|
// 创建一个新的文本编辑区
|
||||||
LineNumberTextArea textArea = new LineNumberTextArea();
|
LineNumberTextArea textArea = new LineNumberTextArea();
|
||||||
|
// 设置当前标签页与本地文件无关联
|
||||||
|
textArea.setRelevance(false);
|
||||||
// TODO: refactor:统一TextArea新建、绑定监听器入口
|
// TODO: refactor:统一TextArea新建、绑定监听器入口
|
||||||
ViewManager viewManager = ViewManager.getInstance();
|
ViewManager viewManager = ViewManager.getInstance();
|
||||||
// 将Tab页添加到TabPane中
|
// 将Tab页添加到TabPane中
|
||||||
|
|||||||
@ -1,30 +1,24 @@
|
|||||||
package org.jcnc.jnotepad.controller.event.handler;
|
package org.jcnc.jnotepad.controller.event.handler;
|
||||||
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
import org.jcnc.jnotepad.controller.manager.Controller;
|
|
||||||
import org.jcnc.jnotepad.manager.ThreadPoolManager;
|
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import static org.jcnc.jnotepad.constants.AppConstants.CONFIG_NAME;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开配置文件事件
|
* 打开配置文件事件
|
||||||
*
|
*
|
||||||
* @author gewuyou
|
* @author gewuyou
|
||||||
*/
|
*/
|
||||||
public class OpenConfig implements EventHandler<ActionEvent> {
|
public class OpenConfig extends OpenFile {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(ActionEvent actionEvent) {
|
public void handle(ActionEvent actionEvent) {
|
||||||
Controller controller = Controller.getInstance();
|
|
||||||
// 显示文件选择对话框,并获取配置文件
|
// 显示文件选择对话框,并获取配置文件
|
||||||
File file = new File(CONFIG_NAME);
|
File file = AppConfigController.getInstance().getConfigPath().toFile();
|
||||||
LogUtil.getLogger(this.getClass()).info("已调用打开配置文件功能");
|
LogUtil.getLogger(this.getClass()).info("已调用打开配置文件功能,{}", file);
|
||||||
LogUtil.getLogger(this.getClass()).info("{}", file);
|
|
||||||
// 创建打开文件的任务并启动线程执行任务
|
// 创建打开文件的任务并启动线程执行任务
|
||||||
ThreadPoolManager.getThreadPool().submit(controller.createOpenFileTask(file));
|
openFile(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,24 @@
|
|||||||
package org.jcnc.jnotepad.controller.event.handler;
|
package org.jcnc.jnotepad.controller.event.handler;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
|
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.controller.manager.Controller;
|
|
||||||
import org.jcnc.jnotepad.manager.ThreadPoolManager;
|
import org.jcnc.jnotepad.manager.ThreadPoolManager;
|
||||||
|
import org.jcnc.jnotepad.tool.EncodingDetector;
|
||||||
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
||||||
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import static org.jcnc.jnotepad.manager.ThreadPoolManager.threadContSelfSubtracting;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,15 +36,96 @@ public class OpenFile implements EventHandler<ActionEvent> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void handle(ActionEvent event) {
|
public void handle(ActionEvent event) {
|
||||||
// 获取控制器
|
|
||||||
Controller controller = Controller.getInstance();
|
|
||||||
// 创建文件选择器
|
// 创建文件选择器
|
||||||
FileChooser fileChooser = new FileChooser();
|
FileChooser fileChooser = new FileChooser();
|
||||||
// 显示文件选择对话框,并获取选中的文件
|
// 显示文件选择对话框,并获取选中的文件
|
||||||
File file = fileChooser.showOpenDialog(null);
|
File file = fileChooser.showOpenDialog(null);
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
// 创建打开文件的任务并启动线程执行任务
|
openFile(file);
|
||||||
ThreadPoolManager.getThreadPool().submit(controller.createOpenFileTask(file));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建打开文件的任务。
|
||||||
|
*
|
||||||
|
* @param file 文件对象
|
||||||
|
* @return 打开文件的任务
|
||||||
|
*/
|
||||||
|
public Task<Void> createOpenFileTask(File file) {
|
||||||
|
Task<Void> openFileTask = new Task<>() {
|
||||||
|
@Override
|
||||||
|
protected Void call() {
|
||||||
|
getText(file);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
// 设置任务成功完成时的处理逻辑
|
||||||
|
openFileTask.setOnSucceeded(e -> threadContSelfSubtracting());
|
||||||
|
|
||||||
|
// 设置任务失败时的处理逻辑
|
||||||
|
openFileTask.setOnFailed(e -> threadContSelfSubtracting());
|
||||||
|
return openFileTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开文件。
|
||||||
|
*
|
||||||
|
* @param file 文件对象
|
||||||
|
*/
|
||||||
|
protected void openFile(File file) {
|
||||||
|
ThreadPoolManager.getThreadPool().submit(createOpenFileTask(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取文本文件的内容。
|
||||||
|
*
|
||||||
|
* @param file 文件对象
|
||||||
|
*/
|
||||||
|
public void getText(File file) {
|
||||||
|
LineNumberTextArea textArea = createNewTextArea();
|
||||||
|
// 设置当前标签页关联本地文件
|
||||||
|
textArea.setRelevance(true);
|
||||||
|
// 检测文件编码
|
||||||
|
Charset encoding = EncodingDetector.detectEncodingCharset(file);
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
|
||||||
|
StringBuilder textBuilder = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
textBuilder.append(line).append("\n");
|
||||||
|
}
|
||||||
|
String text = textBuilder.toString();
|
||||||
|
LogUtil.getLogger(this.getClass()).info("已调用读取文件功能");
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
textArea.getMainTextArea().setText(text);
|
||||||
|
JNotepadTab tab = createNewTab(file.getName(), textArea, encoding);
|
||||||
|
tab.setUserData(file);
|
||||||
|
JNotepadTabPane.getInstance().addNewTab(tab);
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新的文本区域。
|
||||||
|
*
|
||||||
|
* @return 新的文本区域
|
||||||
|
*/
|
||||||
|
private LineNumberTextArea createNewTextArea() {
|
||||||
|
return new LineNumberTextArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新的标签页。
|
||||||
|
*
|
||||||
|
* @param tabName 标签名
|
||||||
|
* @param textArea 文本区域
|
||||||
|
* @return 新的标签页
|
||||||
|
*/
|
||||||
|
private JNotepadTab createNewTab(String tabName, LineNumberTextArea textArea, Charset charset) {
|
||||||
|
return new JNotepadTab(tabName, textArea, charset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,8 @@
|
|||||||
package org.jcnc.jnotepad.controller.event.handler;
|
package org.jcnc.jnotepad.controller.event.handler;
|
||||||
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
|
|
||||||
import static org.jcnc.jnotepad.tool.FileUtil.saveTab;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存文件事件处理器。
|
* 保存文件事件处理器。
|
||||||
@ -17,7 +14,7 @@ import static org.jcnc.jnotepad.tool.FileUtil.saveTab;
|
|||||||
*
|
*
|
||||||
* @author 许轲
|
* @author 许轲
|
||||||
*/
|
*/
|
||||||
public class SaveAsFile implements EventHandler<ActionEvent> {
|
public class SaveAsFile extends SaveFile {
|
||||||
/**
|
/**
|
||||||
* 处理保存文件事件。
|
* 处理保存文件事件。
|
||||||
*
|
*
|
||||||
|
|||||||
@ -2,16 +2,19 @@ package org.jcnc.jnotepad.controller.event.handler;
|
|||||||
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import org.jcnc.jnotepad.LunchApp;
|
import javafx.stage.FileChooser;
|
||||||
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
|
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
import org.jcnc.jnotepad.view.init.View;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import static org.jcnc.jnotepad.constants.AppConstants.CONFIG_NAME;
|
import java.io.File;
|
||||||
import static org.jcnc.jnotepad.tool.FileUtil.saveTab;
|
|
||||||
|
import static org.jcnc.jnotepad.controller.config.AppConfigController.CONFIG_NAME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存文件
|
* 保存文件
|
||||||
@ -47,10 +50,42 @@ public class SaveFile implements EventHandler<ActionEvent> {
|
|||||||
// 如果该文件是配置文件则刷新快捷键
|
// 如果该文件是配置文件则刷新快捷键
|
||||||
if (CONFIG_NAME.equals(selectedTab.getText())) {
|
if (CONFIG_NAME.equals(selectedTab.getText())) {
|
||||||
// 重新加载语言包和快捷键
|
// 重新加载语言包和快捷键
|
||||||
View.getInstance().initJnotepadConfigs(LunchApp.getLocalizationConfigs());
|
AppConfigController.getInstance().loadConfig();
|
||||||
|
JNotepadMenuBar.getMenuBar().initShortcutKeys();
|
||||||
|
LocalizationController.initLocal();
|
||||||
logger.info("已刷新语言包!");
|
logger.info("已刷新语言包!");
|
||||||
logger.info("已刷新快捷键!");
|
logger.info("已刷新快捷键!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存页面方法
|
||||||
|
*
|
||||||
|
* @param currentClass 调用该方法的类
|
||||||
|
* @apiNote 将当前选中的标签页进行弹出窗口式的保存
|
||||||
|
* @see LogUtil
|
||||||
|
*/
|
||||||
|
protected void saveTab(Class<?> currentClass) {
|
||||||
|
JNotepadTab selectedTab = JNotepadTabPane.getInstance().getSelected();
|
||||||
|
if (selectedTab != null) {
|
||||||
|
// 创建一个文件窗口
|
||||||
|
FileChooser fileChooser = new FileChooser();
|
||||||
|
// 设置保存文件名称
|
||||||
|
fileChooser.setInitialFileName(selectedTab.getText());
|
||||||
|
// 设置保存文件类型
|
||||||
|
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt"));
|
||||||
|
File file = fileChooser.showSaveDialog(null);
|
||||||
|
if (file != null) {
|
||||||
|
LogUtil.getLogger(currentClass).info("正在保存文件:{}", file.getName());
|
||||||
|
selectedTab.save();
|
||||||
|
// 将保存后的文件设置为已关联
|
||||||
|
selectedTab.getLineNumberTextArea().setRelevance(true);
|
||||||
|
// 更新Tab页标签上的文件名
|
||||||
|
selectedTab.setText(file.getName());
|
||||||
|
// 将文件对象保存到Tab页的UserData中
|
||||||
|
selectedTab.setUserData(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
package org.jcnc.jnotepad.app.config;
|
package org.jcnc.jnotepad.controller.i18n;
|
||||||
|
|
||||||
import org.jcnc.jnotepad.LunchApp;
|
import org.jcnc.jnotepad.LunchApp;
|
||||||
import org.jcnc.jnotepad.app.i18n.UIResourceBundle;
|
import org.jcnc.jnotepad.app.i18n.UIResourceBundle;
|
||||||
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -18,9 +19,9 @@ import static org.jcnc.jnotepad.constants.TextConstants.ENGLISH;
|
|||||||
* @author gewuyou
|
* @author gewuyou
|
||||||
* @see LunchApp
|
* @see LunchApp
|
||||||
*/
|
*/
|
||||||
public class LocalizationConfig {
|
public class LocalizationController {
|
||||||
private static final LocalizationConfig LOCALIZATION_CONFIG = new LocalizationConfig();
|
private static final LocalizationController LOCALIZATION_CONFIG = new LocalizationController();
|
||||||
private String language;
|
|
||||||
private static final Map<String, Locale> SUPPORT_LOCALES;
|
private static final Map<String, Locale> SUPPORT_LOCALES;
|
||||||
private static final Map<Locale, String> SUPPORT_LANGUAGES;
|
private static final Map<Locale, String> SUPPORT_LANGUAGES;
|
||||||
|
|
||||||
@ -39,44 +40,52 @@ public class LocalizationConfig {
|
|||||||
return Locale.getDefault();
|
return Locale.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化语言配置
|
||||||
|
*/
|
||||||
|
public static void initLocal() {
|
||||||
|
setCurrentLocal(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前语言配置
|
||||||
|
*
|
||||||
|
* @param locale 当前语言Local对象
|
||||||
|
*/
|
||||||
public static void setCurrentLocal(Locale locale) {
|
public static void setCurrentLocal(Locale locale) {
|
||||||
|
if (locale != null && locale.equals(getCurrentLocal())) {
|
||||||
|
// 要更新的语言与当前语言一致,则不执行
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (locale == null) {
|
||||||
|
locale = SUPPORT_LOCALES.get(LOCALIZATION_CONFIG.getLanguage());
|
||||||
|
}
|
||||||
|
if (locale == null) {
|
||||||
|
locale = getCurrentLocal();
|
||||||
|
}
|
||||||
Locale.setDefault(locale);
|
Locale.setDefault(locale);
|
||||||
UIResourceBundle.getInstance().resetLocal();
|
|
||||||
|
UIResourceBundle.getInstance().resetLocal(getCurrentLocal());
|
||||||
LOCALIZATION_CONFIG.setLanguage(SUPPORT_LANGUAGES.get(locale));
|
LOCALIZATION_CONFIG.setLanguage(SUPPORT_LANGUAGES.get(locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setCurrentLocal(String language) {
|
private LocalizationController() {
|
||||||
Locale locale = SUPPORT_LOCALES.get(language);
|
this.appConfigController = AppConfigController.getInstance();
|
||||||
if (locale != null) {
|
|
||||||
setCurrentLocal(locale);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalizationConfig() {
|
private final AppConfigController appConfigController;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String textWrap;
|
|
||||||
|
|
||||||
|
|
||||||
public static LocalizationConfig getLocalizationConfig() {
|
|
||||||
return LOCALIZATION_CONFIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getTextWrap() {
|
|
||||||
return textWrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTextWrap(String textWrap) {
|
|
||||||
this.textWrap = textWrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setLanguage(String language) {
|
private void setLanguage(String language) {
|
||||||
this.language = language;
|
appConfigController.updateLanguage(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询当前语言配置
|
||||||
|
*
|
||||||
|
* @return appConfig中的当前语言配置
|
||||||
|
*/
|
||||||
public String getLanguage() {
|
public String getLanguage() {
|
||||||
return this.language;
|
return appConfigController.getLanguage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,27 +1,12 @@
|
|||||||
package org.jcnc.jnotepad.controller.manager;
|
package org.jcnc.jnotepad.controller.manager;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.concurrent.Task;
|
|
||||||
import org.jcnc.jnotepad.Interface.ControllerInterface;
|
import org.jcnc.jnotepad.Interface.ControllerInterface;
|
||||||
import org.jcnc.jnotepad.app.i18n.UIResourceBundle;
|
import org.jcnc.jnotepad.controller.event.handler.NewFile;
|
||||||
import org.jcnc.jnotepad.constants.TextConstants;
|
import org.jcnc.jnotepad.controller.event.handler.OpenFile;
|
||||||
import org.jcnc.jnotepad.manager.ThreadPoolManager;
|
|
||||||
import org.jcnc.jnotepad.tool.EncodingDetector;
|
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
|
||||||
import org.jcnc.jnotepad.view.manager.ViewManager;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jcnc.jnotepad.manager.ThreadPoolManager.threadContSelfSubtracting;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 控制器类,实现ControllerInterface接口,用于管理文本编辑器的各种操作和事件处理。
|
* 控制器类,实现ControllerInterface接口,用于管理文本编辑器的各种操作和事件处理。
|
||||||
* 包括打开关联文件、创建文本区域、处理行分隔、新建文件、打开文件、自动保存等功能。
|
* 包括打开关联文件、创建文本区域、处理行分隔、新建文件、打开文件、自动保存等功能。
|
||||||
@ -46,17 +31,12 @@ public class Controller implements ControllerInterface {
|
|||||||
* @return 创建的文本区域
|
* @return 创建的文本区域
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public LineNumberTextArea openAssociatedFileAndCreateTextArea(List<String> rawParameters) {
|
public void openAssociatedFileAndCreateTextArea(List<String> rawParameters) {
|
||||||
if (!rawParameters.isEmpty()) {
|
if (!rawParameters.isEmpty()) {
|
||||||
String filePath = rawParameters.get(0);
|
String filePath = rawParameters.get(0);
|
||||||
openAssociatedFile(filePath);
|
openAssociatedFile(filePath);
|
||||||
return null;
|
|
||||||
} else {
|
} else {
|
||||||
LineNumberTextArea textArea = createNewTextArea();
|
new NewFile().addNewFileTab();
|
||||||
// 设置当前标签页与本地文件无关联
|
|
||||||
textArea.setRelevance(false);
|
|
||||||
configureTextArea(textArea);
|
|
||||||
return textArea;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,116 +49,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()) {
|
||||||
openFile(file);
|
new OpenFile().createOpenFileTask(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取文本文件的内容。
|
|
||||||
*
|
|
||||||
* @param file 文件对象
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void getText(File file) {
|
|
||||||
LineNumberTextArea textArea = createNewTextArea();
|
|
||||||
// 设置当前标签页关联本地文件
|
|
||||||
textArea.setRelevance(true);
|
|
||||||
// 检测文件编码
|
|
||||||
Charset encoding = EncodingDetector.detectEncodingCharset(file);
|
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
|
|
||||||
StringBuilder textBuilder = new StringBuilder();
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
textBuilder.append(line).append("\n");
|
|
||||||
}
|
|
||||||
String text = textBuilder.toString();
|
|
||||||
LogUtil.getLogger(this.getClass()).info("已调用读取文件功能");
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
textArea.getMainTextArea().setText(text);
|
|
||||||
JNotepadTab tab = createNewTab(file.getName(), textArea, encoding);
|
|
||||||
tab.setUserData(file);
|
|
||||||
JNotepadTabPane.getInstance().addNewTab(tab);
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新UI和标签页
|
|
||||||
*
|
|
||||||
* @param textArea 文本域
|
|
||||||
* @apiNote
|
|
||||||
* @since 2023/8/20 12:40
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void updateUiWithNewTextArea(LineNumberTextArea textArea) {
|
|
||||||
ViewManager viewManager = ViewManager.getInstance();
|
|
||||||
String tabTitle = UIResourceBundle.getContent(TextConstants.NEW_FILE) + viewManager.selfIncreaseAndGetTabIndex();
|
|
||||||
JNotepadTabPane.getInstance().addNewTab(new JNotepadTab(tabTitle, textArea));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置文本区域。
|
|
||||||
*
|
|
||||||
* @param textArea 文本区域
|
|
||||||
*/
|
|
||||||
private void configureTextArea(LineNumberTextArea textArea) {
|
|
||||||
textArea.getMainTextArea().setWrapText(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建新的文本区域。
|
|
||||||
*
|
|
||||||
* @return 新的文本区域
|
|
||||||
*/
|
|
||||||
private LineNumberTextArea createNewTextArea() {
|
|
||||||
return new LineNumberTextArea();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建新的标签页。
|
|
||||||
*
|
|
||||||
* @param tabName 标签名
|
|
||||||
* @param textArea 文本区域
|
|
||||||
* @return 新的标签页
|
|
||||||
*/
|
|
||||||
private JNotepadTab createNewTab(String tabName, LineNumberTextArea textArea, Charset charset) {
|
|
||||||
return new JNotepadTab(tabName, textArea, charset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建打开文件的任务。
|
|
||||||
*
|
|
||||||
* @param file 文件对象
|
|
||||||
* @return 打开文件的任务
|
|
||||||
*/
|
|
||||||
public Task<Void> createOpenFileTask(File file) {
|
|
||||||
Task<Void> openFileTask = new Task<>() {
|
|
||||||
@Override
|
|
||||||
protected Void call() {
|
|
||||||
getText(file);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
// 设置任务成功完成时的处理逻辑
|
|
||||||
openFileTask.setOnSucceeded(e -> threadContSelfSubtracting());
|
|
||||||
|
|
||||||
// 设置任务失败时的处理逻辑
|
|
||||||
openFileTask.setOnFailed(e -> threadContSelfSubtracting());
|
|
||||||
return openFileTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开文件。
|
|
||||||
*
|
|
||||||
* @param file 文件对象
|
|
||||||
*/
|
|
||||||
private void openFile(File file) {
|
|
||||||
ThreadPoolManager.getThreadPool().submit(createOpenFileTask(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,59 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.json;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据生成类,用于生成示例数据。
|
|
||||||
* @author 许轲
|
|
||||||
*/
|
|
||||||
public class DataGenerator {
|
|
||||||
|
|
||||||
|
|
||||||
private DataGenerator() {
|
|
||||||
}
|
|
||||||
/// 快捷键常量
|
|
||||||
|
|
||||||
private static final String CTRL_N = "ctrl+n";
|
|
||||||
private static final String CTRL_O = "ctrl+o";
|
|
||||||
private static final String CTRL_S = "ctrl+s";
|
|
||||||
private static final String CTRL_ALT_S = "ctrl+alt+s";
|
|
||||||
private static final String ALT_S = "alt+s";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成示例 MyData 对象。
|
|
||||||
*
|
|
||||||
* @return 示例 MyData 对象
|
|
||||||
*/
|
|
||||||
public static MyData generateMyData() {
|
|
||||||
MyData myData = new MyData();
|
|
||||||
myData.setLanguage("chinese");
|
|
||||||
|
|
||||||
List<MyData.ShortcutKey> shortcutKeys = new ArrayList<>();
|
|
||||||
shortcutKeys.add(createShortcutKey("newItem", CTRL_N));
|
|
||||||
shortcutKeys.add(createShortcutKey("openItem", CTRL_O));
|
|
||||||
shortcutKeys.add(createShortcutKey("saveItem", CTRL_S));
|
|
||||||
shortcutKeys.add(createShortcutKey("saveAsItem", CTRL_ALT_S));
|
|
||||||
shortcutKeys.add(createShortcutKey("lineFeedItem", ""));
|
|
||||||
shortcutKeys.add(createShortcutKey("openConfigItem", ALT_S));
|
|
||||||
shortcutKeys.add(createShortcutKey("addItem", ""));
|
|
||||||
shortcutKeys.add(createShortcutKey("countItem", ""));
|
|
||||||
|
|
||||||
myData.setShortcutKey(shortcutKeys);
|
|
||||||
return myData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 ShortcutKey 对象。
|
|
||||||
*
|
|
||||||
* @param buttonName 按钮名称
|
|
||||||
* @param shortcutKeyValue 快捷键值
|
|
||||||
* @return ShortcutKey 对象
|
|
||||||
*/
|
|
||||||
private static MyData.ShortcutKey createShortcutKey(String buttonName, String shortcutKeyValue) {
|
|
||||||
MyData.ShortcutKey shortcutKey = new MyData.ShortcutKey();
|
|
||||||
shortcutKey.setButtonName(buttonName);
|
|
||||||
shortcutKey.setShortcutKeyValue(shortcutKeyValue);
|
|
||||||
return shortcutKey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.json;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据模型类,用于表示 MyData 对象的数据结构。
|
|
||||||
*
|
|
||||||
* @author 许轲
|
|
||||||
*/
|
|
||||||
public class MyData {
|
|
||||||
private String language;
|
|
||||||
private List<ShortcutKey> shortcutKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ShortcutKey 类,用于表示快捷键信息。
|
|
||||||
*/
|
|
||||||
public static class ShortcutKey {
|
|
||||||
private String buttonName;
|
|
||||||
private String shortcutKeyValue;
|
|
||||||
|
|
||||||
public String getButtonName() {
|
|
||||||
return buttonName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setButtonName(String buttonName) {
|
|
||||||
this.buttonName = buttonName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getShortcutKeyValue() {
|
|
||||||
return shortcutKeyValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShortcutKeyValue(String shortcutKeyValue) {
|
|
||||||
this.shortcutKeyValue = shortcutKeyValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLanguage() {
|
|
||||||
return language;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLanguage(String language) {
|
|
||||||
this.language = language;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ShortcutKey> getShortcutKey() {
|
|
||||||
return shortcutKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShortcutKey(List<ShortcutKey> shortcutKey) {
|
|
||||||
this.shortcutKey = shortcutKey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.tool;
|
|
||||||
|
|
||||||
import javafx.stage.FileChooser;
|
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author 一个大转盘
|
|
||||||
*/
|
|
||||||
public class FileUtil {
|
|
||||||
|
|
||||||
private FileUtil() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把一个文件中的内容读取成一个String字符串<br>
|
|
||||||
*
|
|
||||||
* @param jsonFile json文件
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public static String getJsonStr(File jsonFile) {
|
|
||||||
String jsonStr;
|
|
||||||
try (
|
|
||||||
Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8)
|
|
||||||
) {
|
|
||||||
|
|
||||||
int ch;
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
while ((ch = reader.read()) != -1) {
|
|
||||||
sb.append((char) ch);
|
|
||||||
}
|
|
||||||
jsonStr = sb.toString();
|
|
||||||
return jsonStr;
|
|
||||||
} catch (IOException e) {
|
|
||||||
LogUtil.getLogger(FileUtil.class).error("读取配置失败!", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存页面方法
|
|
||||||
*
|
|
||||||
* @param currentClass 调用该方法的类
|
|
||||||
* @apiNote 将当前选中的标签页进行弹出窗口式的保存
|
|
||||||
* @see LogUtil
|
|
||||||
*/
|
|
||||||
public static void saveTab(Class<?> currentClass) {
|
|
||||||
JNotepadTab selectedTab = JNotepadTabPane.getInstance().getSelected();
|
|
||||||
if (selectedTab != null) {
|
|
||||||
// 创建一个文件窗口
|
|
||||||
FileChooser fileChooser = new FileChooser();
|
|
||||||
// 设置保存文件名称
|
|
||||||
fileChooser.setInitialFileName(selectedTab.getText());
|
|
||||||
// 设置保存文件类型
|
|
||||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("文本文档", "*.txt"));
|
|
||||||
File file = fileChooser.showSaveDialog(null);
|
|
||||||
if (file != null) {
|
|
||||||
LogUtil.getLogger(currentClass).info("正在保存文件:{}", file.getName());
|
|
||||||
selectedTab.save();
|
|
||||||
// 将保存后的文件设置为已关联
|
|
||||||
selectedTab.getLineNumberTextArea().setRelevance(true);
|
|
||||||
// 更新Tab页标签上的文件名
|
|
||||||
selectedTab.setText(file.getName());
|
|
||||||
// 将文件对象保存到Tab页的UserData中
|
|
||||||
selectedTab.setUserData(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -3,7 +3,10 @@ package org.jcnc.jnotepad.ui;
|
|||||||
import javafx.beans.property.StringProperty;
|
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;
|
||||||
|
import org.jcnc.jnotepad.app.config.AppConfig;
|
||||||
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
|
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
||||||
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
|
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
@ -30,6 +33,8 @@ public class LineNumberTextArea extends BorderPane {
|
|||||||
|
|
||||||
public LineNumberTextArea() {
|
public LineNumberTextArea() {
|
||||||
mainTextArea = new TextArea();
|
mainTextArea = new TextArea();
|
||||||
|
mainTextArea.setWrapText(AppConfigController.getInstance().getAutoLineConfig());
|
||||||
|
|
||||||
lineNumberArea = new TextArea();
|
lineNumberArea = new TextArea();
|
||||||
lineNumberArea.setEditable(false);
|
lineNumberArea.setEditable(false);
|
||||||
lineNumberArea.setPrefWidth(MIN_LINE_NUMBER_WIDTH);
|
lineNumberArea.setPrefWidth(MIN_LINE_NUMBER_WIDTH);
|
||||||
|
|||||||
@ -1,31 +1,21 @@
|
|||||||
package org.jcnc.jnotepad.ui.menu;
|
package org.jcnc.jnotepad.ui.menu;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.input.KeyCombination;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.jcnc.jnotepad.LunchApp;
|
import org.jcnc.jnotepad.app.config.AppConfig;
|
||||||
import org.jcnc.jnotepad.app.config.GlobalConfig;
|
|
||||||
import org.jcnc.jnotepad.app.config.LocalizationConfig;
|
|
||||||
import org.jcnc.jnotepad.app.i18n.UIResourceBundle;
|
import org.jcnc.jnotepad.app.i18n.UIResourceBundle;
|
||||||
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
import org.jcnc.jnotepad.controller.event.handler.*;
|
import org.jcnc.jnotepad.controller.event.handler.*;
|
||||||
import org.jcnc.jnotepad.exception.AppException;
|
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
|
||||||
import org.jcnc.jnotepad.tool.JsonUtil;
|
|
||||||
import org.jcnc.jnotepad.tool.LogUtil;
|
import org.jcnc.jnotepad.tool.LogUtil;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
|
||||||
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
|
||||||
import org.jcnc.jnotepad.view.init.View;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import java.io.*;
|
import java.util.*;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static com.fasterxml.jackson.core.JsonEncoding.UTF8;
|
|
||||||
import static org.jcnc.jnotepad.constants.AppConstants.CONFIG_NAME;
|
|
||||||
import static org.jcnc.jnotepad.constants.TextConstants.*;
|
import static org.jcnc.jnotepad.constants.TextConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +32,7 @@ public class JNotepadMenuBar extends MenuBar {
|
|||||||
|
|
||||||
private static final JNotepadMenuBar MENU_BAR = new JNotepadMenuBar();
|
private static final JNotepadMenuBar MENU_BAR = new JNotepadMenuBar();
|
||||||
|
|
||||||
LocalizationConfig localizationConfig = LocalizationConfig.getLocalizationConfig();
|
AppConfigController appConfigController = AppConfigController.getInstance();
|
||||||
Logger logger = LogUtil.getLogger(this.getClass());
|
Logger logger = LogUtil.getLogger(this.getClass());
|
||||||
|
|
||||||
private JNotepadMenuBar() {
|
private JNotepadMenuBar() {
|
||||||
@ -142,6 +132,30 @@ public class JNotepadMenuBar extends MenuBar {
|
|||||||
// 菜单栏
|
// 菜单栏
|
||||||
this.getMenus().addAll(fileMenu, setMenu, pluginMenu);
|
this.getMenus().addAll(fileMenu, setMenu, pluginMenu);
|
||||||
initEventHandlers();
|
initEventHandlers();
|
||||||
|
initShortcutKeys();
|
||||||
|
toggleLanguageCheck(appConfigController.getLanguage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化快捷键。
|
||||||
|
*/
|
||||||
|
public void initShortcutKeys() {
|
||||||
|
List<AppConfig.ShortcutKey> shortcutKeyConfigs = appConfigController.getShortcutKey();
|
||||||
|
//FIXME: 如果shortcutKey不存在,需要解绑已绑定的快捷键
|
||||||
|
for (AppConfig.ShortcutKey shortcutKey : shortcutKeyConfigs) {
|
||||||
|
// 保证json的key必须和变量名一致
|
||||||
|
MenuItem menuItem = this.itemMap.get(shortcutKey.getButtonName());
|
||||||
|
if (Objects.isNull(menuItem)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String shortKeyValue = shortcutKey.getShortcutKeyValue();
|
||||||
|
if ("".equals(shortKeyValue)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
logger.info("功能名称:{}->快捷键:{}", menuItem.getText(), shortKeyValue);
|
||||||
|
// 动态添加快捷键
|
||||||
|
menuItem.setAccelerator(KeyCombination.keyCombination(shortKeyValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -260,7 +274,7 @@ public class JNotepadMenuBar extends MenuBar {
|
|||||||
openConfigItem.setOnAction(new OpenConfig());
|
openConfigItem.setOnAction(new OpenConfig());
|
||||||
lineFeedItem.selectedProperty().addListener((observableValue, before, after) -> {
|
lineFeedItem.selectedProperty().addListener((observableValue, before, after) -> {
|
||||||
// 1. 更新全局配置
|
// 1. 更新全局配置
|
||||||
GlobalConfig.getConfig().setAutoLineConfig(after);
|
AppConfigController.getInstance().setAutoLineConfig(after);
|
||||||
// 2. 对当前tab生效配置
|
// 2. 对当前tab生效配置
|
||||||
jNotepadTabPane.fireTabSelected();
|
jNotepadTabPane.fireTabSelected();
|
||||||
});
|
});
|
||||||
@ -270,31 +284,14 @@ public class JNotepadMenuBar extends MenuBar {
|
|||||||
// 设置窗口为置顶
|
// 设置窗口为置顶
|
||||||
primaryStage.setAlwaysOnTop(after);
|
primaryStage.setAlwaysOnTop(after);
|
||||||
});
|
});
|
||||||
englishItem.setOnAction(new LocalizationHandler() {
|
englishItem.setOnAction(this::toggleLanguage);
|
||||||
@Override
|
chineseItem.setOnAction(this::toggleLanguage);
|
||||||
public void handle(ActionEvent actionEvent) {
|
|
||||||
try {
|
|
||||||
setCurrentLanguage(ENGLISH);
|
|
||||||
toggleLanguage(actionEvent);
|
|
||||||
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new AppException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
chineseItem.setOnAction(new LocalizationHandler() {
|
|
||||||
@Override
|
|
||||||
public void handle(ActionEvent actionEvent) {
|
|
||||||
try {
|
|
||||||
setCurrentLanguage(CHINESE);
|
|
||||||
toggleLanguage(actionEvent);
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new AppException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换语言
|
||||||
|
* @param actionEvent 点击事件
|
||||||
|
*/
|
||||||
private void toggleLanguage(ActionEvent actionEvent) {
|
private void toggleLanguage(ActionEvent actionEvent) {
|
||||||
if (actionEvent == null) {
|
if (actionEvent == null) {
|
||||||
return;
|
return;
|
||||||
@ -303,61 +300,9 @@ public class JNotepadMenuBar extends MenuBar {
|
|||||||
if (languageItem == null) {
|
if (languageItem == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LocalizationConfig.setCurrentLocal((Locale) languageItem.getUserData());
|
LocalizationController.setCurrentLocal((Locale) languageItem.getUserData());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置当前语言<br>
|
|
||||||
*
|
|
||||||
* @param language 要设置的语言
|
|
||||||
* @since 2023/8/26 16:16
|
|
||||||
*/
|
|
||||||
private void setCurrentLanguage(String language) throws JsonProcessingException {
|
|
||||||
// 如果当前已是该语言则不执行该方法
|
|
||||||
if (localizationConfig.getLanguage().equals(language)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
boolean flag = false;
|
|
||||||
// 获取本地配置文件
|
|
||||||
logger.info("尝试读取本地配置文件!");
|
|
||||||
StringBuilder jsonData = new StringBuilder();
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(CONFIG_NAME)))) {
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
jsonData.append(line);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("读取失败,配置文件错误或不存在配置文件!");
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
ObjectNode json;
|
|
||||||
|
|
||||||
if (!flag) {
|
|
||||||
json = JsonUtil.OBJECT_MAPPER.readValue(jsonData.toString(), ObjectNode.class);
|
|
||||||
logger.info("读取本地配置文件成功!");
|
|
||||||
} else {
|
|
||||||
logger.info("获取默认内置配置文件!");
|
|
||||||
// 如果读取本地失败则获取默认配置文件
|
|
||||||
json = createShortcutKeyJson();
|
|
||||||
}
|
|
||||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(CONFIG_NAME, Charset.forName(UTF8.name())))) {
|
|
||||||
// 更新语言值为 language 并写回本地
|
|
||||||
json.put(LOWER_LANGUAGE, language);
|
|
||||||
writer.write(JsonUtil.toJsonString(json));
|
|
||||||
// 刷新文件
|
|
||||||
writer.flush();
|
|
||||||
// 重新加载快捷键与语言包
|
|
||||||
View.getInstance().initJnotepadConfigs(LunchApp.getLocalizationConfigs());
|
|
||||||
logger.info("已刷新语言包!");
|
|
||||||
logger.info("已刷新快捷键!");
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("配置文件写入失败,请检查配置文件");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, MenuItem> getItemMap() {
|
|
||||||
return itemMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据当前选中tab,更新菜单选项
|
* 根据当前选中tab,更新菜单选项
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package org.jcnc.jnotepad.ui.tab;
|
package org.jcnc.jnotepad.ui.tab;
|
||||||
|
|
||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
import org.jcnc.jnotepad.app.config.GlobalConfig;
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
import org.jcnc.jnotepad.ui.LineNumberTextArea;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
@ -33,7 +33,7 @@ public class JNotepadTab extends Tab {
|
|||||||
super(tabTitle);
|
super(tabTitle);
|
||||||
lineNumberTextArea = textArea;
|
lineNumberTextArea = textArea;
|
||||||
this.setContent(lineNumberTextArea);
|
this.setContent(lineNumberTextArea);
|
||||||
setAutoLine(GlobalConfig.getConfig().getAutoLineConfig());
|
setAutoLine(AppConfigController.getInstance().getAutoLineConfig());
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package org.jcnc.jnotepad.ui.tab;
|
package org.jcnc.jnotepad.ui.tab;
|
||||||
|
|
||||||
import javafx.scene.control.TabPane;
|
import javafx.scene.control.TabPane;
|
||||||
import org.jcnc.jnotepad.app.config.GlobalConfig;
|
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||||
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
|
||||||
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
|
import org.jcnc.jnotepad.ui.status.JNotepadStatusBox;
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ public class JNotepadTabPane extends TabPane {
|
|||||||
*/
|
*/
|
||||||
public void fireTabSelected() {
|
public void fireTabSelected() {
|
||||||
JNotepadTab selectedTab = getSelected();
|
JNotepadTab selectedTab = getSelected();
|
||||||
selectedTab.setAutoLine(GlobalConfig.getConfig().getAutoLineConfig());
|
selectedTab.setAutoLine(AppConfigController.getInstance().getAutoLineConfig());
|
||||||
JNotepadStatusBox.getInstance().updateWhenTabSelected();
|
JNotepadStatusBox.getInstance().updateWhenTabSelected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,43 +0,0 @@
|
|||||||
package org.jcnc.jnotepad.view.init;
|
|
||||||
|
|
||||||
import org.jcnc.jnotepad.app.init.LoadJnotepadConfig;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author 许轲
|
|
||||||
*/
|
|
||||||
public class View {
|
|
||||||
|
|
||||||
private View() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final View INSTANCE = new View();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化配置文件
|
|
||||||
*
|
|
||||||
* @param loadJnotepadConfigs 需要加载的配置文件数组
|
|
||||||
* @since 2023/8/24 15:29
|
|
||||||
*/
|
|
||||||
public void initJnotepadConfigs(List<LoadJnotepadConfig<?>> loadJnotepadConfigs) {
|
|
||||||
for (LoadJnotepadConfig<?> loadJnotepadConfig : loadJnotepadConfigs) {
|
|
||||||
initJnotepadConfig(loadJnotepadConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化配置文件
|
|
||||||
*
|
|
||||||
* @param loadJnotepadConfig 配置文件
|
|
||||||
* @since 2023/8/24 15:29
|
|
||||||
*/
|
|
||||||
public void initJnotepadConfig(LoadJnotepadConfig<?> loadJnotepadConfig) {
|
|
||||||
loadJnotepadConfig.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static View getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user