Compare commits
81 Commits
master
...
release-v1
| Author | SHA1 | Date | |
|---|---|---|---|
| e4bb8cfa17 | |||
|
|
98ee99168b | ||
|
|
4d065afe98 | ||
|
|
2c3416fde5 | ||
|
|
51749cf81b | ||
|
|
9037223584 | ||
|
|
3aea4f319a | ||
|
|
cae04fe2a0 | ||
|
|
6a5298b0fa | ||
|
|
6b5449a6d5 | ||
|
|
31a736c6b8 | ||
|
|
950b15880e | ||
|
|
694cd2a448 | ||
|
|
5659fc8591 | ||
|
|
fb486a87ba | ||
|
|
5fef22d0db | ||
|
|
7e745797f9 | ||
| 2486b9bbb5 | |||
| 92b47af415 | |||
| 36ac4c87f1 | |||
| 96fa1434fa | |||
| 11c833bb54 | |||
| 32f8a0c189 | |||
| db004a23b0 | |||
| 9c3473a166 | |||
| 70dc245d1e | |||
| 8cd73016c5 | |||
| cf453a012c | |||
| b624d11c7d | |||
| eb7a599e03 | |||
| dbc2c9270d | |||
| e47ffd017c | |||
| 2b0ffd1a22 | |||
| b9fdb14bcd | |||
| 7d4123ba50 | |||
| 464532b509 | |||
| c13f846b99 | |||
| b895d0c234 | |||
| 60dad5389b | |||
| d6a9319cd7 | |||
| 956e1cc64f | |||
| df3737d23e | |||
| 84753f8fdd | |||
| 49682f8cd5 | |||
| d4220b2acc | |||
| 0f8cc95e40 | |||
| cac5a365f5 | |||
| a3f77bc6fe | |||
| d4f02c84c7 | |||
| b5fe6c8451 | |||
| 2b0dce4640 | |||
| 0402d31630 | |||
| c9c6152df2 | |||
| 8e2d7c53de | |||
|
|
4fdefea1bd | ||
|
|
0d191ef104 | ||
|
|
559387eecc | ||
|
|
0a94a9f7d1 | ||
|
|
c036127f36 | ||
|
|
eb3559115e | ||
|
|
e469b8ba89 | ||
|
|
6920774e64 | ||
|
|
b45c22c275 | ||
|
|
69f0381167 | ||
|
|
c8ea5622e0 | ||
|
|
e85340ba06 | ||
|
|
6fee8fe4ee | ||
|
|
48589365b7 | ||
|
|
249333b961 | ||
|
|
e75fa0e3da | ||
|
|
e58ab2e3dc | ||
|
|
0e3b7dcaab | ||
|
|
ac015b4679 | ||
|
|
9b6ec0734e | ||
|
|
6e2889453c | ||
| 9e93d537a6 | |||
| 1870bf6b90 | |||
| 8c135f968a | |||
| eca42274c0 | |||
|
|
11e1f8c607 | ||
|
|
ac150126d8 |
@ -50,9 +50,7 @@ body:
|
||||
label: 版本
|
||||
description: 你当前正在使用我们软件的哪个版本/分支?
|
||||
options:
|
||||
- V1.1.13(最新开发版)
|
||||
- V1.1.12(最新发行版)
|
||||
- V1.1.11
|
||||
- V1.1.10
|
||||
- V1.1.14(最新开发版)
|
||||
- V1.1.13(最新发行版)
|
||||
validations:
|
||||
required: true
|
||||
@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<img src="src/main/resources/img/icon.svg" alt="JNotepad Icon">
|
||||
<img src="src/main/resources/jcnc/app/svg/icon.svg" alt="JNotepad Icon">
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">JNotepad</h1>
|
||||
<h4 align="center" style="margin: 30px 0 30px; font-weight: bold;">JavaFX开发,插件驱动,创造无限可能</h4>
|
||||
|
||||
|
||||
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>org.jcnc</groupId>
|
||||
<artifactId>JNotepad</artifactId>
|
||||
<version>1.1.4-beta</version>
|
||||
<version>1.0.14-alpha</version>
|
||||
<name>JNotepad</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
||||
@ -24,29 +24,30 @@ module org.jcnc.jnotepad {
|
||||
exports org.jcnc.jnotepad.model.enums;
|
||||
exports org.jcnc.jnotepad.app.config;
|
||||
exports org.jcnc.jnotepad.app.i18n;
|
||||
exports org.jcnc.jnotepad.common.constants;
|
||||
exports org.jcnc.jnotepad.app.common.constants;
|
||||
exports org.jcnc.jnotepad.controller.config;
|
||||
exports org.jcnc.jnotepad.controller.manager;
|
||||
exports org.jcnc.jnotepad.controller.i18n;
|
||||
exports org.jcnc.jnotepad.controller.event.handler.toolbar;
|
||||
exports org.jcnc.jnotepad.controller.event.handler.menuitem;
|
||||
exports org.jcnc.jnotepad.component.module.interfaces;
|
||||
exports org.jcnc.jnotepad.ui.component.module.interfaces;
|
||||
opens org.jcnc.jnotepad.app.config;
|
||||
exports org.jcnc.jnotepad.plugin.interfaces;
|
||||
exports org.jcnc.jnotepad.views.root.bottom.function;
|
||||
exports org.jcnc.jnotepad.controller.plugin.interfaces;
|
||||
exports org.jcnc.jnotepad.ui.views.root.bottom.function;
|
||||
|
||||
exports org.jcnc.jnotepad.component.module;
|
||||
exports org.jcnc.jnotepad.ui.component.module;
|
||||
exports org.jcnc.jnotepad.model.entity;
|
||||
exports org.jcnc.jnotepad.views.root.bottom;
|
||||
exports org.jcnc.jnotepad.views.root.bottom.status;
|
||||
exports org.jcnc.jnotepad.ui.views.root.bottom;
|
||||
exports org.jcnc.jnotepad.ui.views.root.bottom.status;
|
||||
exports org.jcnc.jnotepad.api.core.views.sidebar.bottom;
|
||||
exports org.jcnc.jnotepad.api.core.controller.config;
|
||||
exports org.jcnc.jnotepad.component.module.base;
|
||||
exports org.jcnc.jnotepad.component.stage.setting;
|
||||
exports org.jcnc.jnotepad.component.module.vbox;
|
||||
exports org.jcnc.jnotepad.component.module.hbox;
|
||||
exports org.jcnc.jnotepad.component.stage.topmenu.help;
|
||||
exports org.jcnc.jnotepad.component.stage.topmenu.plugin;
|
||||
exports org.jcnc.jnotepad.component.module.vbox.components;
|
||||
exports org.jcnc.jnotepad.ui.component.module.base;
|
||||
exports org.jcnc.jnotepad.ui.component.stage.setting;
|
||||
exports org.jcnc.jnotepad.ui.component.module.vbox;
|
||||
exports org.jcnc.jnotepad.ui.component.module.hbox;
|
||||
exports org.jcnc.jnotepad.ui.component.stage.topmenu.help;
|
||||
exports org.jcnc.jnotepad.ui.component.stage.topmenu.plugin;
|
||||
exports org.jcnc.jnotepad.ui.component.module.vbox.components;
|
||||
exports org.jcnc.jnotepad.ui.views.root.center.main.center.tab;
|
||||
|
||||
}
|
||||
@ -3,7 +3,7 @@ package org.jcnc.jnotepad;
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.app.manager.ApplicationManager;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
|
||||
|
||||
/**
|
||||
@ -26,13 +26,16 @@ public class JnotepadApp extends Application {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) {
|
||||
public void init() {
|
||||
// 获取当前启动位置a
|
||||
String currentWorkingDirectory = System.getProperty("user.dir");
|
||||
LogUtil.getLogger(this.getClass()).info("当前启动位置:{}", currentWorkingDirectory);
|
||||
|
||||
LoggerUtil.getLogger(this.getClass()).info("当前启动位置:{}", currentWorkingDirectory);
|
||||
// 设置参数
|
||||
APPLICATION_MANAGER.setApplication(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) {
|
||||
APPLICATION_MANAGER.setPrimaryStage(primaryStage);
|
||||
// 加载应用程序资源
|
||||
APPLICATION_MANAGER.loadAppResources();
|
||||
|
||||
@ -7,7 +7,10 @@ import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/**
|
||||
* 抽象窗格舞台
|
||||
* 抽象窗格舞台。
|
||||
* <p>
|
||||
* 该类是一个抽象的窗格舞台,用于创建自定义的JavaFX窗口。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
@ -15,40 +18,46 @@ public abstract class AbstractPaneStage extends BorderPane {
|
||||
private final Stage stage = new Stage();
|
||||
|
||||
/**
|
||||
* 获取舞台图标
|
||||
* 获取舞台图标。
|
||||
*
|
||||
* @return 舞台图标
|
||||
*/
|
||||
protected abstract Image getStageIcon();
|
||||
|
||||
/**
|
||||
* 获取舞台标题
|
||||
* 获取舞台标题。
|
||||
*
|
||||
* @return 舞台标题
|
||||
*/
|
||||
protected abstract String getStageTitle();
|
||||
|
||||
/**
|
||||
* 获取自定义舞台
|
||||
* 获取自定义舞台场景。
|
||||
*
|
||||
* @return 舞台
|
||||
* @return 舞台场景
|
||||
*/
|
||||
protected abstract Scene getCustomizationScene();
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
* 初始化方法。
|
||||
* <p>
|
||||
* 在此方法中,您可以进行与窗口相关的初始化操作。
|
||||
* </p>
|
||||
*/
|
||||
protected abstract void initialize();
|
||||
|
||||
/**
|
||||
* 自定义启动方法
|
||||
* 自定义启动方法。
|
||||
*
|
||||
* @param stage 自定义舞台
|
||||
*/
|
||||
public abstract void run(Stage stage);
|
||||
|
||||
/**
|
||||
* 启动方法
|
||||
* 启动方法。
|
||||
* <p>
|
||||
* 该方法设置窗口的图标、标题、场景,并将窗口设置为模态对话框,然后显示窗口。
|
||||
* </p>
|
||||
*/
|
||||
public void run() {
|
||||
stage.getIcons().add(getStageIcon());
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package org.jcnc.jnotepad.api.core.controller.config;
|
||||
|
||||
import org.jcnc.jnotepad.api.core.controller.interfaces.ConfigController;
|
||||
import org.jcnc.jnotepad.app.utils.JsonUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.app.utils.PopUpUtil;
|
||||
import org.jcnc.jnotepad.controller.exception.AppException;
|
||||
import org.jcnc.jnotepad.util.JsonUtil;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
@ -16,59 +16,61 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* 基本配置文件控制器抽象类
|
||||
* 抽象基本配置文件控制器类。
|
||||
* <p>
|
||||
* 该类是基本配置文件控制器的抽象实现,提供了加载、持久化配置文件以及其他相关方法。
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 配置文件类型
|
||||
* @author gewuyou
|
||||
*/
|
||||
public abstract class BaseConfigController<T> implements ConfigController<T> {
|
||||
|
||||
protected final String rootConfigDir = "config";
|
||||
|
||||
protected final String systemConfigDir = "system";
|
||||
protected static final String ROOT_CONFIG_DIR = "config";
|
||||
|
||||
protected static final String SYSTEM_CONFIG_DIR = "system";
|
||||
private final Logger logger = LoggerUtil.getLogger(getClass());
|
||||
protected T config;
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 获取配置文件Class类
|
||||
* 获取配置文件Class类。
|
||||
*
|
||||
* @return 配置文件Class类
|
||||
*/
|
||||
protected abstract Class<T> getConfigClass();
|
||||
|
||||
/**
|
||||
* 获取配置文件名称
|
||||
* 获取配置文件名称。
|
||||
*
|
||||
* @return 配置文件名称
|
||||
*/
|
||||
protected abstract String getConfigName();
|
||||
|
||||
/**
|
||||
* 获取配置文件文件夹路径
|
||||
* 获取配置文件文件夹路径。
|
||||
*
|
||||
* @return 配置文件夹路径
|
||||
*/
|
||||
protected abstract String getConfigDir();
|
||||
|
||||
/**
|
||||
* 获取配置文件类
|
||||
* 获取配置文件对象。
|
||||
*
|
||||
* @return 获取配置文件类
|
||||
* @return 配置文件对象
|
||||
*/
|
||||
public T getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加载配置文件内容
|
||||
* 加载配置文件内容。
|
||||
*/
|
||||
@Override
|
||||
public void loadConfig() {
|
||||
createConfigIfNotExists();
|
||||
// 存在则加载
|
||||
try {
|
||||
logger.info("正在加载配置文件:{}...", getConfigClass());
|
||||
logger.info("正在加载配置文件: {}...", getConfigClass());
|
||||
String configContent = Files.readString(getConfigPath());
|
||||
config = JsonUtil.OBJECT_MAPPER.readValue(configContent, getConfigClass());
|
||||
} catch (IOException e) {
|
||||
@ -79,7 +81,7 @@ public abstract class BaseConfigController<T> implements ConfigController<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置文件持久化
|
||||
* 配置文件持久化。
|
||||
*/
|
||||
@Override
|
||||
public void writeConfig() {
|
||||
@ -88,7 +90,7 @@ public abstract class BaseConfigController<T> implements ConfigController<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置文件持久化
|
||||
* 配置文件持久化。
|
||||
*
|
||||
* @param config 配置文件对象
|
||||
*/
|
||||
@ -106,7 +108,7 @@ public abstract class BaseConfigController<T> implements ConfigController<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果配置文件不存在则创建
|
||||
* 如果配置文件不存在则创建。
|
||||
*/
|
||||
@Override
|
||||
public void createConfigIfNotExists() {
|
||||
@ -122,7 +124,7 @@ public abstract class BaseConfigController<T> implements ConfigController<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置文件路径
|
||||
* 获取配置文件路径。
|
||||
*
|
||||
* @return 配置文件路径
|
||||
*/
|
||||
|
||||
@ -4,22 +4,35 @@ import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* 配置文件控制器接口
|
||||
* <p>
|
||||
* 该接口定义了配置文件相关的操作,包括加载、持久化、创建和获取配置文件路径等。
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 配置文件类型
|
||||
* @author gewuyou
|
||||
*/
|
||||
public interface ConfigController<T> {
|
||||
/**
|
||||
* 加载配置文件内容
|
||||
* <p>
|
||||
* 从配置文件中加载配置信息。
|
||||
* </p>
|
||||
*/
|
||||
void loadConfig();
|
||||
|
||||
/**
|
||||
* 配置文件持久化
|
||||
* <p>
|
||||
* 将配置信息持久化到配置文件中。
|
||||
* </p>
|
||||
*/
|
||||
void writeConfig();
|
||||
|
||||
/**
|
||||
* 配置文件持久化
|
||||
* <p>
|
||||
* 将指定的配置对象持久化到配置文件中。
|
||||
* </p>
|
||||
*
|
||||
* @param config 配置文件对象
|
||||
*/
|
||||
@ -27,19 +40,28 @@ public interface ConfigController<T> {
|
||||
|
||||
/**
|
||||
* 如果配置文件不存在则创建
|
||||
* <p>
|
||||
* 在需要的情况下创建配置文件,如果配置文件已存在,则不执行任何操作。
|
||||
* </p>
|
||||
*/
|
||||
void createConfigIfNotExists();
|
||||
|
||||
/**
|
||||
* 创建配置文件实体
|
||||
* <p>
|
||||
* 生成默认的配置文件实体对象,用于后续的序列化操作。
|
||||
* </p>
|
||||
*
|
||||
* @return 默认的配置文件实体
|
||||
* @apiNote 返回默认的配置文件实体用于序列化json
|
||||
* @apiNote 返回默认的配置文件实体用于序列化 JSON 数据。
|
||||
*/
|
||||
T generateDefaultConfig();
|
||||
|
||||
/**
|
||||
* 获取配置文件路径
|
||||
* <p>
|
||||
* 返回配置文件的路径。
|
||||
* </p>
|
||||
*
|
||||
* @return 配置文件路径
|
||||
*/
|
||||
|
||||
@ -7,6 +7,10 @@ import java.util.Map;
|
||||
/**
|
||||
* 抽象缓存管理类
|
||||
*
|
||||
* <p>
|
||||
* 该类是缓存管理的抽象基类,用于管理不同类型的缓存。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public abstract class AbstractCacheManager {
|
||||
@ -41,7 +45,6 @@ public abstract class AbstractCacheManager {
|
||||
*
|
||||
* @return 缓存集合
|
||||
*/
|
||||
|
||||
public Map<String, Cache> getCaches() {
|
||||
return caches;
|
||||
}
|
||||
@ -112,5 +115,4 @@ public abstract class AbstractCacheManager {
|
||||
}
|
||||
return cache.getCacheData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
package org.jcnc.jnotepad.api.core.views.manager.builder;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.Button;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 下方状态栏按钮建造者
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class BottomStatusBoxButtonBuilder {
|
||||
private Button button;
|
||||
|
||||
private FontIcon fontIcon;
|
||||
|
||||
private EventHandler<ActionEvent> eventHandler;
|
||||
|
||||
public BottomStatusBoxButtonBuilder() {
|
||||
}
|
||||
|
||||
public BottomStatusBoxButtonBuilder(Button button) {
|
||||
this.button = button;
|
||||
}
|
||||
|
||||
public BottomStatusBoxButtonBuilder setFontIcon(FontIcon fontIcon) {
|
||||
this.fontIcon = fontIcon;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BottomStatusBoxButtonBuilder setEventHandler(EventHandler<ActionEvent> eventHandler) {
|
||||
this.eventHandler = eventHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Button build() {
|
||||
Optional<Button> container = Optional.ofNullable(button);
|
||||
button = container.orElseGet(Button::new);
|
||||
button.setGraphic(fontIcon);
|
||||
button.setOnAction(eventHandler);
|
||||
return button;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package org.jcnc.jnotepad.api.core.views.menu;
|
||||
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.control.Menu;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.ui.views.root.top.menubar.TopMenuBar;
|
||||
|
||||
/**
|
||||
* 抽象基础菜单类
|
||||
*
|
||||
* <p>
|
||||
* 此抽象类用于创建基础菜单,包括菜单项的注册和初始化。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public abstract class AbstractBaseMenu extends AbstractMenu<Menu> {
|
||||
protected final TopMenuBar topMenuBar = TopMenuBar.getInstance();
|
||||
|
||||
/**
|
||||
* 获取菜单名称
|
||||
*
|
||||
* @return 菜单名称
|
||||
*/
|
||||
public abstract String getMenuName();
|
||||
|
||||
/**
|
||||
* 获取菜单项
|
||||
*
|
||||
* @return 菜单项集合
|
||||
*/
|
||||
@Override
|
||||
protected ObservableList<MenuItem> getItems() {
|
||||
return getMenu().getItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化菜单栏
|
||||
*/
|
||||
@Override
|
||||
public void initMenu() {
|
||||
registerMenu();
|
||||
Menu menu = getMenu();
|
||||
// 菜单名称国际化
|
||||
UiResourceBundle.bindStringProperty(menu.textProperty(), getMenuName());
|
||||
// 初始化菜单项
|
||||
initMenuItems(getMenuItems());
|
||||
}
|
||||
}
|
||||
@ -1,42 +1,35 @@
|
||||
package org.jcnc.jnotepad.api.core.views.top.menu;
|
||||
package org.jcnc.jnotepad.api.core.views.menu;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.CheckMenuItem;
|
||||
import javafx.scene.control.Menu;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.RadioMenuItem;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.views.root.top.menubar.TopMenuBar;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.controller.config.UserConfigController;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 抽象顶部菜单
|
||||
* 抽象菜单类
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public abstract class AbstractTopMenu {
|
||||
protected final TopMenuBar topMenuBar = TopMenuBar.getInstance();
|
||||
|
||||
protected Logger logger = LogUtil.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 获取菜单名称
|
||||
*
|
||||
* @return 菜单名称
|
||||
*/
|
||||
public abstract String getMenuName();
|
||||
public abstract class AbstractMenu<T> {
|
||||
protected Logger logger = LoggerUtil.getLogger(this.getClass());
|
||||
UserConfigController userConfigController = UserConfigController.getInstance();
|
||||
|
||||
/**
|
||||
* 获取菜单
|
||||
*
|
||||
* @return 菜单
|
||||
*/
|
||||
public abstract Menu getMenu();
|
||||
public abstract T getMenu();
|
||||
|
||||
/**
|
||||
* 获取菜单项集合
|
||||
@ -46,9 +39,22 @@ public abstract class AbstractTopMenu {
|
||||
public abstract Map<String, MenuItem> getMenuItems();
|
||||
|
||||
/**
|
||||
* 注册顶部菜单
|
||||
* 注册菜单
|
||||
*/
|
||||
protected abstract void registerTopMenu();
|
||||
protected abstract void registerMenu();
|
||||
|
||||
/**
|
||||
* 初始化菜单
|
||||
*/
|
||||
protected abstract void initMenu();
|
||||
|
||||
/**
|
||||
* 获取菜单项
|
||||
*
|
||||
* @return 菜单项集合
|
||||
*/
|
||||
protected abstract ObservableList<MenuItem> getItems();
|
||||
|
||||
|
||||
/**
|
||||
* 注册菜单项
|
||||
@ -56,7 +62,7 @@ public abstract class AbstractTopMenu {
|
||||
* @param menuItem 菜单项
|
||||
* @param menuItemName 菜单项名称
|
||||
* @param userData 用户数据,用来存放必要的数据,比如按钮菜单项名称
|
||||
* @param eventHandler 事件
|
||||
* @param eventHandler 事件处理器
|
||||
*/
|
||||
public void registerMenuItem(MenuItem menuItem, String menuItemName, Object userData, EventHandler<ActionEvent> eventHandler) {
|
||||
getMenuItems().put(menuItemName, menuItem);
|
||||
@ -70,9 +76,8 @@ public abstract class AbstractTopMenu {
|
||||
* @param checkMenuItem 检查菜单项
|
||||
* @param menuItemName 菜单项名称
|
||||
* @param userData 用户数据,用来存放必要的数据,比如按钮菜单项名称
|
||||
* @param listener 监听事件
|
||||
* @param listener 监听器
|
||||
*/
|
||||
|
||||
public void registerMenuItem(CheckMenuItem checkMenuItem, String menuItemName, Object userData, ChangeListener<Boolean> listener) {
|
||||
getMenuItems().put(menuItemName, checkMenuItem);
|
||||
checkMenuItem.setUserData(userData);
|
||||
@ -85,42 +90,30 @@ public abstract class AbstractTopMenu {
|
||||
* @param radioMenuItem 单选菜单项
|
||||
* @param menuItemName 菜单项名称
|
||||
* @param userData 用户数据,用来存放必要的数据
|
||||
* @param eventHandler 操作事件
|
||||
* @param eventHandler 事件处理器
|
||||
*/
|
||||
|
||||
public void registerRadioMenuItem(Map<String, RadioMenuItem> radioMenuItems, RadioMenuItem radioMenuItem, String menuItemName, Object userData, EventHandler<ActionEvent> eventHandler) {
|
||||
radioMenuItems.put(menuItemName, radioMenuItem);
|
||||
radioMenuItem.setUserData(userData);
|
||||
radioMenuItem.setOnAction(eventHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化菜单栏
|
||||
*/
|
||||
public void initMenu() {
|
||||
registerTopMenu();
|
||||
logger.info("初始化菜单!");
|
||||
Menu menu = getMenu();
|
||||
// 文件菜单
|
||||
UiResourceBundle.bindStringProperty(menu.textProperty(), getMenuName());
|
||||
// 初始化菜单项
|
||||
initMenuItems(getMenuItems(), menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化菜单项
|
||||
*
|
||||
* @param menuItems 菜单项集合
|
||||
* @param menu 菜单
|
||||
*/
|
||||
|
||||
private void initMenuItems(Map<String, MenuItem> menuItems, Menu menu) {
|
||||
protected void initMenuItems(Map<String, MenuItem> menuItems) {
|
||||
logger.info("初始化菜单项!");
|
||||
var itemMap = topMenuBar.getAllItemMap();
|
||||
Map<String, MenuItem> menuItemMap = new HashMap<>(16);
|
||||
menuItems.forEach((key, value) -> {
|
||||
UiResourceBundle.bindStringProperty(value.textProperty(), key);
|
||||
itemMap.put((String) value.getUserData(), value);
|
||||
menu.getItems().add(value);
|
||||
menuItemMap.put((String) value.getUserData(), value);
|
||||
getItems().add(value);
|
||||
});
|
||||
userConfigController.getMenuItems().add(menuItemMap);
|
||||
userConfigController.initShortcutKeys(menuItemMap);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,230 @@
|
||||
package org.jcnc.jnotepad.api.core.views.menu.builder;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.*;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.controller.config.UserConfigController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 抽象菜单建造者类
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public abstract class AbstractMenuBuilder<B, T> {
|
||||
/**
|
||||
* 上下文菜单项
|
||||
*/
|
||||
protected final Map<String, MenuItem> menuItems = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Get subclass builder
|
||||
*
|
||||
* @return builder
|
||||
*/
|
||||
protected abstract B getBuilder();
|
||||
|
||||
/**
|
||||
* 获取菜单
|
||||
*
|
||||
* @return 菜单
|
||||
*/
|
||||
protected abstract T getMenu();
|
||||
|
||||
/**
|
||||
* Retrieves the items of the menu.
|
||||
*
|
||||
* @return an ObservableList of MenuItems
|
||||
*/
|
||||
protected abstract ObservableList<MenuItem> getItems();
|
||||
|
||||
/**
|
||||
* 添加菜单项
|
||||
*
|
||||
* @param label 菜单项名称
|
||||
* @param eventHandler 事件
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addMenuItem(String label, EventHandler<ActionEvent> eventHandler) {
|
||||
MenuItem menuItem = new MenuItem(label);
|
||||
menuItem.setOnAction(eventHandler);
|
||||
menuItems.put(label, menuItem);
|
||||
getItems().add(menuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单项
|
||||
*
|
||||
* @param label 菜单项名称
|
||||
* @param eventHandler 事件
|
||||
* @param visible 是否可见
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addMenuItem(String label, EventHandler<ActionEvent> eventHandler, BooleanProperty visible) {
|
||||
MenuItem menuItem = new MenuItem(label);
|
||||
menuItem.setOnAction(eventHandler);
|
||||
menuItem.setVisible(visible.get());
|
||||
visible.addListener((observable, oldValue, newValue) -> menuItem.setVisible(Boolean.TRUE.equals(newValue)));
|
||||
menuItems.put(label, menuItem);
|
||||
getItems().add(menuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单项
|
||||
*
|
||||
* @param label 菜单项名称
|
||||
* @param eventHandler 事件
|
||||
* @param visible 是否可见
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addMenuItem(String label, EventHandler<ActionEvent> eventHandler, boolean visible) {
|
||||
MenuItem menuItem = new MenuItem(label);
|
||||
menuItem.setOnAction(eventHandler);
|
||||
menuItem.setVisible(visible);
|
||||
menuItems.put(label, menuItem);
|
||||
getItems().add(menuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单选菜单项
|
||||
*
|
||||
* @param label 菜单项名称
|
||||
* @param eventHandler 事件
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addRadioMenuItem(String label, EventHandler<ActionEvent> eventHandler) {
|
||||
RadioMenuItem menuItem = new RadioMenuItem(label);
|
||||
menuItem.setOnAction(eventHandler);
|
||||
menuItems.put(label, menuItem);
|
||||
getItems().add(menuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加复选菜单项
|
||||
*
|
||||
* @param label 菜单项名称
|
||||
* @param eventHandler 事件
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addCheckMenuItem(String label, EventHandler<ActionEvent> eventHandler) {
|
||||
CheckMenuItem menuItem = new CheckMenuItem(label);
|
||||
menuItem.setOnAction(eventHandler);
|
||||
menuItems.put(label, menuItem);
|
||||
getItems().add(menuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
|
||||
public B addCheckMenuItem(CheckMenuItem checkMenuItem, EventHandler<ActionEvent> eventHandler) {
|
||||
checkMenuItem.setOnAction(eventHandler);
|
||||
menuItems.put(checkMenuItem.getText(), checkMenuItem);
|
||||
getItems().add(checkMenuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单
|
||||
*
|
||||
* @param menu 菜单
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addMenu(Menu menu) {
|
||||
menuItems.put(menu.getText(), menu);
|
||||
getItems().add(menu);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单
|
||||
*
|
||||
* @param menu 菜单
|
||||
* @param visible 是否隐藏
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addMenu(Menu menu, BooleanProperty visible) {
|
||||
menu.setVisible(visible.get());
|
||||
visible.addListener((observable, oldValue, newValue) -> menu.setVisible(Boolean.TRUE.equals(newValue)));
|
||||
menuItems.put(menu.getText(), menu);
|
||||
getItems().add(menu);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单
|
||||
*
|
||||
* @param menu 菜单
|
||||
* @param visible 是否隐藏
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addMenu(Menu menu, boolean visible) {
|
||||
menu.setVisible(visible);
|
||||
menuItems.put(menu.getText(), menu);
|
||||
getItems().add(menu);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加分割线
|
||||
*
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addSeparatorMenuItem() {
|
||||
getItems().add(new SeparatorMenuItem());
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分割线
|
||||
*
|
||||
* @param visible 是否可见
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addSeparatorMenuItem(BooleanProperty visible) {
|
||||
SeparatorMenuItem separatorMenuItem = new SeparatorMenuItem();
|
||||
separatorMenuItem.setVisible(visible.get());
|
||||
visible.addListener((observable, oldValue, newValue) -> separatorMenuItem.setVisible(Boolean.TRUE.equals(newValue)));
|
||||
getItems().add(separatorMenuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分割线
|
||||
*
|
||||
* @param visible 是否可见
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addSeparatorMenuItem(boolean visible) {
|
||||
SeparatorMenuItem separatorMenuItem = new SeparatorMenuItem();
|
||||
separatorMenuItem.setVisible(visible);
|
||||
getItems().add(separatorMenuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build menu
|
||||
*
|
||||
* @return menu
|
||||
*/
|
||||
public T build() {
|
||||
UserConfigController userConfigController = UserConfigController.getInstance();
|
||||
Map<String, MenuItem> menuItemMap = new HashMap<>(16);
|
||||
menuItems.forEach((key, value) -> {
|
||||
UiResourceBundle.bindStringProperty(value.textProperty(), key);
|
||||
menuItemMap.put((String) value.getUserData(), value);
|
||||
});
|
||||
userConfigController.getMenuItems().add(menuItemMap);
|
||||
userConfigController.initShortcutKeys(menuItemMap);
|
||||
return getMenu();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package org.jcnc.jnotepad.api.core.views.menu.builder;
|
||||
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.MenuItem;
|
||||
|
||||
/**
|
||||
* 上下文菜单建造者类
|
||||
*
|
||||
* <p>
|
||||
* 此类用于构建上下文菜单对象,可以添加菜单项、单选菜单项、复选菜单项以及分割线等。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class ContextMenuBuilder extends AbstractMenuBuilder<ContextMenuBuilder, ContextMenu> {
|
||||
|
||||
private final ContextMenu contextMenu;
|
||||
|
||||
public ContextMenuBuilder() {
|
||||
contextMenu = new ContextMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取子类的建造者实例
|
||||
*
|
||||
* @return 建造者实例
|
||||
*/
|
||||
@Override
|
||||
protected ContextMenuBuilder getBuilder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单
|
||||
*
|
||||
* @return 菜单
|
||||
*/
|
||||
@Override
|
||||
protected ContextMenu getMenu() {
|
||||
return contextMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文菜单的菜单项列表
|
||||
*
|
||||
* @return 菜单项列表
|
||||
*/
|
||||
@Override
|
||||
protected ObservableList<MenuItem> getItems() {
|
||||
return contextMenu.getItems();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package org.jcnc.jnotepad.api.core.views.menu.builder;
|
||||
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.control.Menu;
|
||||
import javafx.scene.control.MenuItem;
|
||||
|
||||
/**
|
||||
* 菜单建造者类
|
||||
*
|
||||
* <p>
|
||||
* 此类用于构建菜单对象,可以添加菜单项、单选菜单项、复选菜单项以及分割线等。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class MenuBuilder extends AbstractMenuBuilder<MenuBuilder, Menu> {
|
||||
|
||||
private final Menu menu;
|
||||
|
||||
|
||||
/**
|
||||
* 构造菜单建造者
|
||||
*
|
||||
* @param label 菜单的标签
|
||||
*/
|
||||
public MenuBuilder(String label) {
|
||||
menu = new Menu(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取子类的建造者实例
|
||||
*
|
||||
* @return 建造者实例
|
||||
*/
|
||||
@Override
|
||||
protected MenuBuilder getBuilder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单
|
||||
*
|
||||
* @return 菜单
|
||||
*/
|
||||
@Override
|
||||
protected Menu getMenu() {
|
||||
return menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单的菜单项列表
|
||||
*
|
||||
* @return 菜单项列表
|
||||
*/
|
||||
@Override
|
||||
protected ObservableList<MenuItem> getItems() {
|
||||
return menu.getItems();
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,10 +3,14 @@ package org.jcnc.jnotepad.api.core.views.sidebar.bottom;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Menu;
|
||||
import javafx.scene.control.MenuBar;
|
||||
import org.jcnc.jnotepad.views.root.bottom.function.FunctionBox;
|
||||
import org.jcnc.jnotepad.ui.views.root.bottom.function.FunctionBox;
|
||||
|
||||
/**
|
||||
* 子功能栏抽象类(用于构建一个基本的子功能栏)
|
||||
* 子功能栏抽象类
|
||||
*
|
||||
* <p>
|
||||
* 此抽象类用于构建一个基本的子功能栏,包括功能按钮的初始化和添加到功能栏中。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
@ -19,11 +23,17 @@ public abstract class AbstractFunctionChildrenBox {
|
||||
|
||||
protected Menu menu = new Menu();
|
||||
|
||||
/**
|
||||
* 构造子功能栏抽象类
|
||||
*/
|
||||
protected AbstractFunctionChildrenBox() {
|
||||
functionBox = FunctionBox.getInstance();
|
||||
menuBar = FunctionBox.getMenuBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化子功能栏,包括将功能按钮添加到菜单栏中
|
||||
*/
|
||||
public void initialize() {
|
||||
menu.setGraphic(label);
|
||||
menuBar.getMenus().add(menu);
|
||||
|
||||
1
src/main/java/org/jcnc/jnotepad/app/aReadme.md
Normal file
1
src/main/java/org/jcnc/jnotepad/app/aReadme.md
Normal file
@ -0,0 +1 @@
|
||||
app 目录存放应用程序配置、应用程序缓存、通用常量和国际化文件。
|
||||
1
src/main/java/org/jcnc/jnotepad/app/common/aReadme.md
Normal file
1
src/main/java/org/jcnc/jnotepad/app/common/aReadme.md
Normal file
@ -0,0 +1 @@
|
||||
common 目录存放应用程序的通用组卷
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.common.constants;
|
||||
package org.jcnc.jnotepad.app.common.constants;
|
||||
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
|
||||
@ -7,13 +7,21 @@ import java.util.regex.Pattern;
|
||||
/**
|
||||
* 应用常量类,用于存放应用程序中的常量值。
|
||||
*
|
||||
* @author 许轲
|
||||
* <p>
|
||||
* 该类包含了应用程序的一些常用常量,如版本号、作者、软件名称、初始宽度和高度、Logo地址等。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 还包括了与标签页相关的正则表达式模式,以及默认的属性和程序文件目录等常量。
|
||||
* </p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public class AppConstants {
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
public static final String VERSION = "1.0.13";
|
||||
public static final String VERSION = "1.0.14-alpha";
|
||||
/**
|
||||
* 作者
|
||||
*/
|
||||
@ -33,10 +41,14 @@ public class AppConstants {
|
||||
/**
|
||||
* logo地址
|
||||
*/
|
||||
public static final String APP_ICON = "/img/icon.png";
|
||||
public static final String APP_ICON = "/jcnc/app/images/appIcons/icon.png";
|
||||
|
||||
/**
|
||||
* 默认标签页的正则
|
||||
*
|
||||
* <p>
|
||||
* 用于匹配默认标签页名称的正则表达式,格式为"New File"后跟数字。
|
||||
* </p>
|
||||
*/
|
||||
public static final Pattern TABNAME_PATTERN = Pattern.compile("^" + Pattern.quote(UiResourceBundle.getContent(TextConstants.NEW_FILE)) + "\\d+$");
|
||||
|
||||
@ -49,11 +61,9 @@ public class AppConstants {
|
||||
*/
|
||||
public static final String PROGRAM_FILE_DIRECTORY = ".jnotepad";
|
||||
|
||||
|
||||
/**
|
||||
* 私有构造函数,防止该类被实例化。
|
||||
*/
|
||||
private AppConstants() {
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package org.jcnc.jnotepad.app.common.constants;
|
||||
|
||||
/**
|
||||
* SplitPane常量类
|
||||
*
|
||||
* <p>用于记录SplitPane中子组件的索引</p>
|
||||
*
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class SplitPaneItemConstants {
|
||||
|
||||
/**
|
||||
* rootSplitPane中的上部分隔栏索引。
|
||||
*/
|
||||
public static final int ROOT_SPLIT_PANE_TOP_SPLIT_PANE = 0;
|
||||
|
||||
/**
|
||||
* rootSplitPane中的底部指令框索引。
|
||||
*/
|
||||
public static final int ROOT_SPLIT_PANE_CMD_BOX = 1;
|
||||
|
||||
/**
|
||||
* rootSplitPane中的上部面板的左侧索引。
|
||||
*/
|
||||
public static final int TOP_SPLIT_PANE_DIRECTORY_SIDEBAR_PANE = 0;
|
||||
|
||||
/**
|
||||
* rootSplitPane中的上部面板的右侧索引。
|
||||
*/
|
||||
public static final int TOP_SPLIT_PANE_CENTER_TAB_PANE = 1;
|
||||
|
||||
}
|
||||
@ -0,0 +1,264 @@
|
||||
package org.jcnc.jnotepad.app.common.constants;
|
||||
|
||||
/**
|
||||
* 文本常量类,包含多处使用的文本常量。
|
||||
*
|
||||
* <p>如果只有一个类使用常量,请在该类中使用 <code>private static final</code> 声明。</p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class TextConstants {
|
||||
|
||||
/**
|
||||
* 标题文本常量
|
||||
*/
|
||||
public static final String TITLE = "title";
|
||||
|
||||
/**
|
||||
* 保存文本常量
|
||||
*/
|
||||
public static final String SAVE = "SAVE";
|
||||
|
||||
/**
|
||||
* 文件文本常量
|
||||
*/
|
||||
public static final String FILE = "FILE";
|
||||
/**
|
||||
* 文件夹
|
||||
*/
|
||||
public static final String FOLDER = "FOLDER";
|
||||
|
||||
/**
|
||||
* 构建文本常量
|
||||
*/
|
||||
public static final String BUILD = "BUILD";
|
||||
|
||||
/**
|
||||
* 终端文本常量
|
||||
*/
|
||||
public static final String TERMINAL = "TERMINAL";
|
||||
|
||||
/**
|
||||
* 运行文本常量
|
||||
*/
|
||||
public static final String RUN = "RUN";
|
||||
|
||||
/**
|
||||
* 调试文本常量
|
||||
*/
|
||||
public static final String DE_BUG = "DE_BUG";
|
||||
|
||||
/**
|
||||
* 新建文本常量
|
||||
*/
|
||||
public static final String NEW = "NEW";
|
||||
|
||||
/**
|
||||
* 打开文本常量
|
||||
*/
|
||||
public static final String OPEN = "OPEN";
|
||||
|
||||
/**
|
||||
* 打开目录文本常量
|
||||
*/
|
||||
public static final String OPEN_DIRECTORY = "OPEN_DIRECTORY";
|
||||
|
||||
/**
|
||||
* 另存为文本常量
|
||||
*/
|
||||
public static final String SAVE_AS = "SAVE_AS";
|
||||
|
||||
/**
|
||||
* 重命名文本常量
|
||||
*/
|
||||
public static final String RENAME = "RENAME";
|
||||
|
||||
/**
|
||||
* 设置文本常量
|
||||
*/
|
||||
public static final String SET = "SET";
|
||||
|
||||
/**
|
||||
* 帮助文本常量
|
||||
*/
|
||||
public static final String HELP = "HELP";
|
||||
|
||||
/**
|
||||
* 自动换行文本常量
|
||||
*/
|
||||
public static final String WORD_WRAP = "WORD_WRAP";
|
||||
|
||||
/**
|
||||
* 插件文本常量
|
||||
*/
|
||||
public static final String PLUGIN = "PLUGIN";
|
||||
|
||||
/**
|
||||
* 管理插件文本常量
|
||||
*/
|
||||
public static final String MANAGER_PLUGIN = "MANAGER_PLUGIN";
|
||||
|
||||
/**
|
||||
* 关于文本常量
|
||||
*/
|
||||
public static final String ABOUT = "ABOUT";
|
||||
|
||||
/**
|
||||
* 开发者文本常量
|
||||
*/
|
||||
public static final String DEVELOPER = "DEVELOPER";
|
||||
|
||||
/**
|
||||
* 统计文本常量
|
||||
*/
|
||||
public static final String STATISTICS = "STATISTICS";
|
||||
|
||||
/**
|
||||
* 打开配置文件文本常量
|
||||
*/
|
||||
public static final String OPEN_CONFIGURATION_FILE = "OPEN_CONFIGURATION_FILE";
|
||||
|
||||
/**
|
||||
* 顶部文本常量
|
||||
*/
|
||||
public static final String TOP = "TOP";
|
||||
|
||||
/**
|
||||
* 语言文本常量
|
||||
*/
|
||||
public static final String LANGUAGE = "LANGUAGE";
|
||||
|
||||
/**
|
||||
* 中文文本常量
|
||||
*/
|
||||
public static final String UPPER_CHINESE = "CHINESE";
|
||||
|
||||
/**
|
||||
* 英文文本常量
|
||||
*/
|
||||
public static final String UPPER_ENGLISH = "ENGLISH";
|
||||
|
||||
/**
|
||||
* 新建文件文本常量
|
||||
*/
|
||||
public static final String NEW_FILE = "NEW_FILE";
|
||||
|
||||
/**
|
||||
* 新建文件夹
|
||||
*/
|
||||
public static final String NEW_DIRECTORY = "NEW_DIRECTORY";
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public static final String DELETE = "DELETE";
|
||||
|
||||
/**
|
||||
* 行文本常量
|
||||
*/
|
||||
public static final String ROW = "ROW";
|
||||
|
||||
/**
|
||||
* 列文本常量
|
||||
*/
|
||||
public static final String COLUMN = "COLUMN";
|
||||
|
||||
/**
|
||||
* 字数统计文本常量
|
||||
*/
|
||||
public static final String WORD_COUNT = "WORD_COUNT";
|
||||
|
||||
/**
|
||||
* 编码文本常量
|
||||
*/
|
||||
public static final String ENCODE = "ENCODE";
|
||||
|
||||
/**
|
||||
* 英文小写文本常量
|
||||
*/
|
||||
public static final String ENGLISH = "english";
|
||||
|
||||
/**
|
||||
* 中文小写文本常量
|
||||
*/
|
||||
public static final String CHINESE = "chinese";
|
||||
|
||||
/**
|
||||
* 关闭
|
||||
*/
|
||||
public static final String CLOSE = "CLOSE";
|
||||
|
||||
/**
|
||||
* 关闭其他标签页
|
||||
*/
|
||||
public static final String CLOSE_OTHER_TABS = "CLOSE_OTHER_TABS";
|
||||
|
||||
/**
|
||||
* 关闭所有标签页
|
||||
*/
|
||||
public static final String CLOSE_ALL_TABS = "CLOSE_ALL_TABS";
|
||||
|
||||
/**
|
||||
* 关闭左侧标签
|
||||
*/
|
||||
public static final String CLOSE_LEFT_TABS = "CLOSE_LEFT_TABS";
|
||||
|
||||
/**
|
||||
* 关闭右侧标签
|
||||
*/
|
||||
public static final String CLOSE_RIGHT_TABS = "CLOSE_RIGHT_TABS";
|
||||
|
||||
/**
|
||||
* 复制
|
||||
*/
|
||||
public static final String COPY = "COPY";
|
||||
|
||||
/**
|
||||
* 粘贴
|
||||
*/
|
||||
public static final String PASTE = "PASTE";
|
||||
|
||||
/**
|
||||
* 剪切
|
||||
*/
|
||||
public static final String SHEAR = "SHEAR";
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
public static final String FILE_NAME = "FILE_NAME";
|
||||
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
public static final String FILE_PATH = "FILE_PATH";
|
||||
|
||||
|
||||
/**
|
||||
* 所在文件夹
|
||||
*/
|
||||
public static final String FOLDER_PATH = "FOLDER_PATH";
|
||||
/**
|
||||
* 固定标签页
|
||||
*/
|
||||
public static final String FIXED_TAB = "FIXED_TAB";
|
||||
/**
|
||||
* 只读
|
||||
*/
|
||||
public static final String READ_ONLY = "READ_ONLY";
|
||||
|
||||
public static final String SEPARATOR = "separator";
|
||||
|
||||
/**
|
||||
* 打开于
|
||||
*/
|
||||
public static final String OPEN_ON = "OPEN_ON";
|
||||
/**
|
||||
* 资源管理器
|
||||
*/
|
||||
public static final String EXPLORER = "EXPLORER";
|
||||
|
||||
private TextConstants() {
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,9 +1,12 @@
|
||||
package org.jcnc.jnotepad.common.manager;
|
||||
package org.jcnc.jnotepad.app.common.manager;
|
||||
|
||||
import org.jcnc.jnotepad.api.core.manager.AbstractCacheManager;
|
||||
|
||||
/**
|
||||
* 应用程序缓存管理类
|
||||
* 应用程序缓存管理类。
|
||||
* <p>
|
||||
* 该类用于管理应用程序中的缓存数据。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
@ -15,10 +18,20 @@ public class ApplicationCacheManager extends AbstractCacheManager {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 ApplicationCacheManager 的实例。
|
||||
*
|
||||
* @return ApplicationCacheManager 实例
|
||||
*/
|
||||
public static ApplicationCacheManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全局命名空间。
|
||||
*
|
||||
* @return 全局命名空间字符串
|
||||
*/
|
||||
@Override
|
||||
public String getGlobalNamespace() {
|
||||
return "jcnc";
|
||||
@ -1,20 +1,21 @@
|
||||
package org.jcnc.jnotepad.common.manager;
|
||||
package org.jcnc.jnotepad.app.common.manager;
|
||||
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 线程池管理类
|
||||
*
|
||||
* <p>该类用于管理应用程序中的线程池,提供了异步操作的执行环境。</p>
|
||||
* 线程池管理类。
|
||||
* <p>
|
||||
* 该类用于管理应用程序中的线程池,提供了异步操作的执行环境。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class ThreadPoolManager {
|
||||
private static final Logger logger = LogUtil.getLogger(ThreadPoolManager.class);
|
||||
private static final Logger logger = LoggerUtil.getLogger(ThreadPoolManager.class);
|
||||
/**
|
||||
* 核心线程数
|
||||
*/
|
||||
@ -68,9 +69,11 @@ public class ThreadPoolManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前运行线程数自减
|
||||
* 当前运行线程数自减。
|
||||
* <p>
|
||||
* 当你创建任务时,务必在最后执行一次该方法。
|
||||
* </p>
|
||||
*
|
||||
* @apiNote 当你创建任务时,务必在最后执行一次该方法
|
||||
* @see ThreadPoolManager
|
||||
*/
|
||||
public static void threadContSelfSubtracting() {
|
||||
@ -8,19 +8,19 @@ import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.DEFAULT_PROPERTY;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
|
||||
/**
|
||||
* 应用程序配置文件
|
||||
*
|
||||
* <p>
|
||||
* 此类用于存储应用程序的配置信息,包括程序根路径、排除的文件夹和文件等。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class AppConfig {
|
||||
/**
|
||||
* 程序根路径
|
||||
*/
|
||||
private String rootPath;
|
||||
/**
|
||||
* 排除的文件夹
|
||||
*/
|
||||
@ -31,12 +31,19 @@ public class AppConfig {
|
||||
*/
|
||||
@JsonIgnore
|
||||
private final Set<File> ignoreFile;
|
||||
/**
|
||||
* 程序根路径
|
||||
*/
|
||||
private String rootPath;
|
||||
/**
|
||||
* 上次的程序根路径
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String lastRootPath;
|
||||
|
||||
/**
|
||||
* 构造应用程序配置对象
|
||||
*/
|
||||
public AppConfig() {
|
||||
ignoreFolder = Set.of(
|
||||
new File(Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, "system").toString()),
|
||||
@ -45,26 +52,56 @@ public class AppConfig {
|
||||
ignoreFile = Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取程序根路径
|
||||
*
|
||||
* @return 程序根路径
|
||||
*/
|
||||
public String getRootPath() {
|
||||
return Optional.ofNullable(rootPath).orElse(System.getProperty(DEFAULT_PROPERTY));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置程序根路径
|
||||
*
|
||||
* @param rootPath 程序根路径
|
||||
*/
|
||||
public void setRootPath(String rootPath) {
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上次的程序根路径
|
||||
*
|
||||
* @return 上次的程序根路径
|
||||
*/
|
||||
public String getLastRootPath() {
|
||||
return lastRootPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置上次的程序根路径
|
||||
*
|
||||
* @param lastRootPath 上次的程序根路径
|
||||
*/
|
||||
public void setLastRootPath(String lastRootPath) {
|
||||
this.lastRootPath = lastRootPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排除的文件夹集合
|
||||
*
|
||||
* @return 排除的文件夹集合
|
||||
*/
|
||||
public Set<File> getIgnoreFolder() {
|
||||
return ignoreFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排除的文件集合
|
||||
*
|
||||
* @return 排除的文件集合
|
||||
*/
|
||||
public Set<File> getIgnoreFile() {
|
||||
return ignoreFile;
|
||||
}
|
||||
|
||||
@ -7,15 +7,29 @@ import java.util.List;
|
||||
/**
|
||||
* 插件配置文件
|
||||
*
|
||||
* <p>
|
||||
* 此类用于存储插件的配置信息,包括插件描述符的列表。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class PluginConfig {
|
||||
private List<PluginDescriptor> plugins;
|
||||
|
||||
/**
|
||||
* 获取插件描述符列表
|
||||
*
|
||||
* @return 插件描述符列表
|
||||
*/
|
||||
public List<PluginDescriptor> getPlugins() {
|
||||
return plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置插件描述符列表
|
||||
*
|
||||
* @param plugins 插件描述符列表
|
||||
*/
|
||||
public void setPlugins(List<PluginDescriptor> plugins) {
|
||||
this.plugins = plugins;
|
||||
}
|
||||
|
||||
@ -8,7 +8,11 @@ import java.util.List;
|
||||
/**
|
||||
* 用户配置文件类
|
||||
*
|
||||
* @author 许轲
|
||||
* <p>
|
||||
* 此类用于存储用户的配置信息,包括语言设置、文本自动换行设置和快捷键配置。
|
||||
* </p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public class UserConfig {
|
||||
|
||||
@ -17,27 +21,56 @@ public class UserConfig {
|
||||
private boolean textWrap;
|
||||
private List<ShortcutKey> shortcutKey;
|
||||
|
||||
|
||||
/**
|
||||
* 获取语言设置
|
||||
*
|
||||
* @return 语言设置
|
||||
*/
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置语言设置
|
||||
*
|
||||
* @param language 语言设置
|
||||
*/
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取快捷键配置列表
|
||||
*
|
||||
* @return 快捷键配置列表
|
||||
*/
|
||||
public List<ShortcutKey> getShortcutKey() {
|
||||
return shortcutKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置快捷键配置列表
|
||||
*
|
||||
* @param shortcutKey 快捷键配置列表
|
||||
*/
|
||||
public void setShortcutKey(List<ShortcutKey> shortcutKey) {
|
||||
this.shortcutKey = shortcutKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文本自动换行设置
|
||||
*
|
||||
* @return 是否启用文本自动换行
|
||||
*/
|
||||
public boolean isTextWrap() {
|
||||
return textWrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文本自动换行设置
|
||||
*
|
||||
* @param textWrap 是否启用文本自动换行
|
||||
*/
|
||||
public void setTextWrap(boolean textWrap) {
|
||||
this.textWrap = textWrap;
|
||||
}
|
||||
|
||||
@ -13,6 +13,22 @@ import java.util.ResourceBundle;
|
||||
/**
|
||||
* UI资源绑定,用于加载语言文件。
|
||||
*
|
||||
* <p>
|
||||
* 此类用于加载和管理UI资源文件,支持国际化和多语言功能。可以通过绑定StringProperty和键值对应的内容,以及获取当前资源文件的内容。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 该类是一个单例类,通过getInstance方法获取实例。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 使用方法示例:
|
||||
* <code>
|
||||
* UiResourceBundle.bindStringProperty(stringProperty, "key");
|
||||
* String content = UiResourceBundle.getContent("key");
|
||||
* </code>
|
||||
* </p>
|
||||
*
|
||||
* @author songdragon
|
||||
*/
|
||||
public class UiResourceBundle {
|
||||
@ -21,7 +37,7 @@ public class UiResourceBundle {
|
||||
/**
|
||||
* resource目录下的i18n/i18nXXX.properties
|
||||
*/
|
||||
private static final String BASENAME = "i18n/i18n";
|
||||
private static final String BASENAME = "jcnc/app/i18n/i18n";
|
||||
/**
|
||||
* 资源文件的观察者绑定。
|
||||
*/
|
||||
@ -35,6 +51,11 @@ public class UiResourceBundle {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取UiResourceBundle的单例实例
|
||||
*
|
||||
* @return UiResourceBundle的单例实例
|
||||
*/
|
||||
public static UiResourceBundle getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
@ -81,6 +102,8 @@ public class UiResourceBundle {
|
||||
|
||||
/**
|
||||
* 重置当前local
|
||||
*
|
||||
* @param toLocal 要设置的新的Locale
|
||||
*/
|
||||
public final void resetLocal(Locale toLocal) {
|
||||
if (this.currentLocale == toLocal) {
|
||||
|
||||
@ -8,22 +8,22 @@ import javafx.scene.layout.Pane;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
import org.jcnc.jnotepad.JnotepadApp;
|
||||
import org.jcnc.jnotepad.app.common.constants.AppConstants;
|
||||
import org.jcnc.jnotepad.app.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.app.common.manager.ThreadPoolManager;
|
||||
import org.jcnc.jnotepad.app.config.AppConfig;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.common.constants.AppConstants;
|
||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
||||
import org.jcnc.jnotepad.app.utils.FileUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.app.utils.UiUtil;
|
||||
import org.jcnc.jnotepad.controller.ResourceController;
|
||||
import org.jcnc.jnotepad.controller.cache.CacheController;
|
||||
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
||||
import org.jcnc.jnotepad.controller.exception.AppException;
|
||||
import org.jcnc.jnotepad.controller.manager.Controller;
|
||||
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
||||
import org.jcnc.jnotepad.util.FileUtil;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.views.manager.*;
|
||||
import org.jcnc.jnotepad.controller.plugin.manager.PluginManager;
|
||||
import org.jcnc.jnotepad.ui.views.manager.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -34,13 +34,19 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.DEFAULT_PROPERTY;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
|
||||
/**
|
||||
* 应用程序管理类<br/>
|
||||
* 此类负责管理应用程序的生命周期等操作
|
||||
* 应用程序管理类
|
||||
*
|
||||
* <p>
|
||||
* 此类负责管理应用程序的生命周期和操作。它包括初始化应用程序、执行默认操作、加载缓存、加载资源、迁移程序根文件夹、停止前操作等功能。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 该类是一个单例类,通过getInstance方法获取实例。
|
||||
* </p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
@ -55,22 +61,27 @@ public class ApplicationManager {
|
||||
private Stage primaryStage;
|
||||
private Application application;
|
||||
|
||||
|
||||
private ApplicationManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取ApplicationManager的单例实例
|
||||
*
|
||||
* @return ApplicationManager的单例实例
|
||||
*/
|
||||
public static ApplicationManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化程序(Initializes the application)
|
||||
* 初始化应用程序
|
||||
*
|
||||
* @apiNote
|
||||
* @since 2023/9/20 17:26
|
||||
* <p>
|
||||
* 此方法用于初始化应用程序的各个组件,包括设置应用程序主题、初始化UI组件、初始化插件、初始化顶部菜单栏、初始化侧边工具栏、初始化下方状态栏、初始化标签页布局等。
|
||||
* </p>
|
||||
*/
|
||||
public void initializeApp() {
|
||||
// 设置应用程序主题 SetTheApplicationTheme
|
||||
// 设置应用程序主题
|
||||
Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
|
||||
// 初始化scene
|
||||
initScene();
|
||||
@ -92,6 +103,10 @@ public class ApplicationManager {
|
||||
|
||||
/**
|
||||
* 执行默认操作
|
||||
*
|
||||
* <p>
|
||||
* 此方法用于执行应用程序的默认操作,例如根据参数打开关联文件并创建文本区域,加载已打开的文件夹等。
|
||||
* </p>
|
||||
*/
|
||||
public void executeDefaultAction() {
|
||||
// 使用加载关联文件并创建文本区域
|
||||
@ -106,7 +121,7 @@ public class ApplicationManager {
|
||||
double width = AppConstants.SCREEN_WIDTH;
|
||||
double length = AppConstants.SCREEN_LENGTH;
|
||||
scene = new Scene(root, width, length);
|
||||
scene.getStylesheets().add(Objects.requireNonNull(application.getClass().getResource("/css/styles.css")).toExternalForm());
|
||||
scene.getStylesheets().add(Objects.requireNonNull(application.getClass().getResource("/jcnc/app/css/styles.css")).toExternalForm());
|
||||
}
|
||||
|
||||
private void initPrimaryStage() {
|
||||
@ -124,6 +139,10 @@ public class ApplicationManager {
|
||||
|
||||
/**
|
||||
* 加载缓存
|
||||
*
|
||||
* <p>
|
||||
* 此方法用于加载应用程序的缓存。
|
||||
* </p>
|
||||
*/
|
||||
public void loadAppCache() {
|
||||
// 加载缓存
|
||||
@ -132,6 +151,10 @@ public class ApplicationManager {
|
||||
|
||||
/**
|
||||
* 加载资源
|
||||
*
|
||||
* <p>
|
||||
* 此方法用于加载应用程序的资源,包括加载资源文件和绑定快捷键。
|
||||
* </p>
|
||||
*/
|
||||
public void loadAppResources() {
|
||||
// 加载资源
|
||||
@ -142,6 +165,10 @@ public class ApplicationManager {
|
||||
|
||||
/**
|
||||
* 迁移程序根文件夹
|
||||
*
|
||||
* <p>
|
||||
* 此方法用于迁移应用程序的根文件夹,将根文件夹从之前的位置迁移到新的位置。
|
||||
* </p>
|
||||
*/
|
||||
public void migrateFileRootFolder() {
|
||||
AppConfig config = AppConfigController.getInstance().getConfig();
|
||||
@ -174,7 +201,9 @@ public class ApplicationManager {
|
||||
/**
|
||||
* 停止前操作
|
||||
*
|
||||
* @apiNote 在停止程序之前会执行此操作
|
||||
* <p>
|
||||
* 在停止应用程序之前,执行一系列操作,包括刷新插件配置、销毁插件、保存已打开的文件标签页、将缓存写入本地、迁移程序根文件夹、关闭线程池等。
|
||||
* </p>
|
||||
*/
|
||||
public void operationBeforeStopping() {
|
||||
PluginConfigController pluginConfigController = PluginConfigController.getInstance();
|
||||
@ -195,7 +224,7 @@ public class ApplicationManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前窗口。
|
||||
* 获取当前窗口
|
||||
*
|
||||
* @return 当前窗口
|
||||
*/
|
||||
@ -206,8 +235,7 @@ public class ApplicationManager {
|
||||
/**
|
||||
* 获取当前窗口的场景
|
||||
*
|
||||
* @return javafx.scene.Scene
|
||||
* @since 2023/9/20 18:21
|
||||
* @return 当前窗口的场景
|
||||
*/
|
||||
public Scene getScene() {
|
||||
return scene;
|
||||
@ -220,8 +248,9 @@ public class ApplicationManager {
|
||||
/**
|
||||
* 加载程序布局
|
||||
*
|
||||
* @apiNote
|
||||
* @since 2023/9/20 17:25
|
||||
* <p>
|
||||
* 此方法用于加载应用程序的布局,包括根布局容器、底部根侧边栏垂直布局、主界面边界布局、顶部边界面板、右侧边栏垂直布局、根布局等组件。
|
||||
* </p>
|
||||
*/
|
||||
public void initAppLayout() {
|
||||
// 加载根布局容器
|
||||
@ -237,9 +266,15 @@ public class ApplicationManager {
|
||||
RootRightSideBarVerticalBoxManager.getInstance().initRootRightSideBarVerticalBox();
|
||||
// 初始化根布局
|
||||
RootBorderPaneManager.getInstance().initRootBorderPane();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 重启应用程序
|
||||
*
|
||||
* <p>
|
||||
* 此方法用于重启当前的Java应用程序。
|
||||
* </p>
|
||||
*/
|
||||
public void restart() {
|
||||
try {
|
||||
// 获取当前Java应用程序的命令
|
||||
@ -250,14 +285,12 @@ public class ApplicationManager {
|
||||
ProcessBuilder builder = new ProcessBuilder(javaCommand, "-cp", System.getProperty("java.class.path"), mainClass);
|
||||
builder.start();
|
||||
// 关闭当前应用程序
|
||||
// fixme 使用这个System.exit(0);,在开发环境,点击重启程序,停止前操作不生效
|
||||
stop();
|
||||
} catch (IOException e) {
|
||||
LogUtil.getLogger("正在重启当前应用程序".getClass());
|
||||
LoggerUtil.getLogger("正在重启当前应用程序".getClass());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Pane getRoot() {
|
||||
return root;
|
||||
}
|
||||
@ -282,6 +315,13 @@ public class ApplicationManager {
|
||||
this.primaryStage = primaryStage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止应用程序
|
||||
*
|
||||
* <p>
|
||||
* 此方法用于停止应用程序。
|
||||
* </p>
|
||||
*/
|
||||
public void stop() {
|
||||
Platform.exit();
|
||||
}
|
||||
|
||||
42
src/main/java/org/jcnc/jnotepad/app/utils/ClipboardUtil.java
Normal file
42
src/main/java/org/jcnc/jnotepad/app/utils/ClipboardUtil.java
Normal file
@ -0,0 +1,42 @@
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
|
||||
/**
|
||||
* 剪切板工具
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class ClipboardUtil {
|
||||
/**
|
||||
* 系统剪切板对象
|
||||
*/
|
||||
private static final Clipboard CLIPBOARD = Clipboard.getSystemClipboard();
|
||||
|
||||
private ClipboardUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the provided text to the system clipboard.
|
||||
*
|
||||
* @param text the text to be written to the clipboard
|
||||
*/
|
||||
public static void writeTextToClipboard(String text) {
|
||||
ClipboardContent content = new ClipboardContent();
|
||||
content.putString(text);
|
||||
CLIPBOARD.setContent(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads text from the clipboard.
|
||||
*
|
||||
* @return the text read from the clipboard
|
||||
*/
|
||||
public static String readTextFromClipboard() {
|
||||
String text = CLIPBOARD.getString();
|
||||
LoggerUtil.getLogger(ClipboardUtil.class).info("剪切板内容:{}", text);
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.util;
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import com.ibm.icu.text.CharsetDetector;
|
||||
import com.ibm.icu.text.CharsetMatch;
|
||||
@ -21,7 +21,7 @@ public class EncodingDetector {
|
||||
* 编码侦测概率阈值,50%
|
||||
*/
|
||||
public static final int THRESHOLD_CONFIDENCE = 50;
|
||||
private static final Logger LOG = LogUtil.getLogger(EncodingDetector.class);
|
||||
private static final Logger LOG = LoggerUtil.getLogger(EncodingDetector.class);
|
||||
|
||||
private EncodingDetector() {
|
||||
}
|
||||
@ -1,10 +1,14 @@
|
||||
package org.jcnc.jnotepad.util;
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.image.ImageView;
|
||||
import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenFile;
|
||||
import org.jcnc.jnotepad.controller.exception.AppException;
|
||||
import org.jcnc.jnotepad.model.entity.DirFileModel;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
@ -14,8 +18,8 @@ import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static org.kordamp.ikonli.antdesignicons.AntDesignIconsFilled.*;
|
||||
|
||||
@ -27,6 +31,13 @@ import static org.kordamp.ikonli.antdesignicons.AntDesignIconsFilled.*;
|
||||
public class FileUtil {
|
||||
private static final MessageDigest MESSAGE_DIGEST_SHA_256;
|
||||
private static final int BUFFER_SIZE = 8192;
|
||||
private static final Logger logger = LoggerUtil.getLogger(FileUtil.class);
|
||||
|
||||
private static final String WINDOWS = "win";
|
||||
|
||||
private static final String MAC = "mac";
|
||||
|
||||
private static final String PATH = "path";
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -130,7 +141,7 @@ public class FileUtil {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
LogUtil.getLogger(OpenFile.class).info("已忽视IO异常!");
|
||||
LoggerUtil.getLogger(OpenFile.class).info("已忽视IO异常!");
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
@ -146,7 +157,11 @@ public class FileUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
DirFileModel dirFileModel = new DirFileModel(file.getAbsolutePath(), file.getName(), new ArrayList<>(), new FontIcon(FOLDER), new FontIcon(FOLDER_OPEN));
|
||||
DirFileModel dirFileModel = new DirFileModel(
|
||||
file.getAbsolutePath(),
|
||||
file.getName(), new ArrayList<>(),
|
||||
new FontIcon(FOLDER),
|
||||
new FontIcon(FOLDER_OPEN));
|
||||
|
||||
File[] files = file.listFiles();
|
||||
if (files != null) {
|
||||
@ -155,14 +170,67 @@ public class FileUtil {
|
||||
DirFileModel childDirFileModel = getDirFileModel(f);
|
||||
dirFileModel.getChildFile().add(childDirFileModel);
|
||||
} else {
|
||||
// todo 在此监测文件后缀,设置对应的图标
|
||||
dirFileModel.getChildFile().add(new DirFileModel(f.getAbsolutePath(), f.getName(), null, new FontIcon(FILE), new FontIcon(FILE)));
|
||||
// 在此监测文件后缀,设置对应的图标
|
||||
dirFileModel.getChildFile().add(new DirFileModel(
|
||||
f.getAbsolutePath(), f.getName(), null,
|
||||
getIconCorrespondingToFileName(f.getName()),
|
||||
null));
|
||||
}
|
||||
}
|
||||
}
|
||||
return dirFileModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a DirFileModel object based on the given dirFileModels map.
|
||||
*
|
||||
* @param dirFileModels a map containing the dirFileModels data
|
||||
* @return the DirFileModel object
|
||||
*/
|
||||
public static DirFileModel getDirFileModel(Map<String, Object> dirFileModels) {
|
||||
if (Objects.isNull(dirFileModels) || dirFileModels.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
File rootDir = new File((String) dirFileModels.get(PATH));
|
||||
DirFileModel dirFileModel = new DirFileModel(
|
||||
rootDir.getAbsolutePath(),
|
||||
rootDir.getName(), new ArrayList<>(),
|
||||
new FontIcon(FOLDER),
|
||||
new FontIcon(FOLDER_OPEN), (Boolean) dirFileModels.get("open"));
|
||||
Optional<Object> o = Optional.ofNullable(dirFileModels.get("childFile"));
|
||||
if (o.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
List<Map<String, Object>> childFile = (List<Map<String, Object>>) o.get();
|
||||
File[] files = rootDir.listFiles();
|
||||
if (files == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (File f : files) {
|
||||
if (f.isDirectory()) {
|
||||
Optional<Map<String, Object>> first = childFile
|
||||
.stream()
|
||||
.filter(map -> map.get(PATH).equals(f.getAbsolutePath())).findFirst();
|
||||
DirFileModel childDirFileModel;
|
||||
if (first.isPresent()) {
|
||||
childDirFileModel = getDirFileModel(first.get());
|
||||
} else {
|
||||
childDirFileModel = getDirFileModel(f);
|
||||
}
|
||||
dirFileModel.getChildFile().add(childDirFileModel);
|
||||
} else {
|
||||
// 在此监测文件后缀,设置对应的图标
|
||||
dirFileModel.getChildFile().add(new DirFileModel(
|
||||
f.getAbsolutePath(), f.getName(), null,
|
||||
getIconCorrespondingToFileName(f.getName()),
|
||||
null));
|
||||
}
|
||||
}
|
||||
return dirFileModel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 文件夹迁移
|
||||
*
|
||||
@ -267,5 +335,100 @@ public class FileUtil {
|
||||
throw new AppException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the file explorer to the specified file or its parent directory.
|
||||
*
|
||||
* @param file the file or directory to open in the file explorer
|
||||
*/
|
||||
public static void openExplorer(File file) {
|
||||
try { // 判断传入的是文件还是文件夹
|
||||
if (file.isDirectory()) {
|
||||
Desktop.getDesktop().open(file);
|
||||
}
|
||||
// 如果是文件则打开所在文件夹
|
||||
else {
|
||||
Desktop.getDesktop().open(file.getParentFile());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new AppException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the icon corresponding to the given file name.
|
||||
*
|
||||
* @param fileName the file name
|
||||
* @return the corresponding icon for the file extension
|
||||
*/
|
||||
public static Node getIconCorrespondingToFileName(String fileName) {
|
||||
// 在此根据文件缀名获取对应的图标
|
||||
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
|
||||
Node orDefault = UiUtil.getIconMap().getOrDefault(fileExtension, FontIcon.of(FILE_UNKNOWN));
|
||||
if (orDefault instanceof FontIcon fontIcon) {
|
||||
return new FontIcon(fontIcon.getIconLiteral());
|
||||
}
|
||||
if (orDefault instanceof ImageView imageView) {
|
||||
return new ImageView(imageView.getImage());
|
||||
}
|
||||
return orDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a terminal in the specified folder.
|
||||
*
|
||||
* @param folder the folder in which to open the terminal
|
||||
*/
|
||||
public static void openTerminal(File folder) {
|
||||
if (!folder.exists()) {
|
||||
return;
|
||||
}
|
||||
if (folder.isFile()) {
|
||||
folder = folder.getParentFile();
|
||||
}
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
ProcessBuilder processBuilder = getProcessBuilder(folder, os);
|
||||
try {
|
||||
processBuilder.start();
|
||||
} catch (IOException e) {
|
||||
PopUpUtil.errorAlert("打开失败", "打开于终端失败", "错误原因:" + e.getMessage(), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a ProcessBuilder object based on the provided folder and operating system.
|
||||
*
|
||||
* @param folder the folder to set as the working directory for the ProcessBuilder object
|
||||
* @param os the operating system to determine the appropriate command for the ProcessBuilder object
|
||||
* @return a ProcessBuilder object with the correct command for the specified operating system
|
||||
*/
|
||||
private static ProcessBuilder getProcessBuilder(File folder, String os) {
|
||||
ProcessBuilder processBuilder;
|
||||
if (os.contains(WINDOWS)) {
|
||||
// Windows系统
|
||||
processBuilder = new ProcessBuilder("cmd.exe", "/c", "start", "cmd.exe", "/k", "cd", folder.getAbsolutePath());
|
||||
} else if (os.contains(MAC)) {
|
||||
// macOS系统
|
||||
processBuilder = new ProcessBuilder("open", "-a", "Terminal", folder.getAbsolutePath());
|
||||
} else {
|
||||
// Linux或其他系统
|
||||
processBuilder = new ProcessBuilder("xdg-open", folder.getAbsolutePath());
|
||||
}
|
||||
return processBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file at the specified path.
|
||||
*
|
||||
* @param path The path to the file to be created.
|
||||
*/
|
||||
public static void createFile(Path path) {
|
||||
try {
|
||||
Files.createFile(path);
|
||||
} catch (IOException e) {
|
||||
logger.error("创建文件失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.util;
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.util;
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -10,8 +10,8 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class LogUtil {
|
||||
private LogUtil() {
|
||||
public class LoggerUtil {
|
||||
private LoggerUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
102
src/main/java/org/jcnc/jnotepad/app/utils/NotificationUtil.java
Normal file
102
src/main/java/org/jcnc/jnotepad/app/utils/NotificationUtil.java
Normal file
@ -0,0 +1,102 @@
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import atlantafx.base.controls.Notification;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import org.jcnc.jnotepad.ui.views.manager.RootManager;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* 通知实用程序
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class NotificationUtil {
|
||||
private static final RootManager ROOT_MANAGER = RootManager.getInstance();
|
||||
private static final StackPane ROOT_STACK_PANE = ROOT_MANAGER.getRootStackPane();
|
||||
|
||||
private NotificationUtil() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a custom notification with the given message and icon, applying the specified styles.
|
||||
*
|
||||
* @param message the message to display in the notification
|
||||
* @param icon the icon to display in the notification
|
||||
* @param styles additional styles to apply to the notification
|
||||
*/
|
||||
public static void customNotification(String message, FontIcon icon, String... styles) {
|
||||
Notification notification = new Notification(message, icon);
|
||||
Collections.addAll(notification.getStyleClass(), styles);
|
||||
RootManager.addNotificationToStackPane(ROOT_STACK_PANE, notification, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a success notification with the given message.
|
||||
*
|
||||
* @param message the message to be displayed in the notification
|
||||
*/
|
||||
public static void successNotification(String message) {
|
||||
Notification notification = new Notification(message, UiUtil.getSuccessIcon());
|
||||
setStyleClass(notification, Styles.SUCCESS);
|
||||
RootManager.addNotificationToStackPane(ROOT_STACK_PANE, notification, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an info notification with the given message.
|
||||
*
|
||||
* @param message the message to display in the notification
|
||||
*/
|
||||
public static void infoNotification(String message) {
|
||||
Notification notification = new Notification(message, UiUtil.getInfoIcon());
|
||||
setStyleClass(notification, Styles.ACCENT);
|
||||
RootManager.addNotificationToStackPane(ROOT_STACK_PANE, notification, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an error notification with the given message and displays it on the root stack pane.
|
||||
*
|
||||
* @param message the error message to be displayed
|
||||
*/
|
||||
public static void errorNotification(String message) {
|
||||
Notification notification = new Notification(message, UiUtil.getErrorIcon());
|
||||
setStyleClass(notification, Styles.DANGER);
|
||||
RootManager.addNotificationToStackPane(ROOT_STACK_PANE, notification, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a warning notification with the given message and displays it on the root stack pane.
|
||||
*
|
||||
* @param message the warning message to be displayed
|
||||
*/
|
||||
public static void warningNotification(String message) {
|
||||
Notification notification = new Notification(message, UiUtil.getWarningIcon());
|
||||
setStyleClass(notification, Styles.WARNING);
|
||||
RootManager.addNotificationToStackPane(ROOT_STACK_PANE, notification, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a question notification with the given message and displays it on the root stack pane.
|
||||
*
|
||||
* @param message the question message to be displayed
|
||||
*/
|
||||
public static void questionNotification(String message) {
|
||||
Notification notification = new Notification(message, UiUtil.getQuestionIcon());
|
||||
setStyleClass(notification, Styles.ACCENT);
|
||||
RootManager.addNotificationToStackPane(ROOT_STACK_PANE, notification, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the style class of the given notification.
|
||||
*
|
||||
* @param notification The notification object to set the style class for.
|
||||
* @param styleClass The style class to add to the notification.
|
||||
*/
|
||||
private static void setStyleClass(Notification notification, String styleClass) {
|
||||
notification.getStyleClass().add(Styles.ELEVATED_1);
|
||||
notification.getStyleClass().add(styleClass);
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
package org.jcnc.jnotepad.util;
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import org.jcnc.jnotepad.component.stage.dialog.AppDialogBuilder;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.interfaces.DialogButtonAction;
|
||||
import org.jcnc.jnotepad.model.enums.DialogType;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.AppDialogBuilder;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.interfaces.DialogButtonAction;
|
||||
|
||||
/**
|
||||
* 弹窗工具类
|
||||
70
src/main/java/org/jcnc/jnotepad/app/utils/ResourceUtil.java
Normal file
70
src/main/java/org/jcnc/jnotepad/app/utils/ResourceUtil.java
Normal file
@ -0,0 +1,70 @@
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import org.jcnc.jnotepad.JnotepadApp;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 资源工具
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class ResourceUtil {
|
||||
public static final String MODULE_DIR = "/jcnc/app/";
|
||||
|
||||
private ResourceUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an input stream for the specified resource.
|
||||
*
|
||||
* @param resource the path to the resource
|
||||
* @return the input stream for the resource
|
||||
*/
|
||||
public static InputStream getResourceAsStream(String resource) {
|
||||
String path = resolve(resource);
|
||||
return Objects.requireNonNull(
|
||||
JnotepadApp.class.getResourceAsStream(resolve(path)),
|
||||
"Resource not found: " + path
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the resource with the specified path.
|
||||
*
|
||||
* @param resource the path of the resource to retrieve
|
||||
* @return the URI of the retrieved resource
|
||||
*/
|
||||
public static URI getResource(String resource) {
|
||||
String path = resolve(resource);
|
||||
URL url = Objects.requireNonNull(JnotepadApp.class.getResource(resolve(path)), "Resource not found: " + path);
|
||||
return URI.create(url.toExternalForm());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a resource path by checking if it starts with a "/". If it does,
|
||||
* the resource path is returned as is. If it doesn't, the resource path is
|
||||
* concatenated with the module directory path.
|
||||
*
|
||||
* @param resource the resource path to be resolved
|
||||
* @param moduleDir the module directory path
|
||||
* @return the resolved resource path
|
||||
*/
|
||||
public static String resolve(String resource, String moduleDir) {
|
||||
Objects.requireNonNull(resource);
|
||||
return resource.startsWith("/") ? resource : moduleDir + resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given resource using the default module directory.
|
||||
*
|
||||
* @param resource the resource to resolve
|
||||
* @return the resolved resource
|
||||
*/
|
||||
public static String resolve(String resource) {
|
||||
return resolve(resource, MODULE_DIR);
|
||||
}
|
||||
}
|
||||
338
src/main/java/org/jcnc/jnotepad/app/utils/TabUtil.java
Normal file
338
src/main/java/org/jcnc/jnotepad/app/utils/TabUtil.java
Normal file
@ -0,0 +1,338 @@
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.jcnc.jnotepad.app.common.constants.AppConstants;
|
||||
import org.jcnc.jnotepad.app.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.app.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.controller.config.UserConfigController;
|
||||
import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenFile;
|
||||
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
|
||||
import org.jcnc.jnotepad.model.entity.Cache;
|
||||
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
|
||||
import org.jcnc.jnotepad.ui.component.module.TextCodeArea;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.factory.impl.BasicFileChooserFactory;
|
||||
import org.jcnc.jnotepad.ui.views.manager.BottomStatusBoxManager;
|
||||
import org.jcnc.jnotepad.ui.views.manager.CenterTabPaneManager;
|
||||
import org.jcnc.jnotepad.ui.views.root.center.main.center.tab.CenterTab;
|
||||
import org.jcnc.jnotepad.ui.views.root.center.main.center.tab.CenterTabPane;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jcnc.jnotepad.app.common.constants.TextConstants.NEW_FILE;
|
||||
import static org.jcnc.jnotepad.app.utils.FileUtil.getFileText;
|
||||
import static org.jcnc.jnotepad.controller.config.UserConfigController.CONFIG_NAME;
|
||||
|
||||
/**
|
||||
* 标签页工具
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class TabUtil {
|
||||
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||
private static final Logger logger = LoggerUtil.getLogger(TabUtil.class);
|
||||
|
||||
private TabUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件标签页
|
||||
*/
|
||||
public static void saveFile(CenterTab tab) {
|
||||
if (tab == null) {
|
||||
return;
|
||||
}
|
||||
// 如果打开的是非关联文件,则调用另存为方法
|
||||
if (!tab.getRelevanceProperty()) {
|
||||
logger.info("当前保存文件为非关联打开文件,调用另存为方法");
|
||||
saveAsFile(tab);
|
||||
} else {
|
||||
logger.info("当前保存文件为关联打开文件,调用自动保存方法");
|
||||
// 调用tab保存方法
|
||||
tab.saveSelectedFileTab();
|
||||
// 如果该文件是配置文件,则刷新快捷键
|
||||
if (CONFIG_NAME.equals(tab.getText())) {
|
||||
// 重新加载语言包和快捷键
|
||||
UserConfigController.getInstance().loadConfig();
|
||||
UserConfigController.getInstance().initAllShortcutKeys();
|
||||
LocalizationController.initLocal();
|
||||
logger.info("已刷新语言包!");
|
||||
logger.info("已刷新快捷键!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 另存为
|
||||
*
|
||||
* @apiNote 将当前选中的标签页进行另存为弹出窗口式的保存。
|
||||
* @see LoggerUtil
|
||||
*/
|
||||
public static void saveAsFile(CenterTab tab) {
|
||||
if (tab == null) {
|
||||
return;
|
||||
}
|
||||
Cache cache = CACHE_MANAGER.getCache("folder", "saveFile");
|
||||
File file = BasicFileChooserFactory.getInstance().createFileChooser(
|
||||
UiResourceBundle.getContent(TextConstants.SAVE_AS),
|
||||
tab.getText(),
|
||||
cache == null ? null : new File((String) cache.getCacheData()),
|
||||
new FileChooser.ExtensionFilter("All types", "*.*"))
|
||||
.showSaveDialog(UiUtil.getAppWindow());
|
||||
if (file != null) {
|
||||
if (cache == null) {
|
||||
CACHE_MANAGER.addCache(
|
||||
CACHE_MANAGER.createCache("folder", "saveFile", file.getParent(),
|
||||
CacheExpirationTime.NEVER_EXPIRES.getValue()));
|
||||
} else {
|
||||
cache.setCacheData(file.getParent());
|
||||
CACHE_MANAGER.addCache(cache);
|
||||
}
|
||||
logger.info("正在保存文件: {}", file.getName());
|
||||
tab.save(file);
|
||||
// 将保存后的文件设置为关联文件
|
||||
tab.setRelevanceProperty(true);
|
||||
// 更新标签页上的文件名
|
||||
tab.setText(file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重命名
|
||||
*/
|
||||
public static void rename(CenterTab tab) {
|
||||
if (tab == null || tab.getText().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 判断当前是否为关联文件
|
||||
if (tab.getRelevanceProperty()) {
|
||||
// 重命名关联文件
|
||||
handleRenameRelevanceFile(tab);
|
||||
}
|
||||
// 如果当前不是关联文件则重命名标签页
|
||||
else {
|
||||
handleRenameTab(tab);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重命名标签页。
|
||||
*
|
||||
* @param tab 标签页组件
|
||||
*/
|
||||
private static void handleRenameTab(CenterTab tab) {
|
||||
// 临时记录标签页名称
|
||||
String tempName = tab.getText();
|
||||
TextField textField = new TextField(tempName);
|
||||
textField.getStyleClass().add("tab-title-editable");
|
||||
// 清空标签页名称
|
||||
tab.setText("");
|
||||
// 监听 Enter 键,完成编辑
|
||||
textField.setOnKeyPressed(event -> {
|
||||
if (event.getCode() == KeyCode.ENTER) {
|
||||
String newTabName = textField.getText();
|
||||
// 检查是否存在相同名称的标签页
|
||||
if (tabNameExists(newTabName)) {
|
||||
|
||||
// 显示弹窗并提示用户更换名称
|
||||
showDuplicateNameAlert(newTabName);
|
||||
|
||||
// 恢复原始名称
|
||||
tab.setText(tempName);
|
||||
|
||||
} else {
|
||||
tab.setText(newTabName);
|
||||
// 可选:移除 TextField 的图形
|
||||
tab.setGraphic(null);
|
||||
// 可选:恢复标签页的关闭按钮
|
||||
tab.setClosable(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 监听失去焦点事件,完成编辑
|
||||
textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
String newTabName = textField.getText();
|
||||
// 检查是否存在相同名称的标签页
|
||||
if (tabNameExists(newTabName)) {
|
||||
// 恢复原始名称
|
||||
tab.setText(tempName);
|
||||
|
||||
}
|
||||
if (Boolean.FALSE.equals(newValue)) {
|
||||
tab.setText(newTabName);
|
||||
// 可选:移除 TextField 的图形
|
||||
tab.setGraphic(null);
|
||||
// 可选:恢复标签页的关闭按钮
|
||||
tab.setClosable(true);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
tab.setClosable(false);
|
||||
// 设置 TextField 作为标签页的图形
|
||||
tab.setGraphic(textField);
|
||||
// 默认获取焦点并选中所有文字
|
||||
textField.requestFocus();
|
||||
textField.selectAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否存在具有相同名称的标签页。
|
||||
*
|
||||
* @param newTabName 要检查的新标签页名称
|
||||
* @return 如果存在具有相同名称的标签页,则返回 true;否则返回 false
|
||||
*/
|
||||
private static boolean tabNameExists(String newTabName) {
|
||||
CenterTabPane tabPane = CenterTabPane.getInstance();
|
||||
return tabPane.getTabs().stream()
|
||||
.anyMatch(tab -> tab.getText().equals(newTabName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示警告弹窗,提示用户更换重复的名称。
|
||||
*/
|
||||
private static void showDuplicateNameAlert(String newTabName) {
|
||||
PopUpUtil.errorAlert(
|
||||
"重命名错误",
|
||||
"\" " + newTabName + "\" 和已有标签页名字重复",
|
||||
"请再次重命名",
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重命名关联文件。
|
||||
*
|
||||
* @param tab 标签页组件
|
||||
*/
|
||||
private static void handleRenameRelevanceFile(CenterTab tab) {
|
||||
// 获取原始文件对象
|
||||
File file = (File) tab.getUserData();
|
||||
|
||||
// 获取应用窗口并绑定
|
||||
File newFile = BasicFileChooserFactory.getInstance()
|
||||
.createFileChooser(
|
||||
UiResourceBundle.getContent(TextConstants.RENAME),
|
||||
tab.getText(),
|
||||
new File(file.getParent()),
|
||||
new FileChooser.ExtensionFilter("All types", "*.*"))
|
||||
.showSaveDialog(UiUtil.getAppWindow());
|
||||
if (newFile != null) {
|
||||
boolean rename = file.renameTo(newFile);
|
||||
// 设置文件数据
|
||||
tab.setUserData(newFile);
|
||||
if (rename) {
|
||||
tab.setText(newFile.getName());
|
||||
logger.info("文件重命名成功");
|
||||
} else {
|
||||
logger.debug("文件重命名失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加新的文件标签页。
|
||||
*/
|
||||
public static void addNewFileTab() {
|
||||
// 创建一个新的文本编辑区
|
||||
TextCodeArea textArea = new TextCodeArea();
|
||||
// 创建标签页
|
||||
CenterTab centerTab = new CenterTab(
|
||||
generateDefaultName(),
|
||||
textArea);
|
||||
// 将Tab页添加到TabPane中
|
||||
CenterTabPaneManager.getInstance().addNewTab(centerTab);
|
||||
// 更新编码信息
|
||||
BottomStatusBoxManager.getInstance().updateEncodingLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the default name for a new tab.
|
||||
*
|
||||
* @return The default name for a new tab.
|
||||
*/
|
||||
private static String generateDefaultName() {
|
||||
// 设定初始索引
|
||||
int index = 1;
|
||||
StringBuilder tabTitle = new StringBuilder();
|
||||
String content = UiResourceBundle.getContent(NEW_FILE);
|
||||
// 获取当前默认创建标签页集合
|
||||
List<Tab> tabs = CenterTabPane.getInstance()
|
||||
.getTabs()
|
||||
.stream()
|
||||
// 排除不属于默认创建的标签页
|
||||
.filter(tab -> AppConstants.TABNAME_PATTERN.matcher(tab.getText()).matches())
|
||||
// 对默认创建的标签页进行排序
|
||||
.sorted(Comparator.comparing(tab -> {
|
||||
String tabText = tab.getText();
|
||||
// 提取数字部分
|
||||
String numberPart = tabText.substring(content.length());
|
||||
// 解析为数字
|
||||
return Integer.parseInt(numberPart);
|
||||
}))
|
||||
// 转为List集合
|
||||
.toList();
|
||||
// 构建初始标签页名称
|
||||
tabTitle.append(content).append(index);
|
||||
for (Tab tab : tabs) {
|
||||
if (tab.getText().contentEquals(tabTitle)) {
|
||||
tabTitle.setLength(0);
|
||||
tabTitle.append(content).append(++index);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tabTitle.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开文件到选项卡
|
||||
*
|
||||
* @param file 文件对象
|
||||
*/
|
||||
public static void openFileToTab(File file) {
|
||||
// 获取标签页集合
|
||||
CenterTabPane centerTabPane = CenterTabPane.getInstance();
|
||||
// 遍历标签页,查找匹配的标签页
|
||||
for (Tab tab : centerTabPane.getTabs()) {
|
||||
// 获取绑定的文件
|
||||
File tabFile = (File) tab.getUserData();
|
||||
if (tabFile == null) {
|
||||
continue;
|
||||
}
|
||||
if (file.getPath().equals((tabFile).getPath())) {
|
||||
// 找到匹配的标签页,设置为选中状态并跳转
|
||||
centerTabPane.getSelectionModel().select(tab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
getText(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文本文件的内容。
|
||||
*
|
||||
* @param file 文件对象
|
||||
*/
|
||||
public static void getText(File file) {
|
||||
TextCodeArea textCodeArea = new TextCodeArea();
|
||||
// 检测文件编码
|
||||
Charset encoding = EncodingDetector.detectEncodingCharset(file);
|
||||
String fileText = getFileText(file, encoding);
|
||||
LoggerUtil.getLogger(OpenFile.class).info("已调用读取文件功能");
|
||||
textCodeArea.appendText(fileText);
|
||||
// 设置当前标签页关联本地文件 设置标签页关联文件
|
||||
CenterTab tab = new CenterTab(file.getName(), textCodeArea, encoding, file, true);
|
||||
// 设置关联文件最后的修改时间
|
||||
tab.setLastModifiedTimeOfAssociatedFile(file.lastModified());
|
||||
CenterTabPaneManager.getInstance().addNewTab(tab);
|
||||
}
|
||||
}
|
||||
222
src/main/java/org/jcnc/jnotepad/app/utils/UiUtil.java
Normal file
222
src/main/java/org/jcnc/jnotepad/app/utils/UiUtil.java
Normal file
@ -0,0 +1,222 @@
|
||||
package org.jcnc.jnotepad.app.utils;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.stage.Window;
|
||||
import org.jcnc.jnotepad.app.common.constants.AppConstants;
|
||||
import org.jcnc.jnotepad.app.manager.ApplicationManager;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.kordamp.ikonli.antdesignicons.AntDesignIconsFilled.*;
|
||||
|
||||
/**
|
||||
* UI工具
|
||||
*
|
||||
* <p>封装了项目中需要引入的UI组件</p>
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class UiUtil {
|
||||
/**
|
||||
* 应用程序图标
|
||||
*/
|
||||
private static final Image APP_ICON = new Image(Objects.requireNonNull(UiUtil.class.getResource(AppConstants.APP_ICON)).toString());
|
||||
|
||||
/**
|
||||
* 错误图标
|
||||
*/
|
||||
private static final FontIcon ERROR_ICON = FontIcon.of(EXCLAMATION_CIRCLE);
|
||||
|
||||
/**
|
||||
* 信息图标
|
||||
*/
|
||||
private static final FontIcon INFO_ICON = FontIcon.of(INFO_CIRCLE);
|
||||
/**
|
||||
* 警告图标
|
||||
*/
|
||||
private static final FontIcon WARNING_ICON = FontIcon.of(WARNING);
|
||||
/**
|
||||
* 问题图标
|
||||
*/
|
||||
private static final FontIcon QUESTION_ICON = FontIcon.of(QUESTION_CIRCLE);
|
||||
|
||||
private static final FontIcon SUCCESS_ICON = FontIcon.of(CHECK_CIRCLE);
|
||||
/**
|
||||
* 图标集合
|
||||
*/
|
||||
private static final Map<String, Node> ICON_MAP = new HashMap<>(32);
|
||||
|
||||
static {
|
||||
// 暂时设置颜色
|
||||
ERROR_ICON.getStyleClass().addAll(Styles.DANGER);
|
||||
INFO_ICON.getStyleClass().addAll(Styles.ACCENT);
|
||||
QUESTION_ICON.getStyleClass().addAll(Styles.ACCENT);
|
||||
WARNING_ICON.getStyleClass().addAll(Styles.WARNING);
|
||||
SUCCESS_ICON.getStyleClass().addAll(Styles.SUCCESS);
|
||||
ICON_MAP.put("css", fileIconByPng("css"));
|
||||
ICON_MAP.put("doc", fileIconByPng("doc"));
|
||||
ICON_MAP.put("dll", fileIconByPng("dll"));
|
||||
ICON_MAP.put("exe", fileIconByPng("exe"));
|
||||
ICON_MAP.put("gif", fileIconByPng("gif"));
|
||||
ICON_MAP.put("gitignore", fileIconByPng("git"));
|
||||
ICON_MAP.put("html", fileIconByPng("html"));
|
||||
ICON_MAP.put("json", fileIconByPng("json"));
|
||||
ICON_MAP.put("md", fileIconByPng("markdown"));
|
||||
ICON_MAP.put("pdf", FontIcon.of(FILE_PDF));
|
||||
ICON_MAP.put("ppt", FontIcon.of(FILE_PPT));
|
||||
ICON_MAP.put("png", fileIconByPng("png"));
|
||||
ICON_MAP.put("sql", fileIconByPng("database"));
|
||||
ICON_MAP.put("svg", fileIconByPng("svg"));
|
||||
ICON_MAP.put("txt", FontIcon.of(FILE_TEXT));
|
||||
ICON_MAP.put("xls", FontIcon.of(FILE_EXCEL));
|
||||
ICON_MAP.put("xml", fileIconByPng("xml"));
|
||||
// 编程语言
|
||||
ICON_MAP.put("bat", fileIconByPng("bat"));
|
||||
ICON_MAP.put("c", fileIconByPng("c"));
|
||||
ICON_MAP.put("cs", fileIconByPng("csharp"));
|
||||
ICON_MAP.put("cpp", fileIconByPng("cplusplus"));
|
||||
ICON_MAP.put("go", fileIconByPng("golang"));
|
||||
ICON_MAP.put("js", fileIconByPng("js"));
|
||||
ICON_MAP.put("java", fileIconByPng("java"));
|
||||
ICON_MAP.put("kt", fileIconByPng("kotlin"));
|
||||
ICON_MAP.put("lua", fileIconByPng("lua"));
|
||||
ICON_MAP.put("py", fileIconByPng("python"));
|
||||
ICON_MAP.put("php", fileIconByPng("php"));
|
||||
ICON_MAP.put("rb", fileIconByPng("ruby"));
|
||||
ICON_MAP.put("sh", fileIconByPng("sh"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
private UiUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用程序图标。
|
||||
*
|
||||
* @return javafx.scene.image.Image 应用程序图标对象
|
||||
*/
|
||||
public static Image getAppIcon() {
|
||||
return APP_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the information icon.
|
||||
*
|
||||
* @return the information icon
|
||||
*/
|
||||
|
||||
public static FontIcon getInfoIcon() {
|
||||
return INFO_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error icon.
|
||||
*
|
||||
* @return the error icon
|
||||
*/
|
||||
public static FontIcon getErrorIcon() {
|
||||
return ERROR_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the warning icon.
|
||||
*
|
||||
* @return the warning icon
|
||||
*/
|
||||
public static FontIcon getWarningIcon() {
|
||||
return WARNING_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the question icon.
|
||||
*
|
||||
* @return the question icon
|
||||
*/
|
||||
public static FontIcon getQuestionIcon() {
|
||||
return QUESTION_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the success icon.
|
||||
*
|
||||
* @return the success icon as a FontIcon object
|
||||
*/
|
||||
public static FontIcon getSuccessIcon() {
|
||||
return SUCCESS_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用窗口。
|
||||
*
|
||||
* @return javafx.stage.Window 应用窗口对象
|
||||
* @apiNote JnotepadApp.getWindow()
|
||||
*/
|
||||
public static Window getAppWindow() {
|
||||
return ApplicationManager.getInstance().getWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an ImageView with the specified module directory, name, and format.
|
||||
*
|
||||
* @param moduleDir the directory where the module is located
|
||||
* @param name the name of the icon
|
||||
* @param format the format of the icon
|
||||
* @return the generated ImageView
|
||||
*/
|
||||
public static ImageView icon(String moduleDir, String name, String format) {
|
||||
return icon(moduleDir + name + format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an ImageView object with the image specified by the given path.
|
||||
*
|
||||
* @param path the path to the image file
|
||||
* @return the ImageView object with the specified image
|
||||
*/
|
||||
public static ImageView icon(String path) {
|
||||
var img = new Image(ResourceUtil.getResourceAsStream(path));
|
||||
return new ImageView(img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an ImageView based on a PNG file.
|
||||
*
|
||||
* @param moduleDir the directory of the module
|
||||
* @param name the name of the PNG file
|
||||
* @return the generated ImageView
|
||||
*/
|
||||
public static ImageView iconByPng(String moduleDir, String name) {
|
||||
return icon(moduleDir + name + ".png");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an ImageView object for a file icon based on the given PNG name.
|
||||
*
|
||||
* @param name the name of the PNG file for the file icon
|
||||
* @return the ImageView object representing the file icon
|
||||
*/
|
||||
public static ImageView fileIconByPng(String name) {
|
||||
return iconByPng("images/fileIcons/", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an ImageView object for a file icon based on the given PNG name.
|
||||
*
|
||||
* @param name the name of the PNG file for the file icon
|
||||
* @return the ImageView object representing the file icon
|
||||
*/
|
||||
public static ImageView sidebarIconByPng(String name) {
|
||||
return iconByPng("images/sidebarIcons/", name);
|
||||
}
|
||||
|
||||
public static Map<String, Node> getIconMap() {
|
||||
return ICON_MAP;
|
||||
}
|
||||
}
|
||||
1
src/main/java/org/jcnc/jnotepad/app/utils/aReadme.md
Normal file
1
src/main/java/org/jcnc/jnotepad/app/utils/aReadme.md
Normal file
@ -0,0 +1 @@
|
||||
util 存放通用的实用工具代码。
|
||||
@ -1,25 +0,0 @@
|
||||
package org.jcnc.jnotepad.common.constants;
|
||||
|
||||
/**
|
||||
* SplitPane常量类
|
||||
* *
|
||||
* <p>用于记录SplitPane中子组件的索引</p>
|
||||
*
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class SplitPaneItemConstants {
|
||||
|
||||
// rootSplitPane
|
||||
|
||||
// 上部
|
||||
public static final int ROOT_SPLIT_PANE_TOP_SPLIT_PANE = 0;
|
||||
// 底部
|
||||
public static final int ROOT_SPLIT_PANE_CMDBox = 1;
|
||||
|
||||
// rootSplitPane中的上部面板
|
||||
// 左侧
|
||||
public static final int TOP_SPLIT_PANE_DIRECTORY_SIDEBAR_PANE = 0;
|
||||
// 右侧
|
||||
public static final int TOP_SPLIT_PANE_CENTER_TAB_PANE = 1;
|
||||
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
package org.jcnc.jnotepad.common.constants;
|
||||
|
||||
|
||||
/**
|
||||
* 文本常量,被多处使用的常量放到此处。如果只有一个class使用,在class中使用private static final声明。
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class TextConstants {
|
||||
|
||||
public static final String TITLE = "title";
|
||||
public static final String SAVE = "SAVE";
|
||||
public static final String FILE = "FILE";
|
||||
|
||||
public static final String BUILD = "BUILD";
|
||||
public static final String TERMINAL = "TERMINAL";
|
||||
|
||||
public static final String RUN = "RUN";
|
||||
public static final String DE_BUG = "DE_BUG";
|
||||
public static final String NEW = "NEW";
|
||||
public static final String OPEN = "OPEN";
|
||||
public static final String OPEN_DIRECTORY = "OPEN_DIRECTORY";
|
||||
public static final String SAVE_AS = "SAVE_AS";
|
||||
public static final String RENAME = "RENAME";
|
||||
public static final String SET = "SET";
|
||||
public static final String HELP = "HELP";
|
||||
public static final String WORD_WRAP = "WORD_WRAP";
|
||||
public static final String PLUGIN = "PLUGIN";
|
||||
public static final String MANAGER_PLUGIN = "MANAGER_PLUGIN";
|
||||
|
||||
public static final String ABOUT = "ABOUT";
|
||||
|
||||
public static final String DEVELOPER = "DEVELOPER";
|
||||
public static final String STATISTICS = "STATISTICS";
|
||||
public static final String OPEN_CONFIGURATION_FILE = "OPEN_CONFIGURATION_FILE";
|
||||
public static final String TOP = "TOP";
|
||||
public static final String LANGUAGE = "LANGUAGE";
|
||||
public static final String UPPER_CHINESE = "CHINESE";
|
||||
public static final String UPPER_ENGLISH = "ENGLISH";
|
||||
public static final String NEW_FILE = "NEW_FILE";
|
||||
public static final String ROW = "ROW";
|
||||
public static final String COLUMN = "COLUMN";
|
||||
public static final String WORD_COUNT = "WORD_COUNT";
|
||||
public static final String ENCODE = "ENCODE";
|
||||
/**
|
||||
* 英文小写
|
||||
*/
|
||||
public static final String ENGLISH = "english";
|
||||
|
||||
/// BaseConfig 文本常量
|
||||
/**
|
||||
* 中文小写
|
||||
*/
|
||||
public static final String CHINESE = "chinese";
|
||||
|
||||
private TextConstants() {
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
package org.jcnc.jnotepad.component.module.base;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import org.jcnc.jnotepad.component.module.interfaces.BorderPaneAble;
|
||||
|
||||
/**
|
||||
* 抽象边界面板类
|
||||
*
|
||||
* <p>这个抽象类继承自JavaFX的BorderPane类,实现了BorderPaneAble接口,用于管理UI组件的布局。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public abstract class AbstractBorderPane extends BorderPane implements BorderPaneAble {
|
||||
|
||||
@Override
|
||||
public void setTopComponent(Node node) {
|
||||
setTop(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBottomComponent(Node node) {
|
||||
setBottom(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLeftComponent(Node node) {
|
||||
setLeft(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRightComponent(Node node) {
|
||||
setRight(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCenterComponent(Node node) {
|
||||
setCenter(node);
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package org.jcnc.jnotepad.component.module.base;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.HBox;
|
||||
import org.jcnc.jnotepad.component.module.interfaces.HorizontalBoxAble;
|
||||
|
||||
/**
|
||||
* 抽象水平盒子类
|
||||
*
|
||||
* <p>这个抽象类继承自JavaFX的HBox类,实现了HBoxAble接口,用于管理水平排列的UI组件。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public abstract class AbstractHorizontalBox extends HBox implements HorizontalBoxAble {
|
||||
private final HBox hBox;
|
||||
|
||||
public AbstractHorizontalBox() {
|
||||
hBox = new HBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChild(Node node) {
|
||||
hBox.getChildren().add(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChild(Node... nodes) {
|
||||
hBox.getChildren().addAll(nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HBox getHorizontalBox() {
|
||||
return hBox;
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
package org.jcnc.jnotepad.component.module.base;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jcnc.jnotepad.component.module.interfaces.VerticalBoxAble;
|
||||
|
||||
/**
|
||||
* 抽象垂直盒子类
|
||||
*
|
||||
* <p>这个抽象类继承自JavaFX的VBox类,实现了VBoxAble接口,用于管理垂直排列的UI组件。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public abstract class AbstractVerticalBox extends VBox implements VerticalBoxAble {
|
||||
|
||||
private final VBox vBox;
|
||||
|
||||
public AbstractVerticalBox() {
|
||||
vBox = new VBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChild(Node node) {
|
||||
vBox.getChildren().add(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChild(Node... nodes) {
|
||||
vBox.getChildren().addAll(nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VBox getVerticalBox() {
|
||||
return vBox;
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
package org.jcnc.jnotepad.component.module.vbox;
|
||||
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import org.jcnc.jnotepad.component.module.vbox.components.CmdTerminalBox;
|
||||
import org.jcnc.jnotepad.component.module.vbox.components.DebugBox;
|
||||
import org.jcnc.jnotepad.component.module.vbox.components.RunBox;
|
||||
|
||||
/**
|
||||
* 底部Run,Debug,Cmd面板
|
||||
*
|
||||
*
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class BuildPanel extends TabPane {
|
||||
|
||||
private static BuildPanel instance = null;
|
||||
|
||||
public static BuildPanel getInstance() {
|
||||
|
||||
if (instance == null) {
|
||||
instance = new BuildPanel();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final CmdTerminalBox cmdTerminalBox;
|
||||
private final RunBox runBox;
|
||||
private final DebugBox debugBox;
|
||||
|
||||
private BuildPanel() {
|
||||
cmdTerminalBox = new CmdTerminalBox();
|
||||
runBox = new RunBox();
|
||||
debugBox = new DebugBox();
|
||||
|
||||
Tab runTab = new Tab("运行",runBox);
|
||||
runTab.setClosable(false);
|
||||
|
||||
Tab buildTab = new Tab("构建", debugBox);
|
||||
buildTab.setClosable(false);
|
||||
|
||||
Tab cmdTab = new Tab("终端",cmdTerminalBox);
|
||||
cmdTab.setClosable(false);
|
||||
this.getTabs().addAll(runTab,buildTab,cmdTab);
|
||||
}
|
||||
|
||||
public CmdTerminalBox getCmdTerminalBox() {
|
||||
return cmdTerminalBox;
|
||||
}
|
||||
|
||||
public RunBox getRunBox() {
|
||||
return runBox;
|
||||
}
|
||||
|
||||
public DebugBox getBuildBox() {
|
||||
return debugBox;
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package org.jcnc.jnotepad.component.module.vbox.components;
|
||||
|
||||
import org.jcnc.jnotepad.component.module.TextCodeArea;
|
||||
|
||||
/**
|
||||
* Debug终端界面。
|
||||
*
|
||||
*
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class DebugBox extends TextCodeArea {
|
||||
public DebugBox() {
|
||||
super();
|
||||
this.setEditable(false);
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.appendText(text);
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
package org.jcnc.jnotepad.component.module.vbox.components;
|
||||
|
||||
import org.jcnc.jnotepad.component.module.TextCodeArea;
|
||||
|
||||
/**
|
||||
* Run终端界面。
|
||||
*
|
||||
*
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class RunBox extends TextCodeArea {
|
||||
|
||||
|
||||
public RunBox() {
|
||||
super();
|
||||
this.setEditable(false);
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.appendText(text);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
package org.jcnc.jnotepad.controller;
|
||||
|
||||
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
|
||||
import org.jcnc.jnotepad.plugin.PluginLoader;
|
||||
import org.jcnc.jnotepad.controller.plugin.PluginLoader;
|
||||
|
||||
/**
|
||||
* 资源控制器
|
||||
|
||||
1
src/main/java/org/jcnc/jnotepad/controller/aReadme.md
Normal file
1
src/main/java/org/jcnc/jnotepad/controller/aReadme.md
Normal file
@ -0,0 +1 @@
|
||||
controller 存放控制器相关的代码,包括事件处理、异常处理等。
|
||||
@ -1,11 +1,11 @@
|
||||
package org.jcnc.jnotepad.controller.cache;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.app.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.app.utils.JsonUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||
import org.jcnc.jnotepad.model.entity.Cache;
|
||||
import org.jcnc.jnotepad.util.JsonUtil;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
@ -27,10 +27,8 @@ import java.util.Set;
|
||||
public class CacheController {
|
||||
|
||||
private static final ApplicationCacheManager APPLICATION_CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
|
||||
private static final CacheController INSTANCE = new CacheController();
|
||||
|
||||
Logger logger = LoggerUtil.getLogger(this.getClass());
|
||||
private String cacheDir;
|
||||
|
||||
private CacheController() {
|
||||
@ -56,6 +54,18 @@ public class CacheController {
|
||||
return;
|
||||
}
|
||||
Map<String, Cache> caches = new HashMap<>(16);
|
||||
setCaches(namespaces, cacheFileDir, caches);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the caches for the given namespaces.
|
||||
*
|
||||
* @param namespaces an array of namespace names
|
||||
* @param cacheFileDir the directory where the cache files are stored
|
||||
* @param caches a map of caches to be set
|
||||
*/
|
||||
private void setCaches(String[] namespaces, File cacheFileDir, Map<String, Cache> caches) {
|
||||
for (String namespace : namespaces) {
|
||||
// 获取命名空间对应的文件夹
|
||||
File namespaceDir = new File(cacheFileDir, namespace);
|
||||
@ -82,12 +92,16 @@ public class CacheController {
|
||||
cacheMap.forEach((k, v) -> setUpCache(namespace, groupName, k, v, caches));
|
||||
} catch (IOException e) {
|
||||
logger.error("读取缓存文件出错!", e);
|
||||
try {
|
||||
Files.delete(cacheFileDir.toPath());
|
||||
} catch (IOException ignore) {
|
||||
logger.error("删除失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置缓存
|
||||
APPLICATION_CACHE_MANAGER.setCaches(caches);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -5,8 +5,8 @@ import org.jcnc.jnotepad.app.config.AppConfig;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.DEFAULT_PROPERTY;
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.DEFAULT_PROPERTY;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
|
||||
/**
|
||||
* 应用程序配置文件控制器
|
||||
@ -15,24 +15,22 @@ import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIREC
|
||||
*/
|
||||
public class AppConfigController extends BaseConfigController<AppConfig> {
|
||||
|
||||
private static final AppConfigController INSTANCE = new AppConfigController();
|
||||
|
||||
public static AppConfigController getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置文件名
|
||||
*/
|
||||
public static final String CONFIG_NAME = "JNotepadConfig.json";
|
||||
|
||||
private static final AppConfigController INSTANCE = new AppConfigController();
|
||||
private final String configDir;
|
||||
|
||||
public AppConfigController() {
|
||||
configDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, systemConfigDir).toString();
|
||||
configDir = Paths.get(System.getProperty(DEFAULT_PROPERTY), PROGRAM_FILE_DIRECTORY, SYSTEM_CONFIG_DIR).toString();
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
public static AppConfigController getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置文件Class类
|
||||
*
|
||||
|
||||
@ -7,7 +7,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
|
||||
/**
|
||||
* 插件控制器
|
||||
@ -26,7 +26,7 @@ public class PluginConfigController extends BaseConfigController<PluginConfig> {
|
||||
|
||||
private PluginConfigController() {
|
||||
String rootPath = AppConfigController.getInstance().getConfig().getRootPath();
|
||||
configDir = Paths.get(rootPath, PROGRAM_FILE_DIRECTORY, rootConfigDir).toString();
|
||||
configDir = Paths.get(rootPath, PROGRAM_FILE_DIRECTORY, ROOT_CONFIG_DIR).toString();
|
||||
setPluginsDir(Paths.get(rootPath, PROGRAM_FILE_DIRECTORY, "plugins").toString());
|
||||
loadConfig();
|
||||
}
|
||||
@ -66,6 +66,10 @@ public class PluginConfigController extends BaseConfigController<PluginConfig> {
|
||||
return configDir;
|
||||
}
|
||||
|
||||
public void setConfigDir(String configDir) {
|
||||
this.configDir = configDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建配置文件实体
|
||||
*
|
||||
@ -79,11 +83,6 @@ public class PluginConfigController extends BaseConfigController<PluginConfig> {
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
|
||||
public void setConfigDir(String configDir) {
|
||||
this.configDir = configDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件路径
|
||||
*
|
||||
|
||||
@ -1,15 +1,20 @@
|
||||
package org.jcnc.jnotepad.controller.config;
|
||||
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.input.KeyCombination;
|
||||
import org.jcnc.jnotepad.api.core.controller.config.BaseConfigController;
|
||||
import org.jcnc.jnotepad.app.config.UserConfig;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.model.entity.ShortcutKey;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
import static org.jcnc.jnotepad.common.constants.TextConstants.CHINESE;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.PROGRAM_FILE_DIRECTORY;
|
||||
import static org.jcnc.jnotepad.app.common.constants.TextConstants.CHINESE;
|
||||
|
||||
/**
|
||||
* 应用程序配置控制器
|
||||
@ -29,13 +34,16 @@ public class UserConfigController extends BaseConfigController<UserConfig> {
|
||||
private static final String CTRL_ALT_S = "ctrl+alt+s";
|
||||
private static final String ALT_S = "alt+s";
|
||||
private static final UserConfigController INSTANCE = new UserConfigController();
|
||||
private final List<Map<String, MenuItem>> menuItems = new ArrayList<>();
|
||||
Logger logger = LoggerUtil.getLogger(this.getClass());
|
||||
private String configDir;
|
||||
|
||||
private UserConfigController() {
|
||||
configDir = Paths.get(AppConfigController.getInstance().getConfig().getRootPath(), PROGRAM_FILE_DIRECTORY, rootConfigDir).toString();
|
||||
configDir = Paths.get(AppConfigController.getInstance().getConfig().getRootPath(), PROGRAM_FILE_DIRECTORY, ROOT_CONFIG_DIR).toString();
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 UserConfigController 的实例。
|
||||
*
|
||||
@ -164,4 +172,35 @@ public class UserConfigController extends BaseConfigController<UserConfig> {
|
||||
return getConfig().getShortcutKey();
|
||||
}
|
||||
|
||||
public void initAllShortcutKeys() {
|
||||
menuItems.forEach(this::initShortcutKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化快捷键
|
||||
*/
|
||||
public void initShortcutKeys(Map<String, MenuItem> menuItemMap) {
|
||||
List<MenuItem> itemsToUnbind = new ArrayList<>();
|
||||
List<ShortcutKey> shortcutKeyConfigs = getShortcutKey();
|
||||
for (ShortcutKey shortcutKey : shortcutKeyConfigs) {
|
||||
// 保证json的key必须和变量名一致
|
||||
MenuItem menuItem = menuItemMap.get(shortcutKey.getButtonName());
|
||||
String shortKeyValue = shortcutKey.getShortcutKeyValue();
|
||||
if ("".equals(shortKeyValue) && menuItem != null) {
|
||||
itemsToUnbind.add(menuItem);
|
||||
continue;
|
||||
}
|
||||
if (menuItem != null) {
|
||||
logger.info("功能名称:{}->快捷键:{}", menuItem.getText(), shortKeyValue);
|
||||
// 动态添加快捷键
|
||||
menuItem.setAccelerator(KeyCombination.keyCombination(shortKeyValue));
|
||||
}
|
||||
}
|
||||
// 解绑需要解绑的快捷键
|
||||
itemsToUnbind.forEach(menuItem -> menuItem.setAccelerator(null));
|
||||
}
|
||||
|
||||
public List<Map<String, MenuItem>> getMenuItems() {
|
||||
return menuItems;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,18 +2,8 @@ package org.jcnc.jnotepad.controller.event.handler.menuitem;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.Tab;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.common.constants.AppConstants;
|
||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.component.module.TextCodeArea;
|
||||
import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager;
|
||||
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
|
||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
|
||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.addNewFileTab;
|
||||
|
||||
/**
|
||||
* 新建文件事件的事件处理程序。
|
||||
@ -32,46 +22,4 @@ public class NewFile implements EventHandler<ActionEvent> {
|
||||
public void handle(ActionEvent event) {
|
||||
addNewFileTab();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加新的文件标签页。
|
||||
*/
|
||||
public void addNewFileTab() {
|
||||
// 创建一个新的文本编辑区
|
||||
TextCodeArea textArea = new TextCodeArea();
|
||||
// TODO: refactor:统一TextArea新建、绑定监听器入口
|
||||
// 设定初始索引
|
||||
int index = 1;
|
||||
StringBuilder tabTitle = new StringBuilder();
|
||||
// 获取当前默认创建标签页集合
|
||||
List<Tab> tabs = CenterTabPane.getInstance()
|
||||
.getTabs()
|
||||
.stream()
|
||||
// 排除不属于默认创建的标签页
|
||||
.filter(tab -> AppConstants.TABNAME_PATTERN.matcher(tab.getText()).matches())
|
||||
// 对默认创建的标签页进行排序
|
||||
.sorted(Comparator.comparing(Tab::getText))
|
||||
// 转为List集合
|
||||
.toList();
|
||||
// 构建初始标签页名称
|
||||
tabTitle.append(UiResourceBundle.getContent(TextConstants.NEW_FILE)).append(index);
|
||||
for (Tab tab : tabs) {
|
||||
if (tab.getText().contentEquals(tabTitle)) {
|
||||
tabTitle.setLength(0);
|
||||
tabTitle.append(UiResourceBundle.getContent(TextConstants.NEW_FILE)).append(++index);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 创建标签页
|
||||
CenterTab centerTab = new CenterTab(
|
||||
tabTitle.toString(),
|
||||
textArea);
|
||||
// 设置当前标签页与本地文件无关联
|
||||
centerTab.setRelevance(false);
|
||||
// 将Tab页添加到TabPane中
|
||||
CenterTabPaneManager.getInstance().addNewTab(centerTab);
|
||||
// 更新编码信息
|
||||
BottomStatusBoxManager.getInstance().updateEncodingLabel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
package org.jcnc.jnotepad.controller.event.handler.menuitem;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.controller.config.UserConfigController;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.openFileToTab;
|
||||
|
||||
/**
|
||||
* 打开配置文件事件处理程序。
|
||||
*
|
||||
@ -24,8 +26,8 @@ public class OpenConfig extends OpenFile {
|
||||
public void handle(ActionEvent actionEvent) {
|
||||
// 显示文件选择对话框,并获取配置文件
|
||||
File file = UserConfigController.getInstance().getConfigPath().toFile();
|
||||
LogUtil.getLogger(this.getClass()).info("已调用打开配置文件功能, {}", file);
|
||||
LoggerUtil.getLogger(this.getClass()).info("已调用打开配置文件功能, {}", file);
|
||||
// 创建打开文件的任务并启动线程执行任务
|
||||
openFile(file);
|
||||
openFileToTab(file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,26 +2,18 @@ package org.jcnc.jnotepad.controller.event.handler.menuitem;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.jcnc.jnotepad.app.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.app.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.component.module.TextCodeArea;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicFileChooserFactory;
|
||||
import org.jcnc.jnotepad.app.utils.UiUtil;
|
||||
import org.jcnc.jnotepad.model.entity.Cache;
|
||||
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
|
||||
import org.jcnc.jnotepad.util.EncodingDetector;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
|
||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
|
||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.factory.impl.BasicFileChooserFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import static org.jcnc.jnotepad.util.FileUtil.getFileText;
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.openFileToTab;
|
||||
|
||||
|
||||
/**
|
||||
@ -60,73 +52,6 @@ public class OpenFile implements EventHandler<ActionEvent> {
|
||||
cache.setCacheData(file.getParent());
|
||||
CACHE_MANAGER.addCache(cache);
|
||||
}
|
||||
openFile(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开文件。
|
||||
*
|
||||
* @param file 文件对象
|
||||
*/
|
||||
public static void openFile(File file) {
|
||||
// 获取标签页集合
|
||||
CenterTabPane centerTabPane = CenterTabPane.getInstance();
|
||||
// 遍历标签页,查找匹配的标签页
|
||||
for (Tab tab : centerTabPane.getTabs()) {
|
||||
// 获取绑定的文件
|
||||
File tabFile = (File) tab.getUserData();
|
||||
if (tabFile == null) {
|
||||
continue;
|
||||
}
|
||||
if (file.getPath().equals((tabFile).getPath())) {
|
||||
// 找到匹配的标签页,设置为选中状态并跳转
|
||||
centerTabPane.getSelectionModel().select(tab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
getText(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文本文件的内容。
|
||||
*
|
||||
* @param file 文件对象
|
||||
*/
|
||||
public static void getText(File file) {
|
||||
TextCodeArea textCodeArea = createNewTextArea();
|
||||
// 检测文件编码
|
||||
Charset encoding = EncodingDetector.detectEncodingCharset(file);
|
||||
String fileText = getFileText(file, encoding);
|
||||
LogUtil.getLogger(OpenFile.class).info("已调用读取文件功能");
|
||||
textCodeArea.appendText(fileText);
|
||||
CenterTab tab = createNewTab(file.getName(), textCodeArea, encoding);
|
||||
// 设置当前标签页关联本地文件
|
||||
tab.setRelevance(true);
|
||||
// 设置标签页关联文件
|
||||
tab.setUserData(file);
|
||||
// 设置关联文件最后的修改时间
|
||||
tab.setLastModifiedTimeOfAssociatedFile(file.lastModified());
|
||||
CenterTabPaneManager.getInstance().addNewTab(tab);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建新的文本区域。
|
||||
*
|
||||
* @return 新的文本区域
|
||||
*/
|
||||
private static TextCodeArea createNewTextArea() {
|
||||
return new TextCodeArea();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新的标签页。
|
||||
*
|
||||
* @param tabName 标签名
|
||||
* @param textCodeArea 文本区域
|
||||
* @return 新的标签页
|
||||
*/
|
||||
private static CenterTab createNewTab(String tabName, TextCodeArea textCodeArea, Charset charset) {
|
||||
return new CenterTab(tabName, textCodeArea, charset);
|
||||
openFileToTab(file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,21 +2,9 @@ package org.jcnc.jnotepad.controller.event.handler.menuitem;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicFileChooserFactory;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
|
||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
|
||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.jcnc.jnotepad.ui.views.manager.CenterTabPaneManager;
|
||||
|
||||
import java.io.File;
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.rename;
|
||||
|
||||
/**
|
||||
* 重命名文件事件处理器。
|
||||
@ -27,137 +15,8 @@ import java.io.File;
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class RenameFile implements EventHandler<ActionEvent> {
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void handle(ActionEvent actionEvent) {
|
||||
// 获取当前标签页
|
||||
CenterTab centerTab = CenterTabPaneManager.getInstance().getSelected();
|
||||
if (centerTab == null || centerTab.getText().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 判断当前是否为关联文件
|
||||
if (centerTab.isRelevance()) {
|
||||
// 重命名关联文件
|
||||
handleRenameRelevanceFile(centerTab);
|
||||
}
|
||||
// 如果当前不是关联文件则重命名标签页
|
||||
else {
|
||||
handleRenameTab(centerTab);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重命名标签页。
|
||||
*
|
||||
* @param centerTab 标签页组件
|
||||
*/
|
||||
private void handleRenameTab(CenterTab centerTab) {
|
||||
TextField textField = new TextField(centerTab.getText());
|
||||
textField.getStyleClass().add("tab-title-editable");
|
||||
// 临时记录标签页名称
|
||||
String tempName = centerTab.getText();
|
||||
// 清空标签页名称
|
||||
centerTab.setText("");
|
||||
|
||||
// 监听 Enter 键,完成编辑
|
||||
textField.setOnKeyPressed(event -> {
|
||||
if (event.getCode() == KeyCode.ENTER) {
|
||||
String newTabName = textField.getText();
|
||||
// 检查是否存在相同名称的标签页
|
||||
if (isTabNameExists(newTabName)) {
|
||||
|
||||
// 显示弹窗并提示用户更换名称
|
||||
showDuplicateNameAlert(newTabName);
|
||||
|
||||
// 恢复原始名称
|
||||
centerTab.setText(tempName);
|
||||
|
||||
} else {
|
||||
centerTab.setText(newTabName);
|
||||
// 可选:移除 TextField 的图形
|
||||
centerTab.setGraphic(null);
|
||||
// 可选:恢复标签页的关闭按钮
|
||||
centerTab.setClosable(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 监听失去焦点事件,完成编辑
|
||||
textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
String newTabName = textField.getText();
|
||||
// 检查是否存在相同名称的标签页
|
||||
if (isTabNameExists(newTabName)) {
|
||||
// 恢复原始名称
|
||||
centerTab.setText(tempName);
|
||||
|
||||
}
|
||||
if (Boolean.FALSE.equals(newValue)) {
|
||||
centerTab.setText(newTabName);
|
||||
// 可选:移除 TextField 的图形
|
||||
centerTab.setGraphic(null);
|
||||
// 可选:恢复标签页的关闭按钮
|
||||
centerTab.setClosable(true);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
centerTab.setClosable(false);
|
||||
// 设置 TextField 作为标签页的图形
|
||||
centerTab.setGraphic(textField);
|
||||
// 默认获取焦点并选中所有文字
|
||||
textField.requestFocus();
|
||||
textField.selectAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否存在具有相同名称的标签页。
|
||||
*
|
||||
* @param newTabName 要检查的新标签页名称
|
||||
* @return 如果存在具有相同名称的标签页,则返回 true;否则返回 false
|
||||
*/
|
||||
private boolean isTabNameExists(String newTabName) {
|
||||
CenterTabPane tabPane = CenterTabPane.getInstance();
|
||||
return tabPane.getTabs().stream()
|
||||
.anyMatch(tab -> tab.getText().equals(newTabName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示警告弹窗,提示用户更换重复的名称。
|
||||
*/
|
||||
private void showDuplicateNameAlert(String newTabName) {
|
||||
|
||||
PopUpUtil.errorAlert("重命名错误", "\" " + newTabName + "\" 和已有标签页名字重复", "请再次重命名", null, null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 重命名关联文件。
|
||||
*
|
||||
* @param centerTab 标签页组件
|
||||
*/
|
||||
private void handleRenameRelevanceFile(CenterTab centerTab) {
|
||||
// 获取原始文件对象
|
||||
File file = (File) centerTab.getUserData();
|
||||
|
||||
// 获取应用窗口并绑定
|
||||
File newFile = BasicFileChooserFactory.getInstance()
|
||||
.createFileChooser(
|
||||
UiResourceBundle.getContent(TextConstants.RENAME),
|
||||
centerTab.getText(),
|
||||
new File(file.getParent()),
|
||||
new FileChooser.ExtensionFilter("All types", "*.*"))
|
||||
.showSaveDialog(UiUtil.getAppWindow());
|
||||
if (newFile != null) {
|
||||
boolean rename = file.renameTo(newFile);
|
||||
// 设置文件数据
|
||||
centerTab.setUserData(newFile);
|
||||
if (rename) {
|
||||
centerTab.setText(newFile.getName());
|
||||
logger.info("文件重命名成功");
|
||||
} else {
|
||||
logger.debug("文件重命名失败");
|
||||
}
|
||||
}
|
||||
rename(CenterTabPaneManager.getInstance().getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
package org.jcnc.jnotepad.controller.event.handler.menuitem;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.ui.views.manager.CenterTabPaneManager;
|
||||
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.saveAsFile;
|
||||
|
||||
/**
|
||||
* 保存文件事件处理器。
|
||||
@ -21,7 +24,7 @@ public class SaveAsFile extends SaveFile {
|
||||
*/
|
||||
@Override
|
||||
public void handle(ActionEvent event) {
|
||||
LogUtil.getLogger(SaveAsFile.class).info("已调用另存为功能");
|
||||
saveTab(this.getClass());
|
||||
LoggerUtil.getLogger(SaveAsFile.class).info("已调用另存为功能");
|
||||
saveAsFile(CenterTabPaneManager.getInstance().getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,25 +2,9 @@ package org.jcnc.jnotepad.controller.event.handler.menuitem;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicFileChooserFactory;
|
||||
import org.jcnc.jnotepad.controller.config.UserConfigController;
|
||||
import org.jcnc.jnotepad.controller.i18n.LocalizationController;
|
||||
import org.jcnc.jnotepad.model.entity.Cache;
|
||||
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
|
||||
import org.jcnc.jnotepad.views.manager.TopMenuBarManager;
|
||||
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
|
||||
import org.slf4j.Logger;
|
||||
import org.jcnc.jnotepad.ui.views.manager.CenterTabPaneManager;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.jcnc.jnotepad.controller.config.UserConfigController.CONFIG_NAME;
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.saveFile;
|
||||
|
||||
/**
|
||||
* 保存文件事件处理程序。
|
||||
@ -31,8 +15,6 @@ import static org.jcnc.jnotepad.controller.config.UserConfigController.CONFIG_NA
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class SaveFile implements EventHandler<ActionEvent> {
|
||||
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 处理保存文件事件。
|
||||
@ -43,63 +25,7 @@ public class SaveFile implements EventHandler<ActionEvent> {
|
||||
*/
|
||||
@Override
|
||||
public void handle(ActionEvent actionEvent) {
|
||||
// 获取当前tab页
|
||||
CenterTab selectedTab = CenterTabPaneManager.getInstance().getSelected();
|
||||
if (selectedTab == null) {
|
||||
return;
|
||||
}
|
||||
// 如果打开的是非关联文件,则调用另存为方法
|
||||
if (!selectedTab.isRelevance()) {
|
||||
logger.info("当前保存文件为非关联打开文件,调用另存为方法");
|
||||
saveTab(this.getClass());
|
||||
} else {
|
||||
logger.info("当前保存文件为关联打开文件,调用自动保存方法");
|
||||
// 调用tab保存方法
|
||||
selectedTab.saveSelectedFileTab();
|
||||
// 如果该文件是配置文件,则刷新快捷键
|
||||
if (CONFIG_NAME.equals(selectedTab.getText())) {
|
||||
// 重新加载语言包和快捷键
|
||||
UserConfigController.getInstance().loadConfig();
|
||||
TopMenuBarManager.getInstance().initShortcutKeys();
|
||||
LocalizationController.initLocal();
|
||||
logger.info("已刷新语言包!");
|
||||
logger.info("已刷新快捷键!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存标签页的方法。
|
||||
*
|
||||
* @param currentClass 调用该方法的类
|
||||
* @apiNote 将当前选中的标签页进行另存为弹出窗口式的保存。
|
||||
* @see LogUtil
|
||||
*/
|
||||
protected void saveTab(Class<?> currentClass) {
|
||||
CenterTab selectedTab = CenterTabPaneManager.getInstance().getSelected();
|
||||
if (selectedTab == null) {
|
||||
return;
|
||||
}
|
||||
Cache cache = CACHE_MANAGER.getCache("folder", "saveFile");
|
||||
File file = BasicFileChooserFactory.getInstance().createFileChooser(
|
||||
UiResourceBundle.getContent(TextConstants.SAVE_AS),
|
||||
selectedTab.getText(),
|
||||
cache == null ? null : new File((String) cache.getCacheData()),
|
||||
new FileChooser.ExtensionFilter("All types", "*.*"))
|
||||
.showSaveDialog(UiUtil.getAppWindow());
|
||||
if (file != null) {
|
||||
if (cache == null) {
|
||||
CACHE_MANAGER.addCache(CACHE_MANAGER.createCache("folder", "saveFile", file.getParent(), CacheExpirationTime.NEVER_EXPIRES.getValue()));
|
||||
} else {
|
||||
cache.setCacheData(file.getParent());
|
||||
CACHE_MANAGER.addCache(cache);
|
||||
}
|
||||
LogUtil.getLogger(currentClass).info("正在保存文件: {}", file.getName());
|
||||
selectedTab.save(file);
|
||||
// 将保存后的文件设置为关联文件
|
||||
selectedTab.setRelevance(true);
|
||||
// 更新标签页上的文件名
|
||||
selectedTab.setText(file.getName());
|
||||
}
|
||||
// 保存当前选中的标签页
|
||||
saveFile(CenterTabPaneManager.getInstance().getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package org.jcnc.jnotepad.controller.event.handler.toolbar;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import org.jcnc.jnotepad.views.manager.DirectorySidebarManager;
|
||||
import org.jcnc.jnotepad.ui.views.manager.DirectorySidebarManager;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -3,16 +3,16 @@ package org.jcnc.jnotepad.controller.event.handler.toolbar;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import org.jcnc.jnotepad.app.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.app.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicDirectoryChooserFactory;
|
||||
import org.jcnc.jnotepad.app.utils.FileUtil;
|
||||
import org.jcnc.jnotepad.app.utils.UiUtil;
|
||||
import org.jcnc.jnotepad.model.entity.Cache;
|
||||
import org.jcnc.jnotepad.model.entity.DirFileModel;
|
||||
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
|
||||
import org.jcnc.jnotepad.util.FileUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.views.manager.DirectorySidebarManager;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.factory.impl.BasicDirectoryChooserFactory;
|
||||
import org.jcnc.jnotepad.ui.views.manager.DirectorySidebarManager;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@ -25,10 +25,10 @@ import java.io.File;
|
||||
*/
|
||||
public class OpenDirectory implements EventHandler<ActionEvent> {
|
||||
|
||||
public static final String GROUP = "directory";
|
||||
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
|
||||
private static final DirectorySidebarManager DIRECTORY_SIDEBAR_MANAGER = DirectorySidebarManager.getInstance();
|
||||
|
||||
public static final String GROUP = "directory";
|
||||
@Override
|
||||
public void handle(ActionEvent actionEvent) {
|
||||
// 获取缓存
|
||||
@ -51,17 +51,21 @@ public class OpenDirectory implements EventHandler<ActionEvent> {
|
||||
CACHE_MANAGER.addCache(cache);
|
||||
}
|
||||
flushDirSidebar(file);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the directory sidebar with the given file.
|
||||
*
|
||||
* @param file the file to be converted into an entity class
|
||||
*/
|
||||
public void flushDirSidebar(File file) {
|
||||
// 将文件转为实体类
|
||||
DirFileModel dirFileModel = FileUtil.getDirFileModel(file);
|
||||
// 缓存已打开的文件夹
|
||||
CACHE_MANAGER.addCache(CACHE_MANAGER.createCache(GROUP, "folderThatWasOpened", file.getAbsolutePath(), CacheExpirationTime.NEVER_EXPIRES.getValue()));
|
||||
// 打开侧边栏
|
||||
DIRECTORY_SIDEBAR_MANAGER.controlShow(true);
|
||||
// 设置文件树功能
|
||||
DIRECTORY_SIDEBAR_MANAGER.setTreeView(dirFileModel);
|
||||
// 缓存已打开的文件夹
|
||||
CACHE_MANAGER.addCache(CACHE_MANAGER.createCache(GROUP, "folderThatWasOpened", dirFileModel, CacheExpirationTime.NEVER_EXPIRES.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,11 @@ package org.jcnc.jnotepad.controller.event.handler.toolbar;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import org.jcnc.jnotepad.views.manager.BuildPanelManager;
|
||||
import org.jcnc.jnotepad.ui.views.manager.BuildPanelManager;
|
||||
|
||||
/**
|
||||
* 终端处理器
|
||||
*
|
||||
*
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class RunBtn implements EventHandler<ActionEvent> {
|
||||
|
||||
@ -2,7 +2,7 @@ package org.jcnc.jnotepad.controller.event.handler.toolbar;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import org.jcnc.jnotepad.component.stage.setting.SetStage;
|
||||
import org.jcnc.jnotepad.ui.component.stage.setting.SetStage;
|
||||
|
||||
/**
|
||||
* 设置按钮事件的事件处理程序。
|
||||
|
||||
@ -9,8 +9,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jcnc.jnotepad.common.constants.TextConstants.CHINESE;
|
||||
import static org.jcnc.jnotepad.common.constants.TextConstants.ENGLISH;
|
||||
import static org.jcnc.jnotepad.app.common.constants.TextConstants.CHINESE;
|
||||
import static org.jcnc.jnotepad.app.common.constants.TextConstants.ENGLISH;
|
||||
|
||||
/**
|
||||
* 本地化控制器
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
package org.jcnc.jnotepad.controller.manager;
|
||||
|
||||
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.component.module.interfaces.ControllerAble;
|
||||
import org.jcnc.jnotepad.controller.event.handler.menuitem.NewFile;
|
||||
import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenFile;
|
||||
import org.jcnc.jnotepad.app.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.ui.component.module.interfaces.ControllerAble;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.addNewFileTab;
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.openFileToTab;
|
||||
|
||||
/**
|
||||
* 控制器类,实现 ControllerAble 接口,用于管理文本编辑器的各种操作和事件处理。
|
||||
*
|
||||
@ -44,15 +45,14 @@ public class Controller implements ControllerAble<List<String>> {
|
||||
// 判空
|
||||
List<String> fileTab = (List<String>) cacheData.orElse(Collections.emptyList());
|
||||
// 打开上次打开的标签页
|
||||
fileTab.forEach(filePath -> OpenFile.openFile(new File(filePath)));
|
||||
|
||||
fileTab.forEach(filePath -> openFileToTab(new File(filePath)));
|
||||
if (!rawParameters.isEmpty()) {
|
||||
String filePath = rawParameters.get(0);
|
||||
openAssociatedFile(filePath);
|
||||
return;
|
||||
}
|
||||
if (fileTab.isEmpty()) {
|
||||
new NewFile().addNewFileTab();
|
||||
addNewFileTab();
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ public class Controller implements ControllerAble<List<String>> {
|
||||
public void openAssociatedFile(String filePath) {
|
||||
File file = new File(filePath);
|
||||
if (file.exists() && file.isFile()) {
|
||||
OpenFile.openFile(file);
|
||||
openFileToTab(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package org.jcnc.jnotepad.plugin;
|
||||
package org.jcnc.jnotepad.controller.plugin;
|
||||
|
||||
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
||||
import org.jcnc.jnotepad.app.common.manager.ThreadPoolManager;
|
||||
import org.jcnc.jnotepad.app.utils.JsonUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
||||
import org.jcnc.jnotepad.controller.exception.AppException;
|
||||
import org.jcnc.jnotepad.controller.plugin.interfaces.Plugin;
|
||||
import org.jcnc.jnotepad.controller.plugin.manager.PluginManager;
|
||||
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||
import org.jcnc.jnotepad.plugin.interfaces.Plugin;
|
||||
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
||||
import org.jcnc.jnotepad.util.JsonUtil;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
@ -32,7 +32,7 @@ public class PluginLoader {
|
||||
private static final PluginLoader INSTANCE = new PluginLoader();
|
||||
|
||||
private static final ExecutorService THREAD_POOL = ThreadPoolManager.getThreadPool();
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
Logger logger = LoggerUtil.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 从插件jar包中读取 json 文件到 PluginDescriptor 类
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.plugin;
|
||||
package org.jcnc.jnotepad.controller.plugin;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
@ -6,11 +6,11 @@ import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicFileChooserFactory;
|
||||
import org.jcnc.jnotepad.plugin.manager.PluginManager;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.app.utils.PopUpUtil;
|
||||
import org.jcnc.jnotepad.app.utils.UiUtil;
|
||||
import org.jcnc.jnotepad.controller.plugin.manager.PluginManager;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.factory.impl.BasicFileChooserFactory;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
@ -26,7 +26,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class PluginManagerInterface {
|
||||
private static final PluginManagerInterface INSTANCE = new PluginManagerInterface();
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
Logger logger = LoggerUtil.getLogger(this.getClass());
|
||||
|
||||
public static PluginManagerInterface getInstance() {
|
||||
return INSTANCE;
|
||||
@ -0,0 +1 @@
|
||||
plugin 存放插件相关的代码,包括插件接口和管理器。
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.plugin.interfaces;
|
||||
package org.jcnc.jnotepad.controller.plugin.interfaces;
|
||||
|
||||
|
||||
/**
|
||||
@ -1,11 +1,11 @@
|
||||
package org.jcnc.jnotepad.plugin.manager;
|
||||
package org.jcnc.jnotepad.controller.plugin.manager;
|
||||
|
||||
import org.jcnc.jnotepad.app.common.manager.ThreadPoolManager;
|
||||
import org.jcnc.jnotepad.app.manager.ApplicationManager;
|
||||
import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.app.utils.PopUpUtil;
|
||||
import org.jcnc.jnotepad.controller.config.PluginConfigController;
|
||||
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
@ -18,7 +18,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.jcnc.jnotepad.plugin.PluginLoader.readPlugin;
|
||||
import static org.jcnc.jnotepad.controller.plugin.PluginLoader.readPlugin;
|
||||
|
||||
/**
|
||||
* 插件管理器
|
||||
@ -34,16 +34,15 @@ public class PluginManager {
|
||||
* 插件类别
|
||||
*/
|
||||
private final Map<String, List<String>> categories = new HashMap<>();
|
||||
Logger logger = LoggerUtil.getLogger(this.getClass());
|
||||
/**
|
||||
* 插件信息
|
||||
*/
|
||||
private List<PluginDescriptor> pluginDescriptors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 插件信息临时集合
|
||||
*/
|
||||
private List<PluginDescriptor> temporaryPluginDescriptors;
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
|
||||
private PluginManager() {
|
||||
|
||||
@ -134,6 +133,7 @@ public class PluginManager {
|
||||
|
||||
/**
|
||||
* 执行加载的插件
|
||||
*
|
||||
* @deprecated 待删除
|
||||
*/
|
||||
public void executePlugins() {
|
||||
1
src/main/java/org/jcnc/jnotepad/model/aReadme.md
Normal file
1
src/main/java/org/jcnc/jnotepad/model/aReadme.md
Normal file
@ -0,0 +1 @@
|
||||
model 存放模型相关的代码,包括实体类和枚举。
|
||||
@ -1,7 +1,9 @@
|
||||
package org.jcnc.jnotepad.model.entity;
|
||||
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import javafx.scene.Node;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ -13,29 +15,80 @@ import java.util.List;
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class DirFileModel {
|
||||
/**
|
||||
* 路径
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String name;
|
||||
|
||||
private FontIcon iconIsNotSelected;
|
||||
|
||||
private FontIcon iconIsSelected;
|
||||
|
||||
/**
|
||||
* 未选中时的图标
|
||||
*/
|
||||
@JsonIgnore
|
||||
private Node iconIsNotSelected;
|
||||
/**
|
||||
* 选中时的图标
|
||||
*/
|
||||
@JsonIgnore
|
||||
private Node iconIsSelected;
|
||||
/**
|
||||
* 子文件
|
||||
*/
|
||||
private List<DirFileModel> childFile;
|
||||
|
||||
/**
|
||||
* 是否打开
|
||||
*/
|
||||
private boolean isOpen;
|
||||
|
||||
public DirFileModel(String path, String name, List<DirFileModel> childFile, FontIcon iconIsNotSelected, FontIcon iconIsSelected) {
|
||||
public DirFileModel(String path, String name, List<DirFileModel> childFile, Node iconIsNotSelected, Node iconIsSelected) {
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.childFile = childFile;
|
||||
this.iconIsNotSelected = iconIsNotSelected;
|
||||
this.iconIsSelected = iconIsSelected;
|
||||
this.isOpen = false;
|
||||
}
|
||||
|
||||
public DirFileModel(String path, String name, List<DirFileModel> childFile, Node iconIsNotSelected, Node iconIsSelected, boolean isOpen) {
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.childFile = childFile;
|
||||
this.iconIsNotSelected = iconIsNotSelected;
|
||||
this.iconIsSelected = iconIsSelected;
|
||||
this.isOpen = isOpen;
|
||||
}
|
||||
|
||||
public DirFileModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given `DirFileModel` represents a directory.
|
||||
*
|
||||
* @param childFile the `DirFileModel` to check
|
||||
* @return `true` if the `childFile` represents a directory, `false` otherwise
|
||||
*/
|
||||
public static boolean isDirectoryByDirFileModel(DirFileModel childFile) {
|
||||
return new File(childFile.getPath()).isDirectory();
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
public List<DirFileModel> getChildFile() {
|
||||
return childFile;
|
||||
}
|
||||
|
||||
public void setChildFile(List<DirFileModel> childFile) {
|
||||
this.childFile = childFile;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
@ -57,23 +110,24 @@ public class DirFileModel {
|
||||
return name;
|
||||
}
|
||||
|
||||
public FontIcon getIconIsNotSelected() {
|
||||
public Node getIconIsNotSelected() {
|
||||
return iconIsNotSelected;
|
||||
}
|
||||
|
||||
public void setIconIsNotSelected(FontIcon iconIsNotSelected) {
|
||||
public void setIconIsNotSelected(Node iconIsNotSelected) {
|
||||
this.iconIsNotSelected = iconIsNotSelected;
|
||||
}
|
||||
|
||||
public FontIcon getIconIsSelected() {
|
||||
public Node getIconIsSelected() {
|
||||
return iconIsSelected;
|
||||
}
|
||||
|
||||
public void setIconIsSelected(FontIcon iconIsSelected) {
|
||||
public void setIconIsSelected(Node iconIsSelected) {
|
||||
this.iconIsSelected = iconIsSelected;
|
||||
}
|
||||
|
||||
public void setChildFile(List<DirFileModel> childFile) {
|
||||
this.childFile = childFile;
|
||||
public void setOpen(boolean open) {
|
||||
isOpen = open;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
package org.jcnc.jnotepad.model.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.jcnc.jnotepad.plugin.interfaces.Plugin;
|
||||
import org.jcnc.jnotepad.controller.plugin.interfaces.Plugin;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
1
src/main/java/org/jcnc/jnotepad/ui/component/aReadme.md
Normal file
1
src/main/java/org/jcnc/jnotepad/ui/component/aReadme.md
Normal file
@ -0,0 +1 @@
|
||||
component 目录包含可复用的UI组件,如自定义模块。
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.module;
|
||||
package org.jcnc.jnotepad.ui.component.module;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Insets;
|
||||
@ -52,8 +52,6 @@ public class TextCodeArea extends CodeArea {
|
||||
"//[^\n]*" + "|" + "/\\*(.|\\R)*?\\*/"
|
||||
// 用于可见段落处理(逐行)
|
||||
+ "|" + "/\\*\\V*" + "|" + "^\\h*\\*(\\V*|/)";
|
||||
|
||||
|
||||
/**
|
||||
* 使用正则表达式将关键字、括号、分号、字符串和注释的模式组合成一个复合模式
|
||||
*/
|
||||
@ -107,23 +105,7 @@ public class TextCodeArea extends CodeArea {
|
||||
}
|
||||
}
|
||||
});
|
||||
this.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/css/java_code_styles.css")).toString());
|
||||
}
|
||||
|
||||
|
||||
private StyleSpans<Collection<String>> computeHighlighting(String text) {
|
||||
Matcher matcher = PATTERN.matcher(text);
|
||||
int lastKwEnd = 0;
|
||||
StyleSpansBuilder<Collection<String>> spansBuilder
|
||||
= new StyleSpansBuilder<>();
|
||||
while (matcher.find()) {
|
||||
String styleClass = getStyleClass(matcher);
|
||||
spansBuilder.add(Collections.emptyList(), matcher.start() - lastKwEnd);
|
||||
spansBuilder.add(Collections.singleton(styleClass), matcher.end() - matcher.start());
|
||||
lastKwEnd = matcher.end();
|
||||
}
|
||||
spansBuilder.add(Collections.emptyList(), text.length() - lastKwEnd);
|
||||
return spansBuilder.create();
|
||||
this.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/jcnc/app/css/java_code_styles.css")).toString());
|
||||
}
|
||||
|
||||
private static String getStyleClass(Matcher matcher) {
|
||||
@ -143,4 +125,19 @@ public class TextCodeArea extends CodeArea {
|
||||
// 永不发生
|
||||
return null;
|
||||
}
|
||||
|
||||
private StyleSpans<Collection<String>> computeHighlighting(String text) {
|
||||
Matcher matcher = PATTERN.matcher(text);
|
||||
int lastKwEnd = 0;
|
||||
StyleSpansBuilder<Collection<String>> spansBuilder
|
||||
= new StyleSpansBuilder<>();
|
||||
while (matcher.find()) {
|
||||
String styleClass = getStyleClass(matcher);
|
||||
spansBuilder.add(Collections.emptyList(), matcher.start() - lastKwEnd);
|
||||
spansBuilder.add(Collections.singleton(styleClass), matcher.end() - matcher.start());
|
||||
lastKwEnd = matcher.end();
|
||||
}
|
||||
spansBuilder.add(Collections.emptyList(), text.length() - lastKwEnd);
|
||||
return spansBuilder.create();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package org.jcnc.jnotepad.ui.component.module.base;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import org.jcnc.jnotepad.ui.component.module.interfaces.BorderPaneAble;
|
||||
|
||||
/**
|
||||
* 抽象边界面板类。
|
||||
*
|
||||
* <p>这个抽象类继承自 JavaFX 的 BorderPane 类,实现了 BorderPaneAble 接口,用于管理 UI 组件的布局。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public abstract class AbstractBorderPane extends BorderPane implements BorderPaneAble {
|
||||
|
||||
/**
|
||||
* 设置顶部组件。
|
||||
*
|
||||
* @param node 顶部组件
|
||||
*/
|
||||
@Override
|
||||
public void setTopComponent(Node node) {
|
||||
setTop(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置底部组件。
|
||||
*
|
||||
* @param node 底部组件
|
||||
*/
|
||||
@Override
|
||||
public void setBottomComponent(Node node) {
|
||||
setBottom(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置左侧组件。
|
||||
*
|
||||
* @param node 左侧组件
|
||||
*/
|
||||
@Override
|
||||
public void setLeftComponent(Node node) {
|
||||
setLeft(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置右侧组件。
|
||||
*
|
||||
* @param node 右侧组件
|
||||
*/
|
||||
@Override
|
||||
public void setRightComponent(Node node) {
|
||||
setRight(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置中心组件。
|
||||
*
|
||||
* @param node 中心组件
|
||||
*/
|
||||
@Override
|
||||
public void setCenterComponent(Node node) {
|
||||
setCenter(node);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package org.jcnc.jnotepad.ui.component.module.base;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.HBox;
|
||||
import org.jcnc.jnotepad.ui.component.module.interfaces.HorizontalBoxAble;
|
||||
|
||||
/**
|
||||
* 抽象水平盒子类。
|
||||
*
|
||||
* <p>这个抽象类继承自 JavaFX 的 HBox 类,实现了 HorizontalBoxAble 接口,用于管理水平排列的 UI 组件。</p>
|
||||
*
|
||||
* <p>请注意,这个类只是一个抽象类,用于提供基本的水平盒子布局功能。您可以继承此类并添加自己的 UI 组件以构建更复杂的界面。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public abstract class AbstractHorizontalBox extends HBox implements HorizontalBoxAble {
|
||||
private final HBox hBox;
|
||||
|
||||
/**
|
||||
* 创建一个新的 AbstractHorizontalBox 实例。
|
||||
*/
|
||||
public AbstractHorizontalBox() {
|
||||
hBox = new HBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* 向水平盒子添加一个节点。
|
||||
*
|
||||
* @param node 要添加的节点
|
||||
*/
|
||||
@Override
|
||||
public void addChild(Node node) {
|
||||
hBox.getChildren().add(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向水平盒子添加多个节点。
|
||||
*
|
||||
* @param nodes 要添加的节点数组
|
||||
*/
|
||||
@Override
|
||||
public void addChild(Node... nodes) {
|
||||
hBox.getChildren().addAll(nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取水平盒子的实例。
|
||||
*
|
||||
* @return 水平盒子实例
|
||||
*/
|
||||
@Override
|
||||
public HBox getHorizontalBox() {
|
||||
return hBox;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package org.jcnc.jnotepad.ui.component.module.base;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jcnc.jnotepad.ui.component.module.interfaces.VerticalBoxAble;
|
||||
|
||||
/**
|
||||
* 抽象垂直盒子类。
|
||||
*
|
||||
* <p>这个抽象类继承自 JavaFX 的 VBox 类,实现了 VerticalBoxAble 接口,用于管理垂直排列的 UI 组件。</p>
|
||||
*
|
||||
* <p>请注意,这个类只是一个抽象类,用于提供基本的垂直盒子布局功能。您可以继承此类并添加自己的 UI 组件以构建更复杂的界面。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public abstract class AbstractVerticalBox extends VBox implements VerticalBoxAble {
|
||||
private final VBox vBox;
|
||||
|
||||
/**
|
||||
* 创建一个新的 AbstractVerticalBox 实例。
|
||||
*/
|
||||
public AbstractVerticalBox() {
|
||||
vBox = new VBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* 向垂直盒子添加一个节点。
|
||||
*
|
||||
* @param node 要添加的节点
|
||||
*/
|
||||
@Override
|
||||
public void addChild(Node node) {
|
||||
vBox.getChildren().add(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向垂直盒子添加多个节点。
|
||||
*
|
||||
* @param nodes 要添加的节点数组
|
||||
*/
|
||||
@Override
|
||||
public void addChild(Node... nodes) {
|
||||
vBox.getChildren().addAll(nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取垂直盒子的实例。
|
||||
*
|
||||
* @return 垂直盒子实例
|
||||
*/
|
||||
@Override
|
||||
public VBox getVerticalBox() {
|
||||
return vBox;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.module.hbox;
|
||||
package org.jcnc.jnotepad.ui.component.module.hbox;
|
||||
|
||||
import javafx.animation.TranslateTransition;
|
||||
import javafx.geometry.Pos;
|
||||
@ -14,11 +14,18 @@ import javafx.util.Duration;
|
||||
* 自定义标题栏组件,用于自定义窗口标题栏的显示和交互。
|
||||
* 该类提供了窗口图标、标题文本以及最小化、最大化和关闭按钮的功能。
|
||||
*
|
||||
* @author 许轲
|
||||
* <p>这个类允许用户创建自定义的窗口标题栏,包括图标、标题文本和按钮来最小化、最大化和关闭窗口。</p>
|
||||
*
|
||||
* <p>通过使用 {@link #getInstance()} 方法获取单例实例,然后将其添加到窗口的顶部,即可创建自定义标题栏。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public class CustomTitleBarBox extends HBox {
|
||||
private static CustomTitleBarBox instance;
|
||||
|
||||
/**
|
||||
* 创建一个新的 CustomTitleBarBox 实例。
|
||||
*/
|
||||
public CustomTitleBarBox() {
|
||||
// 设置样式和布局
|
||||
this.setAlignment(Pos.CENTER);
|
||||
@ -65,9 +72,9 @@ public class CustomTitleBarBox extends HBox {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标题栏的单例实例
|
||||
* 获取标题栏的单例实例。
|
||||
*
|
||||
* @return CustomTitleBar的单例实例
|
||||
* @return CustomTitleBarBox 的单例实例
|
||||
*/
|
||||
public static CustomTitleBarBox getInstance() {
|
||||
if (instance == null) {
|
||||
@ -77,9 +84,9 @@ public class CustomTitleBarBox extends HBox {
|
||||
}
|
||||
|
||||
/**
|
||||
* 使窗口可拖动
|
||||
* 使窗口可拖动。
|
||||
*
|
||||
* @param stage 要拖动的窗口的Stage对象
|
||||
* @param stage 要拖动的窗口的 Stage 对象
|
||||
*/
|
||||
public void makeDraggable(Stage stage) {
|
||||
// 创建一个平移动画,设置持续时间和目标位置
|
||||
@ -1,12 +1,14 @@
|
||||
package org.jcnc.jnotepad.component.module.interfaces;
|
||||
package org.jcnc.jnotepad.ui.component.module.interfaces;
|
||||
|
||||
import javafx.scene.Node;
|
||||
|
||||
/**
|
||||
* 可设置BorderPane子组件的接口
|
||||
* 可设置BorderPane子组件的接口。
|
||||
*
|
||||
* <p>该接口定义了设置BorderPane的各个子组件(上、下、左、右、中)的方法。</p>
|
||||
*
|
||||
* <p>实现此接口的类可以设置BorderPane布局的各个子组件,以定制UI布局。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public interface BorderPaneAble {
|
||||
@ -1,11 +1,14 @@
|
||||
package org.jcnc.jnotepad.component.module.interfaces;
|
||||
package org.jcnc.jnotepad.ui.component.module.interfaces;
|
||||
|
||||
/**
|
||||
* 控制器接口类
|
||||
* 控制器接口类。
|
||||
*
|
||||
* <p>该接口定义了控制器的方法,用于打开关联文件并创建TextArea。</p>
|
||||
* <p>该接口定义了控制器的方法,用于打开关联文件并创建 TextArea。</p>
|
||||
*
|
||||
* @author 许轲
|
||||
* <p>实现此接口的类可以通过调用方法来打开关联文件并创建 TextArea,以执行与文件操作相关的控制逻辑。</p>
|
||||
*
|
||||
* @param <T> 原始参数的类型
|
||||
* @author luke
|
||||
*/
|
||||
public interface ControllerAble<T> {
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
package org.jcnc.jnotepad.component.module.interfaces;
|
||||
package org.jcnc.jnotepad.ui.component.module.interfaces;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
/**
|
||||
* 可添加子节点的水平布局接口
|
||||
* 可添加子节点的水平布局接口。
|
||||
*
|
||||
* <p>该接口定义了添加子节点和获取水平布局的方法。</p>
|
||||
* <p>该接口定义了向水平布局添加子节点和获取水平布局的方法。</p>
|
||||
*
|
||||
* <p>实现此接口的类可以使用方法将一个或多个子节点添加到水平布局中,以自定义水平布局的UI组件。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
@ -1,12 +1,14 @@
|
||||
package org.jcnc.jnotepad.component.module.interfaces;
|
||||
package org.jcnc.jnotepad.ui.component.module.interfaces;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
/**
|
||||
* 可添加子节点的垂直布局接口
|
||||
* 可添加子节点的垂直布局接口。
|
||||
*
|
||||
* <p>该接口定义了添加子节点和获取垂直布局的方法。</p>
|
||||
* <p>该接口定义了向垂直布局添加子节点和获取垂直布局的方法。</p>
|
||||
*
|
||||
* <p>实现此接口的类可以使用方法将一个或多个子节点添加到垂直布局中,以自定义垂直布局的UI组件。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
@ -0,0 +1,83 @@
|
||||
package org.jcnc.jnotepad.ui.component.module.vbox;
|
||||
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import org.jcnc.jnotepad.ui.component.module.vbox.components.CmdTerminalBox;
|
||||
import org.jcnc.jnotepad.ui.component.module.vbox.components.DebugBox;
|
||||
import org.jcnc.jnotepad.ui.component.module.vbox.components.RunBox;
|
||||
|
||||
/**
|
||||
* 底部运行、调试和命令终端面板。
|
||||
*
|
||||
* <p>这个类实现了一个包含运行信息、调试信息和命令终端的底部面板。它是TabPane的子类,用于将这三个组件以选项卡的形式显示在底部面板上。</p>
|
||||
*
|
||||
* <p>可以通过调用getInstance方法获取单例实例。</p>
|
||||
*
|
||||
* @author cccqyu
|
||||
* @see CmdTerminalBox
|
||||
* @see RunBox
|
||||
* @see DebugBox
|
||||
* @see TabPane
|
||||
*/
|
||||
public class BuildPanel extends TabPane {
|
||||
|
||||
private static BuildPanel instance = null;
|
||||
private final CmdTerminalBox cmdTerminalBox;
|
||||
private final RunBox runBox;
|
||||
private final DebugBox debugBox;
|
||||
private BuildPanel() {
|
||||
cmdTerminalBox = new CmdTerminalBox();
|
||||
runBox = new RunBox();
|
||||
debugBox = new DebugBox();
|
||||
|
||||
Tab runTab = new Tab("运行", runBox);
|
||||
runTab.setClosable(false);
|
||||
|
||||
Tab buildTab = new Tab("调试", debugBox);
|
||||
buildTab.setClosable(false);
|
||||
|
||||
Tab cmdTab = new Tab("命令终端", cmdTerminalBox);
|
||||
cmdTab.setClosable(false);
|
||||
this.getTabs().addAll(runTab, buildTab, cmdTab);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取BuildPanel的单例实例。
|
||||
*
|
||||
* @return BuildPanel的单例实例
|
||||
*/
|
||||
public static BuildPanel getInstance() {
|
||||
|
||||
if (instance == null) {
|
||||
instance = new BuildPanel();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取命令终端组件。
|
||||
*
|
||||
* @return CmdTerminalBox对象
|
||||
*/
|
||||
public CmdTerminalBox getCmdTerminalBox() {
|
||||
return cmdTerminalBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取运行信息组件。
|
||||
*
|
||||
* @return RunBox对象
|
||||
*/
|
||||
public RunBox getRunBox() {
|
||||
return runBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调试信息组件。
|
||||
*
|
||||
* @return DebugBox对象
|
||||
*/
|
||||
public DebugBox getDebugBox() {
|
||||
return debugBox;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.module.vbox.components;
|
||||
package org.jcnc.jnotepad.ui.component.module.vbox.components;
|
||||
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.Timeline;
|
||||
@ -10,7 +10,7 @@ import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Duration;
|
||||
import org.fxmisc.richtext.StyleClassedTextArea;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
@ -18,6 +18,12 @@ import java.nio.charset.Charset;
|
||||
/**
|
||||
* 命令行终端界面。
|
||||
*
|
||||
* <p>这个类实现了一个简单的命令行终端界面,用于显示命令输出并接受用户输入的命令。</p>
|
||||
*
|
||||
* <p>通过调用构造函数来创建CmdTerminal对象。它包括了一个用于显示命令输出的文本区域和一个用于输入命令的文本框。</p>
|
||||
*
|
||||
* <p>这个终端界面支持基本的命令执行,并将命令输出显示在文本区域中。</p>
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
public class CmdTerminalBox extends VBox {
|
||||
@ -30,6 +36,7 @@ public class CmdTerminalBox extends VBox {
|
||||
* 用户输入命令的文本框
|
||||
*/
|
||||
private final TextField cmdInput;
|
||||
String currentDirectory;
|
||||
/**
|
||||
* 用于运行命令的进程
|
||||
*/
|
||||
@ -39,8 +46,6 @@ public class CmdTerminalBox extends VBox {
|
||||
*/
|
||||
private PrintWriter cmdInputWriter;
|
||||
|
||||
String currentDirectory;
|
||||
|
||||
/**
|
||||
* 创建CmdTerminal对象的构造函数。
|
||||
*/
|
||||
@ -64,7 +69,6 @@ public class CmdTerminalBox extends VBox {
|
||||
// 获取当前工作目录的文件夹路径
|
||||
currentDirectory = System.getProperty("user.dir");
|
||||
|
||||
|
||||
// 创建并启动cmd进程,使用GBK字符编码
|
||||
try {
|
||||
cmdProcess = new ProcessBuilder("cmd.exe")
|
||||
@ -74,14 +78,12 @@ public class CmdTerminalBox extends VBox {
|
||||
.start();
|
||||
cmdInputWriter = new PrintWriter(new OutputStreamWriter(cmdProcess.getOutputStream(), Charset.forName("GBK")));
|
||||
} catch (IOException e) {
|
||||
LogUtil.getLogger(this.getClass()).info("已调用, {}", cmdProcess);
|
||||
LoggerUtil.getLogger(this.getClass()).info("已调用, {}", cmdProcess);
|
||||
}
|
||||
|
||||
|
||||
// 延迟执行打印当前文件夹路径的语句
|
||||
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0.5), event -> {
|
||||
appendTextToCmdOutput(currentDirectory + ">" + "\n");
|
||||
|
||||
}));
|
||||
timeline.setCycleCount(1);
|
||||
timeline.play();
|
||||
@ -112,7 +114,7 @@ public class CmdTerminalBox extends VBox {
|
||||
Platform.runLater(() -> appendTextToCmdOutput(outputLine));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtil.getLogger(this.getClass()).info("已调用, {}", this);
|
||||
LoggerUtil.getLogger(this.getClass()).info("已调用, {}", this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package org.jcnc.jnotepad.ui.component.module.vbox.components;
|
||||
|
||||
import org.jcnc.jnotepad.ui.component.module.TextCodeArea;
|
||||
|
||||
/**
|
||||
* 调试信息显示界面。
|
||||
*
|
||||
* <p>这个类实现了一个用于显示调试信息的界面,它是TextCodeArea的子类,并在构造函数中将其设置为不可编辑状态。</p>
|
||||
*
|
||||
* <p>调试信息可以通过调用setText方法将文本添加到界面中。</p>
|
||||
*
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class DebugBox extends TextCodeArea {
|
||||
/**
|
||||
* 创建DebugBox对象的构造函数。
|
||||
*/
|
||||
public DebugBox() {
|
||||
super();
|
||||
this.setEditable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置调试信息的文本内容。
|
||||
*
|
||||
* @param text 要显示的调试信息文本
|
||||
*/
|
||||
public void setText(String text) {
|
||||
this.appendText(text);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package org.jcnc.jnotepad.ui.component.module.vbox.components;
|
||||
|
||||
import org.jcnc.jnotepad.ui.component.module.TextCodeArea;
|
||||
|
||||
/**
|
||||
* 运行信息显示界面。
|
||||
*
|
||||
* <p>这个类实现了一个用于显示运行信息的界面,它是TextCodeArea的子类,并在构造函数中将其设置为不可编辑状态。</p>
|
||||
*
|
||||
* <p>运行信息可以通过调用setText方法将文本添加到界面中。</p>
|
||||
*
|
||||
* @author cccqyu
|
||||
*/
|
||||
public class RunBox extends TextCodeArea {
|
||||
/**
|
||||
* 创建RunBox对象的构造函数。
|
||||
*/
|
||||
public RunBox() {
|
||||
super();
|
||||
this.setEditable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置运行信息的文本内容。
|
||||
*
|
||||
* @param text 要显示的运行信息文本
|
||||
*/
|
||||
public void setText(String text) {
|
||||
this.appendText(text);
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,13 @@
|
||||
package org.jcnc.jnotepad.component.stage.dialog;
|
||||
package org.jcnc.jnotepad.ui.component.stage.dialog;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.interfaces.DialogButtonAction;
|
||||
import org.jcnc.jnotepad.app.utils.UiUtil;
|
||||
import org.jcnc.jnotepad.model.enums.DialogType;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.interfaces.DialogButtonAction;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
/**
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.stage.dialog;
|
||||
package org.jcnc.jnotepad.ui.component.stage.dialog;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
@ -7,7 +7,7 @@ import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.interfaces.DialogButtonAction;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.interfaces.DialogButtonAction;
|
||||
|
||||
/**
|
||||
* 应用对话框
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.stage.dialog.factory;
|
||||
package org.jcnc.jnotepad.ui.component.stage.dialog.factory;
|
||||
|
||||
import javafx.stage.DirectoryChooser;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.stage.dialog.factory;
|
||||
package org.jcnc.jnotepad.ui.component.stage.dialog.factory;
|
||||
|
||||
import javafx.stage.FileChooser;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package org.jcnc.jnotepad.component.stage.dialog.factory.impl;
|
||||
package org.jcnc.jnotepad.ui.component.stage.dialog.factory.impl;
|
||||
|
||||
import javafx.stage.DirectoryChooser;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.factory.DirectoryChooserFactory;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.factory.DirectoryChooserFactory;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@ -44,7 +44,7 @@ public class BasicDirectoryChooserFactory implements DirectoryChooserFactory {
|
||||
@Override
|
||||
public DirectoryChooser createDirectoryChooser(String title, File directory) {
|
||||
|
||||
DirectoryChooser directoryChooser= createDirectoryChooser();
|
||||
DirectoryChooser directoryChooser = createDirectoryChooser();
|
||||
// 设置窗口名称
|
||||
directoryChooser.setTitle(title);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package org.jcnc.jnotepad.component.stage.dialog.factory.impl;
|
||||
package org.jcnc.jnotepad.ui.component.stage.dialog.factory.impl;
|
||||
|
||||
import javafx.stage.FileChooser;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.factory.FileChooserFactory;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.factory.FileChooserFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
@ -1,6 +1,6 @@
|
||||
package org.jcnc.jnotepad.component.stage.dialog.interfaces;
|
||||
package org.jcnc.jnotepad.ui.component.stage.dialog.interfaces;
|
||||
|
||||
import org.jcnc.jnotepad.component.stage.dialog.AppDialogStage;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.AppDialogStage;
|
||||
|
||||
/**
|
||||
* 对话框按钮点击事件接口
|
||||
@ -10,6 +10,7 @@ import org.jcnc.jnotepad.component.stage.dialog.AppDialogStage;
|
||||
public interface DialogButtonAction {
|
||||
/**
|
||||
* 处理按钮的操作。子类必须实现此方法以定义按钮的行为
|
||||
*
|
||||
* @param appDialogStage 对话框
|
||||
* @apiNote
|
||||
* @since 2023/9/3 22:53
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.stage.setting;
|
||||
package org.jcnc.jnotepad.ui.component.stage.setting;
|
||||
|
||||
import javafx.scene.control.Button;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.stage.setting;
|
||||
package org.jcnc.jnotepad.ui.component.stage.setting;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.stage.setting;
|
||||
package org.jcnc.jnotepad.ui.component.stage.setting;
|
||||
|
||||
import atlantafx.base.controls.CustomTextField;
|
||||
import atlantafx.base.theme.Styles;
|
||||
@ -16,24 +16,24 @@ import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.app.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.app.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.app.config.AppConfig;
|
||||
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
|
||||
import org.jcnc.jnotepad.app.manager.ApplicationManager;
|
||||
import org.jcnc.jnotepad.common.constants.TextConstants;
|
||||
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
|
||||
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicDirectoryChooserFactory;
|
||||
import org.jcnc.jnotepad.app.utils.PopUpUtil;
|
||||
import org.jcnc.jnotepad.app.utils.UiUtil;
|
||||
import org.jcnc.jnotepad.controller.config.AppConfigController;
|
||||
import org.jcnc.jnotepad.controller.event.handler.toolbar.OpenDirectory;
|
||||
import org.jcnc.jnotepad.controller.plugin.PluginManagerInterface;
|
||||
import org.jcnc.jnotepad.model.entity.Cache;
|
||||
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
|
||||
import org.jcnc.jnotepad.plugin.PluginManagerInterface;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.ui.component.stage.dialog.factory.impl.BasicDirectoryChooserFactory;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.SCREEN_LENGTH;
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.SCREEN_WIDTH;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.SCREEN_LENGTH;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.SCREEN_WIDTH;
|
||||
|
||||
/**
|
||||
* SetStage类表示设置窗口的单例对象。此窗口用于显示不同的设置选项和其对应的布局。
|
||||
@ -52,9 +52,8 @@ public class SetStage {
|
||||
public static final String SECURITY_SETTING_2 = "安全设置项2";
|
||||
|
||||
private static SetStage instance;
|
||||
private StackPane contentDisplay;
|
||||
|
||||
private final ApplicationCacheManager cacheManager = ApplicationCacheManager.getInstance();
|
||||
private StackPane contentDisplay;
|
||||
|
||||
/**
|
||||
* 私有构造方法以实现单例模式。
|
||||
@ -160,7 +159,6 @@ public class SetStage {
|
||||
securityItem.getChildren().add(securityItem2);
|
||||
|
||||
|
||||
|
||||
root.getChildren().add(generalItem);
|
||||
root.getChildren().add(appearanceItem);
|
||||
root.getChildren().add(securityItem);
|
||||
@ -203,7 +201,6 @@ public class SetStage {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 创建常规设置项1的布局。
|
||||
*
|
||||
@ -225,12 +222,11 @@ public class SetStage {
|
||||
var fileChooseBtn = new Button();
|
||||
fileChooseBtn.setText("选择文件夹");
|
||||
fileChooseBtn.getStyleClass().addAll(Styles.SMALL);
|
||||
BasicDirectoryChooserFactory directoryChooserFactory = BasicDirectoryChooserFactory.getInstance();
|
||||
fileChooseBtn.setOnAction(event -> {
|
||||
// 获取打开目录缓存
|
||||
Cache cache = cacheManager.getCache(OpenDirectory.GROUP, "openDirectory");
|
||||
|
||||
File file = directoryChooserFactory.createDirectoryChooser(
|
||||
File file = BasicDirectoryChooserFactory.getInstance().createDirectoryChooser(
|
||||
UiResourceBundle.getContent(TextConstants.OPEN),
|
||||
cache == null ? null : new File((String) cache.getCacheData()))
|
||||
.showDialog(UiUtil.getAppWindow());
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.stage.topmenu.builder;
|
||||
package org.jcnc.jnotepad.ui.component.stage.topmenu.builder;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jcnc.jnotepad.component.stage.topmenu.help;
|
||||
package org.jcnc.jnotepad.ui.component.stage.topmenu.help;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.Scene;
|
||||
@ -10,10 +10,10 @@ import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.api.core.component.stage.AbstractPaneStage;
|
||||
import org.jcnc.jnotepad.app.manager.ApplicationManager;
|
||||
import org.jcnc.jnotepad.component.stage.topmenu.builder.StageButtonBuilder;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.PopUpUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.app.utils.PopUpUtil;
|
||||
import org.jcnc.jnotepad.app.utils.UiUtil;
|
||||
import org.jcnc.jnotepad.ui.component.stage.topmenu.builder.StageButtonBuilder;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
@ -23,7 +23,7 @@ import org.slf4j.Logger;
|
||||
*/
|
||||
public class DeveloperDebugPaneStage extends AbstractPaneStage {
|
||||
private static final String DEBUG_STR = "开发者调试: {}启动!";
|
||||
Logger logger = LogUtil.getLogger(this.getClass());
|
||||
Logger logger = LoggerUtil.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 获取舞台图标
|
||||
@ -1,6 +1,5 @@
|
||||
package org.jcnc.jnotepad.component.stage.topmenu.help;
|
||||
package org.jcnc.jnotepad.ui.component.stage.topmenu.help;
|
||||
|
||||
import atlantafx.base.controls.Notification;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@ -12,18 +11,17 @@ import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.jcnc.jnotepad.api.core.component.stage.AbstractPaneStage;
|
||||
import org.jcnc.jnotepad.util.LogUtil;
|
||||
import org.jcnc.jnotepad.util.UiUtil;
|
||||
import org.jcnc.jnotepad.views.manager.RootManager;
|
||||
import org.jcnc.jnotepad.app.utils.ClipboardUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.app.utils.NotificationUtil;
|
||||
import org.jcnc.jnotepad.app.utils.UiUtil;
|
||||
|
||||
import static org.jcnc.jnotepad.common.constants.AppConstants.*;
|
||||
import static org.jcnc.jnotepad.app.common.constants.AppConstants.*;
|
||||
|
||||
/**
|
||||
* 帮助页面
|
||||
@ -129,22 +127,11 @@ public class HelpPaneStage extends AbstractPaneStage {
|
||||
bottomBox.setAlignment(Pos.BOTTOM_RIGHT);
|
||||
|
||||
Button leftBtn = getButton(" 复制并关闭 ", event -> {
|
||||
// 获取 RootManager 的实例
|
||||
RootManager rootManager = RootManager.getInstance();
|
||||
|
||||
// 创建一个新的 Notification
|
||||
Notification notification = new Notification();
|
||||
notification.setMessage("已成功复制软件信息!");
|
||||
|
||||
// 调用 RootManager 中的方法来显示 Notification
|
||||
rootManager.addNotificationToStackPane(rootManager.getRootStackPane(), notification);
|
||||
|
||||
Clipboard clipboard = Clipboard.getSystemClipboard();
|
||||
ClipboardContent content = new ClipboardContent();
|
||||
NotificationUtil.infoNotification("软件信息已经复制到剪贴板!");
|
||||
String info = "软件名字:" + APP_NAME + "\t" + "版本:" + VERSION;
|
||||
content.putString(info);
|
||||
LogUtil.getLogger(this.getClass()).info("软件信息已经复制到剪贴板:{}", info);
|
||||
clipboard.setContent(content);
|
||||
ClipboardUtil.writeTextToClipboard(info);
|
||||
LoggerUtil.getLogger(this.getClass()).info("软件信息已经复制到剪贴板:{}", info);
|
||||
|
||||
// 关闭当前的 Stage
|
||||
Stage currentStage = (Stage) ((Button) event.getSource()).getScene().getWindow();
|
||||
currentStage.close();
|
||||
@ -204,10 +191,10 @@ public class HelpPaneStage extends AbstractPaneStage {
|
||||
*/
|
||||
private void openWebsite(String url) {
|
||||
try {
|
||||
LogUtil.getLogger(this.getClass()).info("正在打开---{}", url);
|
||||
LoggerUtil.getLogger(this.getClass()).info("正在打开---{}", url);
|
||||
java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
|
||||
} catch (java.io.IOException e) {
|
||||
LogUtil.getLogger(this.getClass()).info("打开失败---{}", url);
|
||||
LoggerUtil.getLogger(this.getClass()).info("打开失败---{}", url);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user