!140 添加 选择文件根路径的功能

Merge pull request !140 from 格物方能致知/develop
This commit is contained in:
格物方能致知 2023-10-05 05:26:56 +00:00 committed by Gitee
commit 79dc83b2c1
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
38 changed files with 421 additions and 312 deletions

View File

@ -21,7 +21,7 @@ module org.jcnc.jnotepad {
requires javafx.web; requires javafx.web;
exports org.jcnc.jnotepad; exports org.jcnc.jnotepad;
exports org.jcnc.jnotepad.cache.enums; exports org.jcnc.jnotepad.model.enums;
exports org.jcnc.jnotepad.app.config; exports org.jcnc.jnotepad.app.config;
exports org.jcnc.jnotepad.app.i18n; exports org.jcnc.jnotepad.app.i18n;
exports org.jcnc.jnotepad.common.constants; exports org.jcnc.jnotepad.common.constants;
@ -36,7 +36,7 @@ module org.jcnc.jnotepad {
exports org.jcnc.jnotepad.views.root.bottom.function; exports org.jcnc.jnotepad.views.root.bottom.function;
exports org.jcnc.jnotepad.component.module; exports org.jcnc.jnotepad.component.module;
exports org.jcnc.jnotepad.cache.entity; exports org.jcnc.jnotepad.model.entity;
exports org.jcnc.jnotepad.views.root.bottom; exports org.jcnc.jnotepad.views.root.bottom;
exports org.jcnc.jnotepad.views.root.bottom.status; exports org.jcnc.jnotepad.views.root.bottom.status;
exports org.jcnc.jnotepad.api.core.views.sidebar.bottom; exports org.jcnc.jnotepad.api.core.views.sidebar.bottom;

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.api.core.ui.stage; package org.jcnc.jnotepad.api.core.component.stage;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.image.Image; import javafx.scene.image.Image;

View File

@ -1,6 +1,6 @@
package org.jcnc.jnotepad.api.core.manager; package org.jcnc.jnotepad.api.core.manager;
import org.jcnc.jnotepad.cache.entity.Cache; import org.jcnc.jnotepad.model.entity.Cache;
import java.util.Map; import java.util.Map;

View File

@ -18,8 +18,8 @@ public class SideBarButtonBuilder {
private EventHandler<ActionEvent> eventHandler; private EventHandler<ActionEvent> eventHandler;
public Button build() { public Button build() {
Optional<Button> container = Optional.of(new Button()); Optional<Button> container = Optional.ofNullable(button);
button = container.get(); button = container.orElseGet(Button::new);
button.setGraphic(imageView); button.setGraphic(imageView);
button.setOnAction(eventHandler); button.setOnAction(eventHandler);
return button; return button;
@ -31,9 +31,9 @@ public class SideBarButtonBuilder {
} }
public SideBarButtonBuilder setButtonEssentialAttribute(Double relativelyPrefWidth, Double relativelyPrefHeight) { public SideBarButtonBuilder setButtonEssentialAttribute(Double relativelyPrefWidth, Double relativelyPrefHeight) {
Optional<Double> container = Optional.of(relativelyPrefHeight); Optional<Double> container = Optional.ofNullable(relativelyPrefHeight);
button.setPrefWidth(imageView.getFitWidth() + container.orElse(20D)); button.setPrefWidth(imageView.getFitWidth() + container.orElse(20D));
container = Optional.of(relativelyPrefWidth); container = Optional.ofNullable(relativelyPrefWidth);
button.setPrefHeight(imageView.getFitHeight() + container.orElse(20D)); button.setPrefHeight(imageView.getFitHeight() + container.orElse(20D));
return this; return this;
} }
@ -49,14 +49,14 @@ public class SideBarButtonBuilder {
* @return 建造者对象 * @return 建造者对象
*/ */
public SideBarButtonBuilder setImageViewEssentialAttribute(Double fitWidth, Double fitHeight, boolean preserveRatio, Double scaleX, Double scaleY) { public SideBarButtonBuilder setImageViewEssentialAttribute(Double fitWidth, Double fitHeight, boolean preserveRatio, Double scaleX, Double scaleY) {
Optional<Double> container = Optional.of(fitWidth); Optional<Double> container = Optional.ofNullable(fitWidth);
imageView.setFitWidth(container.orElse(10D)); imageView.setFitWidth(container.orElse(10D));
container = Optional.of(fitHeight); container = Optional.ofNullable(fitHeight);
imageView.setFitHeight(container.orElse(10D)); imageView.setFitHeight(container.orElse(10D));
imageView.setPreserveRatio(preserveRatio); imageView.setPreserveRatio(preserveRatio);
container = Optional.of(scaleX); container = Optional.ofNullable(scaleX);
imageView.setScaleX(container.orElse(2.5)); imageView.setScaleX(container.orElse(2.5));
container = Optional.of(scaleY); container = Optional.ofNullable(scaleY);
imageView.setScaleY(container.orElse(2.5)); imageView.setScaleY(container.orElse(2.5));
return this; return this;
} }

View File

@ -1,6 +1,6 @@
package org.jcnc.jnotepad.app.config; package org.jcnc.jnotepad.app.config;
import org.jcnc.jnotepad.cache.entity.PluginDescriptor; import org.jcnc.jnotepad.model.entity.PluginDescriptor;
import java.util.List; import java.util.List;

View File

@ -1,7 +1,7 @@
package org.jcnc.jnotepad.app.config; package org.jcnc.jnotepad.app.config;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import org.jcnc.jnotepad.cache.entity.ShortcutKey; import org.jcnc.jnotepad.model.entity.ShortcutKey;
import java.util.List; import java.util.List;

View File

@ -15,7 +15,6 @@ import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
import org.jcnc.jnotepad.controller.ResourceController; import org.jcnc.jnotepad.controller.ResourceController;
import org.jcnc.jnotepad.controller.cache.CacheController; import org.jcnc.jnotepad.controller.cache.CacheController;
import org.jcnc.jnotepad.controller.config.PluginConfigController; import org.jcnc.jnotepad.controller.config.PluginConfigController;
import org.jcnc.jnotepad.controller.config.UserConfigController;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.plugin.manager.PluginManager; import org.jcnc.jnotepad.plugin.manager.PluginManager;
import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.LogUtil;
@ -140,8 +139,7 @@ public class ApplicationManager {
// 刷新插件配置文件 // 刷新插件配置文件
pluginConfigController.getConfig().setPlugins(PluginManager.getInstance().getPluginDescriptors()); pluginConfigController.getConfig().setPlugins(PluginManager.getInstance().getPluginDescriptors());
pluginConfigController.writeConfig(); pluginConfigController.writeConfig();
// 保存配置文件
UserConfigController.getInstance().writeConfig();
// 销毁插件可能申请的资源 // 销毁插件可能申请的资源
PluginManager.getInstance().destroyPlugins(); PluginManager.getInstance().destroyPlugins();
// 保存已打开的文件标签页 // 保存已打开的文件标签页

View File

@ -1,226 +0,0 @@
package org.jcnc.jnotepad.component.module;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import org.fxmisc.richtext.GenericStyledArea;
import org.fxmisc.richtext.LineNumberFactory;
import org.fxmisc.richtext.model.Paragraph;
import org.fxmisc.richtext.model.StyleSpans;
import org.fxmisc.richtext.model.StyleSpansBuilder;
import org.reactfx.Subscription;
import org.reactfx.collection.ListModification;
import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 行号文本区域
*
* <p>这个类继承自JavaFX的BorderPane类用于显示带有行号的文本区域它包括主要文本区域和行号文本区域</p>
*
* @author luke
*/
public class CodeArea extends org.fxmisc.richtext.CodeArea {
private static final String[] KEYWORDS = new String[]{
"abstract", "assert", "boolean", "break", "byte",
"case", "catch", "char", "class", "const",
"continue", "default", "do", "double", "else",
"enum", "extends", "final", "finally", "float",
"for", "goto", "if", "implements", "import",
"instanceof", "int", "interface", "long", "native",
"new", "package", "private", "protected", "public",
"return", "short", "static", "strictfp", "super",
"switch", "synchronized", "this", "throw", "throws",
"transient", "try", "void", "volatile", "while"
};
/**
* 定义用于匹配关键字括号分号字符串和注释的正则表达式模式
*/
private static final String KEYWORD_PATTERN = "\\b(" + String.join("|", KEYWORDS) + ")\\b";
private static final String PAREN_PATTERN = "\\(|\\)";
private static final String BRACE_PATTERN = "\\{|\\}";
private static final String BRACKET_PATTERN = "\\[|\\]";
private static final String SEMICOLON_PATTERN = "\\;";
private static final String STRING_PATTERN = "\"([^\"\\\\]|\\\\.)*\"";
private static final String COMMENT_PATTERN =
// 用于整体文本处理文本块
"//[^\n]*" + "|" + "/\\*(.|\\R)*?\\*/"
// 用于可见段落处理逐行
+ "|" + "/\\*[^\\v]*" + "|" + "^\\h*\\*([^\\v]*|/)";
/**
* 使用正则表达式将关键字括号分号字符串和注释的模式组合成一个复合模式
*/
private static final Pattern PATTERN = Pattern.compile(
"(?<KEYWORD>" + KEYWORD_PATTERN + ")"
+ "|(?<PAREN>" + PAREN_PATTERN + ")"
+ "|(?<BRACE>" + BRACE_PATTERN + ")"
+ "|(?<BRACKET>" + BRACKET_PATTERN + ")"
+ "|(?<SEMICOLON>" + SEMICOLON_PATTERN + ")"
+ "|(?<STRING>" + STRING_PATTERN + ")"
+ "|(?<COMMENT>" + COMMENT_PATTERN + ")"
);
/**
* 构造函数
* <p>
* 用于创建 LineNumberTextArea 对象
*/
public CodeArea() {
//
this.setPadding(new Insets(8, 0, 0, 0));
// 在区域左侧添加行号
this.setParagraphGraphicFactory(LineNumberFactory.get(this));
this.setContextMenu(new DefaultContextMenu());
/*
重新计算所有文本的语法高亮用户停止编辑区域后的500毫秒内
*/
Subscription cleanupWhenNoLongerNeedIt = this
.multiPlainChanges()
.successionEnds(Duration.ofMillis(500))
.subscribe(ignore -> this.setStyleSpans(0, computeHighlighting(this.getText())));
this.getVisibleParagraphs().addModificationObserver
(
new CodeArea.VisibleParagraphStyler<>(this, this::computeHighlighting)
);
// 自动缩进在按下回车键时插入上一行的缩进
final Pattern whiteSpace = Pattern.compile("^\\s+");
this.addEventHandler(KeyEvent.KEY_PRESSED, kE ->
{
if (kE.getCode() == KeyCode.ENTER) {
int caretPosition = this.getCaretPosition();
int currentParagraph = this.getCurrentParagraph();
Matcher m0 = whiteSpace.matcher(this.getParagraph(currentParagraph - 1).getSegments().get(0));
if (m0.find()) {
Platform.runLater(() -> this.insertText(caretPosition, m0.group()));
}
}
});
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();
}
private static String getStyleClass(Matcher matcher) {
String styleClass =
matcher.group("KEYWORD") != null ? "keyword" :
matcher.group("PAREN") != null ? "paren" :
matcher.group("BRACE") != null ? "brace" :
matcher.group("BRACKET") != null ? "bracket" :
matcher.group("SEMICOLON") != null ? "semicolon" :
matcher.group("STRING") != null ? "string" :
matcher.group("COMMENT") != null ? "comment" :
null; /* 永远不会发生 */
assert styleClass != null;
return styleClass;
}
static class VisibleParagraphStyler<PS, SEG, S> implements Consumer<ListModification<? extends Paragraph<PS, SEG, S>>> {
private final GenericStyledArea<PS, SEG, S> area;
private final Function<String, StyleSpans<S>> computeStyles;
private int prevParagraph, prevTextLength;
public VisibleParagraphStyler(GenericStyledArea<PS, SEG, S> area, Function<String, StyleSpans<S>> computeStyles) {
this.computeStyles = computeStyles;
this.area = area;
}
@Override
public void accept(ListModification<? extends Paragraph<PS, SEG, S>> lm) {
if (lm.getAddedSize() > 0) {
Platform.runLater(() -> {
int paragraph = Math.min(area.firstVisibleParToAllParIndex() + lm.getFrom(), area.getParagraphs().size() - 1);
String text = area.getText(paragraph, 0, paragraph, area.getParagraphLength(paragraph));
if (paragraph != prevParagraph || text.length() != prevTextLength) {
if (paragraph < area.getParagraphs().size() - 1) {
int startPos = area.getAbsolutePosition(paragraph, 0);
area.setStyleSpans(startPos, computeStyles.apply(text));
}
prevTextLength = text.length();
prevParagraph = paragraph;
}
});
}
}
}
private static class DefaultContextMenu extends ContextMenu {
private final MenuItem fold;
private final MenuItem unfold;
private final MenuItem print;
public DefaultContextMenu() {
fold = new MenuItem("折叠所选文本");
fold.setOnAction(aE -> {
hide();
fold();
});
unfold = new MenuItem("从光标处展开");
unfold.setOnAction(aE -> {
hide();
unfold();
});
print = new MenuItem("打印");
print.setOnAction(aE -> {
hide();
print();
});
getItems().addAll(fold, unfold, print);
}
/**
* 折叠多行所选文本仅显示第一行并隐藏其余部分
*/
private void fold() {
((org.fxmisc.richtext.CodeArea) getOwnerNode()).foldSelectedParagraphs();
}
/**
* 展开当前行/段落如果有折叠
*/
private void unfold() {
org.fxmisc.richtext.CodeArea area = (org.fxmisc.richtext.CodeArea) getOwnerNode();
area.unfoldParagraphs(area.getCurrentParagraph());
}
private void print() {
System.out.println(((org.fxmisc.richtext.CodeArea) getOwnerNode()).getText());
}
}
}

View File

@ -0,0 +1,146 @@
package org.jcnc.jnotepad.component.module;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import org.fxmisc.richtext.CodeArea;
import org.fxmisc.richtext.LineNumberFactory;
import org.fxmisc.richtext.model.StyleSpans;
import org.fxmisc.richtext.model.StyleSpansBuilder;
import org.jcnc.jnotepad.model.entity.DefaultContextMenu;
import org.jcnc.jnotepad.model.entity.VisibleParagraphStyler;
import org.reactfx.Subscription;
import java.time.Duration;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 文本代码域
* </p>
*
* @author luke
*/
public class TextCodeArea extends CodeArea {
private static final String[] KEYWORDS = new String[]{
"abstract", "assert", "boolean", "break", "byte",
"case", "catch", "char", "class", "const",
"continue", "default", "do", "double", "else",
"enum", "extends", "final", "finally", "float",
"for", "goto", "if", "implements", "import",
"instanceof", "int", "interface", "long", "native",
"new", "package", "private", "protected", "public",
"return", "short", "static", "strictfp", "super",
"switch", "synchronized", "this", "throw", "throws",
"transient", "try", "void", "volatile", "while"
};
/**
* 定义用于匹配关键字括号分号字符串和注释的正则表达式模式
*/
private static final String KEYWORD_PATTERN = "\\b(" + String.join("|", KEYWORDS) + ")\\b";
private static final String PAREN_PATTERN = "[()]";
private static final String BRACE_PATTERN = "[{}]";
private static final String BRACKET_PATTERN = "[\\[\\]]";
private static final String SEMICOLON_PATTERN = ";";
private static final String STRING_PATTERN = "\"([^\"\\\\]|\\\\.)*\"";
private static final String COMMENT_PATTERN =
// 用于整体文本处理文本块
"//[^\n]*" + "|" + "/\\*(.|\\R)*?\\*/"
// 用于可见段落处理逐行
+ "|" + "/\\*\\V*" + "|" + "^\\h*\\*(\\V*|/)";
/**
* 使用正则表达式将关键字括号分号字符串和注释的模式组合成一个复合模式
*/
private static final Pattern PATTERN = Pattern.compile(
"(?<KEYWORD>" + KEYWORD_PATTERN + ")"
+ "|(?<PAREN>" + PAREN_PATTERN + ")"
+ "|(?<BRACE>" + BRACE_PATTERN + ")"
+ "|(?<BRACKET>" + BRACKET_PATTERN + ")"
+ "|(?<SEMICOLON>" + SEMICOLON_PATTERN + ")"
+ "|(?<STRING>" + STRING_PATTERN + ")"
+ "|(?<COMMENT>" + COMMENT_PATTERN + ")"
);
/**
* 构造函数
* <p>
* 用于创建 TextCodeArea 对象
*/
public TextCodeArea() {
//
this.setPadding(new Insets(8, 0, 0, 0));
// 在区域左侧添加行号
this.setParagraphGraphicFactory(LineNumberFactory.get(this));
this.setContextMenu(new DefaultContextMenu());
/*
重新计算所有文本的语法高亮用户停止编辑区域后的500毫秒内
fixme 这个代码没有作用
*/
Subscription cleanupWhenNoLongerNeedIt = this
.multiPlainChanges()
.successionEnds(Duration.ofMillis(500))
.subscribe(ignore -> this.setStyleSpans(0, computeHighlighting(this.getText())));
this.getVisibleParagraphs().addModificationObserver
(
new VisibleParagraphStyler<>(this, this::computeHighlighting)
);
// 自动缩进在按下回车键时插入上一行的缩进
final Pattern whiteSpace = Pattern.compile("^\\s+");
this.addEventHandler(KeyEvent.KEY_PRESSED, kE ->
{
if (kE.getCode() == KeyCode.ENTER) {
int caretPosition = this.getCaretPosition();
int currentParagraph = this.getCurrentParagraph();
Matcher m0 = whiteSpace.matcher(this.getParagraph(currentParagraph - 1).getSegments().get(0));
if (m0.find()) {
Platform.runLater(() -> this.insertText(caretPosition, m0.group()));
}
}
});
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();
}
private static String getStyleClass(Matcher matcher) {
Map<String, String> patternToStyleClass = new HashMap<>(16);
patternToStyleClass.put("keyword", matcher.group("KEYWORD"));
patternToStyleClass.put("paren", matcher.group("PAREN"));
patternToStyleClass.put("brace", matcher.group("BRACE"));
patternToStyleClass.put("bracket", matcher.group("BRACKET"));
patternToStyleClass.put("semicolon", matcher.group("SEMICOLON"));
patternToStyleClass.put("string", matcher.group("STRING"));
patternToStyleClass.put("comment", matcher.group("COMMENT"));
for (Map.Entry<String, String> entry : patternToStyleClass.entrySet()) {
if (entry.getValue() != null) {
return entry.getKey();
}
}
// 永不发生
return null;
}
}

View File

@ -5,8 +5,8 @@ import javafx.geometry.Pos;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.stage.Modality; import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.jcnc.jnotepad.cache.enums.DialogType;
import org.jcnc.jnotepad.component.stage.dialog.interfaces.DialogButtonAction; import org.jcnc.jnotepad.component.stage.dialog.interfaces.DialogButtonAction;
import org.jcnc.jnotepad.model.enums.DialogType;
import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.util.UiUtil;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;

View File

@ -17,7 +17,7 @@ import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.jcnc.jnotepad.api.core.ui.stage.AbstractPaneStage; import org.jcnc.jnotepad.api.core.component.stage.AbstractPaneStage;
import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.RootManager; import org.jcnc.jnotepad.views.manager.RootManager;

View File

@ -16,9 +16,22 @@ import javafx.scene.text.Font;
import javafx.scene.text.Text; import javafx.scene.text.Text;
import javafx.stage.Modality; import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
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.controller.config.AppConfigController;
import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenDirectory;
import org.jcnc.jnotepad.model.entity.Cache;
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
import org.jcnc.jnotepad.plugin.PluginManagerInterface; import org.jcnc.jnotepad.plugin.PluginManagerInterface;
import org.jcnc.jnotepad.util.PopUpUtil;
import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.util.UiUtil;
import java.io.File;
import static org.jcnc.jnotepad.common.constants.AppConstants.SCREEN_LENGTH; 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.common.constants.AppConstants.SCREEN_WIDTH;
@ -42,6 +55,8 @@ public class SetStage extends Stage {
private static SetStage instance; private static SetStage instance;
private StackPane contentDisplay; private StackPane contentDisplay;
private final ApplicationCacheManager cacheManager = ApplicationCacheManager.getInstance();
/** /**
* 私有构造方法以实现单例模式 * 私有构造方法以实现单例模式
*/ */
@ -202,8 +217,6 @@ public class SetStage extends Stage {
DeveloperDebugStage debugPage = new DeveloperDebugStage(); DeveloperDebugStage debugPage = new DeveloperDebugStage();
debugPage.start(new Stage()); debugPage.start(new Stage());
}); });
generalLayout.getChildren().addAll(devBox); generalLayout.getChildren().addAll(devBox);
return generalLayout; return generalLayout;
@ -218,23 +231,50 @@ public class SetStage extends Stage {
VBox generalLayout = new VBox(10); VBox generalLayout = new VBox(10);
generalLayout.setPadding(new Insets(25)); generalLayout.setPadding(new Insets(25));
var hBox=new HBox(5); var hBox = new HBox(5);
var fileChooseText =new Text("路径选择: "); var fileChooseText = new Text("文件根路径: ");
fileChooseText.setFont(new Font(18)); fileChooseText.setFont(new Font(18));
AppConfig config = AppConfigController.getInstance().getConfig();
var fileChoose =new CustomTextField(""); var fileChoose = new CustomTextField(config.getRootPath());
fileChoose.getStyleClass().add(Styles.SMALL); fileChoose.getStyleClass().add(Styles.SMALL);
fileChoose.setPrefWidth(420); fileChoose.setPrefWidth(420);
var fileChooseBtn =new Button(); var fileChooseBtn = new Button();
fileChooseBtn.setText("选择文件夹"); fileChooseBtn.setText("选择文件夹");
fileChooseBtn.getStyleClass().addAll(Styles.SMALL); fileChooseBtn.getStyleClass().addAll(Styles.SMALL);
BasicDirectoryChooserFactory directoryChooserFactory = BasicDirectoryChooserFactory.getInstance();
fileChooseBtn.setOnAction(event -> { fileChooseBtn.setOnAction(event -> {
// TODO: 2023/10/4 选择文件 // 获取打开目录缓存
Cache cache = cacheManager.getCache(OpenDirectory.GROUP, "openDirectory");
File file = directoryChooserFactory.createDirectoryChooser(
UiResourceBundle.getContent(TextConstants.OPEN),
cache == null ? null : new File((String) cache.getCacheData()))
.showDialog(UiUtil.getAppWindow());
if (file == null) {
return;
}
if (file.equals(new File(config.getRootPath()))) {
PopUpUtil.errorAlert("错误", "路径不能和默认路径相同", "请重新选择路径", null, null);
return;
}
// 设置缓存
if (cache == null) {
cacheManager.addCache(cacheManager.createCache(OpenDirectory.GROUP, "openDirectory", file.getAbsolutePath(), CacheExpirationTime.NEVER_EXPIRES.getValue()));
} else {
cache.setCacheData(file.getParent());
cacheManager.addCache(cache);
}
config.setRootPath(file.getAbsolutePath());
PopUpUtil.questionAlert("更改", "设置程序文件根路径", "设置成功,请重启程序以应用路径更改!", appDialog -> {
appDialog.close();
ApplicationManager.getInstance().restart();
}, null, "重启", "以后再说");
Stage stage = (Stage) fileChooseBtn.getScene().getWindow();
stage.close();
}); });
hBox.getChildren().addAll(fileChooseText,fileChoose,fileChooseBtn); hBox.getChildren().addAll(fileChooseText, fileChoose, fileChooseBtn);
generalLayout.getChildren().addAll(hBox); generalLayout.getChildren().addAll(hBox);

View File

@ -25,9 +25,9 @@ import javafx.scene.web.WebView;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.commonmark.parser.Parser; import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.renderer.html.HtmlRenderer;
import org.jcnc.jnotepad.api.core.ui.stage.AbstractPaneStage; import org.jcnc.jnotepad.api.core.component.stage.AbstractPaneStage;
import org.jcnc.jnotepad.cache.entity.PluginDescriptor;
import org.jcnc.jnotepad.component.stage.setting.CustomSetButton; import org.jcnc.jnotepad.component.stage.setting.CustomSetButton;
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
import org.jcnc.jnotepad.plugin.manager.PluginManager; import org.jcnc.jnotepad.plugin.manager.PluginManager;
import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.PopUpUtil; import org.jcnc.jnotepad.util.PopUpUtil;

View File

@ -1,9 +1,9 @@
package org.jcnc.jnotepad.controller.cache; package org.jcnc.jnotepad.controller.cache;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import org.jcnc.jnotepad.cache.entity.Cache;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager; import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
import org.jcnc.jnotepad.controller.config.AppConfigController; 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.JsonUtil;
import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.LogUtil;
import org.slf4j.Logger; import org.slf4j.Logger;

View File

@ -2,7 +2,7 @@ package org.jcnc.jnotepad.controller.config;
import org.jcnc.jnotepad.api.core.controller.config.BaseConfigController; import org.jcnc.jnotepad.api.core.controller.config.BaseConfigController;
import org.jcnc.jnotepad.app.config.UserConfig; import org.jcnc.jnotepad.app.config.UserConfig;
import org.jcnc.jnotepad.cache.entity.ShortcutKey; import org.jcnc.jnotepad.model.entity.ShortcutKey;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -6,7 +6,7 @@ import javafx.scene.control.Tab;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.common.constants.AppConstants; import org.jcnc.jnotepad.common.constants.AppConstants;
import org.jcnc.jnotepad.common.constants.TextConstants; import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.component.module.CodeArea; import org.jcnc.jnotepad.component.module.TextCodeArea;
import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager; import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager;
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager; 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.CenterTab;
@ -38,7 +38,7 @@ public class NewFile implements EventHandler<ActionEvent> {
*/ */
public void addNewFileTab() { public void addNewFileTab() {
// 创建一个新的文本编辑区 // 创建一个新的文本编辑区
CodeArea textArea = new CodeArea(); TextCodeArea textArea = new TextCodeArea();
// TODO: refactor统一TextArea新建绑定监听器入口 // TODO: refactor统一TextArea新建绑定监听器入口
// 设定初始索引 // 设定初始索引
int index = 1; int index = 1;

View File

@ -4,12 +4,12 @@ package org.jcnc.jnotepad.controller.event.handler.menuitem;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.cache.entity.Cache;
import org.jcnc.jnotepad.cache.entity.DirFileModel;
import org.jcnc.jnotepad.cache.enums.CacheExpirationTime;
import org.jcnc.jnotepad.common.constants.TextConstants; import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager; import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicDirectoryChooserFactory; import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicDirectoryChooserFactory;
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.FileUtil;
import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.DirectorySidebarManager; import org.jcnc.jnotepad.views.manager.DirectorySidebarManager;

View File

@ -5,12 +5,12 @@ import javafx.event.EventHandler;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.cache.entity.Cache;
import org.jcnc.jnotepad.cache.enums.CacheExpirationTime;
import org.jcnc.jnotepad.common.constants.TextConstants; import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager; import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
import org.jcnc.jnotepad.component.module.CodeArea; import org.jcnc.jnotepad.component.module.TextCodeArea;
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicFileChooserFactory; import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicFileChooserFactory;
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.EncodingDetector;
import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.util.UiUtil;
@ -70,9 +70,9 @@ public class OpenFile implements EventHandler<ActionEvent> {
*/ */
public static void openFile(File file) { public static void openFile(File file) {
// 获取标签页集合 // 获取标签页集合
CenterTabPane jnotepadTabPane = CenterTabPane.getInstance(); CenterTabPane centerTabPane = CenterTabPane.getInstance();
// 遍历标签页查找匹配的标签页 // 遍历标签页查找匹配的标签页
for (Tab tab : jnotepadTabPane.getTabs()) { for (Tab tab : centerTabPane.getTabs()) {
// 获取绑定的文件 // 获取绑定的文件
File tabFile = (File) tab.getUserData(); File tabFile = (File) tab.getUserData();
if (tabFile == null) { if (tabFile == null) {
@ -80,7 +80,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
} }
if (file.getPath().equals((tabFile).getPath())) { if (file.getPath().equals((tabFile).getPath())) {
// 找到匹配的标签页设置为选中状态并跳转 // 找到匹配的标签页设置为选中状态并跳转
jnotepadTabPane.getSelectionModel().select(tab); centerTabPane.getSelectionModel().select(tab);
return; return;
} }
} }
@ -93,13 +93,13 @@ public class OpenFile implements EventHandler<ActionEvent> {
* @param file 文件对象 * @param file 文件对象
*/ */
public static void getText(File file) { public static void getText(File file) {
CodeArea textArea = createNewTextArea(); TextCodeArea textCodeArea = createNewTextArea();
// 检测文件编码 // 检测文件编码
Charset encoding = EncodingDetector.detectEncodingCharset(file); Charset encoding = EncodingDetector.detectEncodingCharset(file);
String fileText = getFileText(file, encoding); String fileText = getFileText(file, encoding);
LogUtil.getLogger(OpenFile.class).info("已调用读取文件功能"); LogUtil.getLogger(OpenFile.class).info("已调用读取文件功能");
textArea.appendText(fileText); textCodeArea.appendText(fileText);
CenterTab tab = createNewTab(file.getName(), textArea, encoding); CenterTab tab = createNewTab(file.getName(), textCodeArea, encoding);
// 设置当前标签页关联本地文件 // 设置当前标签页关联本地文件
tab.setRelevance(true); tab.setRelevance(true);
// 设置标签页关联文件 // 设置标签页关联文件
@ -115,18 +115,18 @@ public class OpenFile implements EventHandler<ActionEvent> {
* *
* @return 新的文本区域 * @return 新的文本区域
*/ */
private static CodeArea createNewTextArea() { private static TextCodeArea createNewTextArea() {
return new CodeArea(); return new TextCodeArea();
} }
/** /**
* 创建新的标签页 * 创建新的标签页
* *
* @param tabName 标签名 * @param tabName 标签名
* @param textArea 文本区域 * @param textCodeArea 文本区域
* @return 新的标签页 * @return 新的标签页
*/ */
private static CenterTab createNewTab(String tabName, CodeArea textArea, Charset charset) { private static CenterTab createNewTab(String tabName, TextCodeArea textCodeArea, Charset charset) {
return new CenterTab(tabName, textArea, charset); return new CenterTab(tabName, textCodeArea, charset);
} }
} }

View File

@ -4,13 +4,13 @@ import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.cache.entity.Cache;
import org.jcnc.jnotepad.cache.enums.CacheExpirationTime;
import org.jcnc.jnotepad.common.constants.TextConstants; import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager; import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicFileChooserFactory; import org.jcnc.jnotepad.component.stage.dialog.factory.impl.BasicFileChooserFactory;
import org.jcnc.jnotepad.controller.config.UserConfigController; import org.jcnc.jnotepad.controller.config.UserConfigController;
import org.jcnc.jnotepad.controller.i18n.LocalizationController; 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.LogUtil;
import org.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager; import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.cache.entity; package org.jcnc.jnotepad.model.entity;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;

View File

@ -0,0 +1,56 @@
package org.jcnc.jnotepad.model.entity;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
/**
* 默认上下文菜单
*
* @author gewuyou
*/
public class DefaultContextMenu extends ContextMenu {
private final MenuItem fold;
private final MenuItem unfold;
private final MenuItem print;
public DefaultContextMenu() {
fold = new MenuItem("折叠所选文本");
fold.setOnAction(aE -> {
hide();
fold();
});
unfold = new MenuItem("从光标处展开");
unfold.setOnAction(aE -> {
hide();
unfold();
});
print = new MenuItem("打印");
print.setOnAction(aE -> {
hide();
print();
});
getItems().addAll(fold, unfold, print);
}
/**
* 折叠多行所选文本仅显示第一行并隐藏其余部分
*/
private void fold() {
((org.fxmisc.richtext.CodeArea) getOwnerNode()).foldSelectedParagraphs();
}
/**
* 展开当前行/段落如果有折叠
*/
private void unfold() {
org.fxmisc.richtext.CodeArea area = (org.fxmisc.richtext.CodeArea) getOwnerNode();
area.unfoldParagraphs(area.getCurrentParagraph());
}
private void print() {
System.out.println(((org.fxmisc.richtext.CodeArea) getOwnerNode()).getText());
}
}

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.cache.entity; package org.jcnc.jnotepad.model.entity;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.cache.entity; package org.jcnc.jnotepad.model.entity;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import org.jcnc.jnotepad.plugin.interfaces.Plugin; import org.jcnc.jnotepad.plugin.interfaces.Plugin;

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.cache.entity; package org.jcnc.jnotepad.model.entity;
/** /**

View File

@ -0,0 +1,47 @@
package org.jcnc.jnotepad.model.entity;
import javafx.application.Platform;
import org.fxmisc.richtext.GenericStyledArea;
import org.fxmisc.richtext.model.Paragraph;
import org.fxmisc.richtext.model.StyleSpans;
import org.reactfx.collection.ListModification;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* 可见段落样式器
*
* @author gewuyou
*/
public class VisibleParagraphStyler<PS, SEG, S> implements Consumer<ListModification<? extends Paragraph<PS, SEG, S>>> {
private final GenericStyledArea<PS, SEG, S> area;
private final Function<String, StyleSpans<S>> computeStyles;
private int prevParagraph;
private int prevTextLength;
public VisibleParagraphStyler(GenericStyledArea<PS, SEG, S> area, Function<String, StyleSpans<S>> computeStyles) {
this.computeStyles = computeStyles;
this.area = area;
}
@Override
public void accept(ListModification<? extends Paragraph<PS, SEG, S>> lm) {
if (lm.getAddedSize() > 0) {
Platform.runLater(() -> {
int paragraph = Math.min(area.firstVisibleParToAllParIndex() + lm.getFrom(), area.getParagraphs().size() - 1);
String text = area.getText(paragraph, 0, paragraph, area.getParagraphLength(paragraph));
if (paragraph != prevParagraph || text.length() != prevTextLength) {
if (paragraph < area.getParagraphs().size() - 1) {
int startPos = area.getAbsolutePosition(paragraph, 0);
area.setStyleSpans(startPos, computeStyles.apply(text));
}
prevTextLength = text.length();
prevParagraph = paragraph;
}
});
}
}
}

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.cache.enums; package org.jcnc.jnotepad.model.enums;
/** /**
* 缓存过期时间枚举 * 缓存过期时间枚举

View File

@ -1,4 +1,4 @@
package org.jcnc.jnotepad.cache.enums; package org.jcnc.jnotepad.model.enums;
/** /**
* 对话框类型 * 对话框类型

View File

@ -1,9 +1,9 @@
package org.jcnc.jnotepad.plugin; package org.jcnc.jnotepad.plugin;
import org.jcnc.jnotepad.cache.entity.PluginDescriptor;
import org.jcnc.jnotepad.common.manager.ThreadPoolManager; import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
import org.jcnc.jnotepad.controller.config.PluginConfigController; import org.jcnc.jnotepad.controller.config.PluginConfigController;
import org.jcnc.jnotepad.controller.exception.AppException; import org.jcnc.jnotepad.controller.exception.AppException;
import org.jcnc.jnotepad.model.entity.PluginDescriptor;
import org.jcnc.jnotepad.plugin.interfaces.Plugin; import org.jcnc.jnotepad.plugin.interfaces.Plugin;
import org.jcnc.jnotepad.plugin.manager.PluginManager; import org.jcnc.jnotepad.plugin.manager.PluginManager;
import org.jcnc.jnotepad.util.JsonUtil; import org.jcnc.jnotepad.util.JsonUtil;

View File

@ -1,9 +1,9 @@
package org.jcnc.jnotepad.plugin.manager; package org.jcnc.jnotepad.plugin.manager;
import org.jcnc.jnotepad.app.manager.ApplicationManager; import org.jcnc.jnotepad.app.manager.ApplicationManager;
import org.jcnc.jnotepad.cache.entity.PluginDescriptor;
import org.jcnc.jnotepad.common.manager.ThreadPoolManager; import org.jcnc.jnotepad.common.manager.ThreadPoolManager;
import org.jcnc.jnotepad.controller.config.PluginConfigController; 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.LogUtil;
import org.jcnc.jnotepad.util.PopUpUtil; import org.jcnc.jnotepad.util.PopUpUtil;
import org.slf4j.Logger; import org.slf4j.Logger;

View File

@ -1,15 +1,17 @@
package org.jcnc.jnotepad.util; package org.jcnc.jnotepad.util;
import org.jcnc.jnotepad.cache.entity.DirFileModel;
import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenFile; import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenFile;
import org.jcnc.jnotepad.controller.exception.AppException; import org.jcnc.jnotepad.controller.exception.AppException;
import org.jcnc.jnotepad.model.entity.DirFileModel;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
import java.io.*; import java.io.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
@ -157,7 +159,42 @@ public class FileUtil {
} }
} }
} }
return dirFileModel; return dirFileModel;
} }
/**
* 文件夹迁移
*
* @param sourceFolder 源文件夹
* @param targetFolder 目标文件夹
* @since 2023/10/5 12:18
*/
private static void migrateFolder(File sourceFolder, File targetFolder) {
// 创建目标文件夹
targetFolder.mkdirs();
// 获取源文件夹中的所有文件和文件夹
File[] files = sourceFolder.listFiles();
if (files != null) {
// 遍历源文件夹中的每个文件和文件夹
for (File file : files) {
if (file.isDirectory()) {
// 如果是文件夹递归调用自身进行迁移
migrateFolder(file, new File(targetFolder, file.getName()));
} else {
// 如果是文件将文件复制到目标文件夹中
Path sourceFilePath = file.toPath();
Path targetFilePath = new File(targetFolder, file.getName()).toPath();
try {
Files.copy(sourceFilePath, targetFilePath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new AppException(e);
}
}
}
}
}
} }

View File

@ -1,8 +1,8 @@
package org.jcnc.jnotepad.util; package org.jcnc.jnotepad.util;
import org.jcnc.jnotepad.cache.enums.DialogType;
import org.jcnc.jnotepad.component.stage.dialog.AppDialogBuilder; import org.jcnc.jnotepad.component.stage.dialog.AppDialogBuilder;
import org.jcnc.jnotepad.component.stage.dialog.interfaces.DialogButtonAction; import org.jcnc.jnotepad.component.stage.dialog.interfaces.DialogButtonAction;
import org.jcnc.jnotepad.model.enums.DialogType;
/** /**
* 弹窗工具类 * 弹窗工具类

View File

@ -7,7 +7,7 @@ import javafx.scene.control.Label;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle; import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.common.constants.TextConstants; import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.component.module.CodeArea; import org.jcnc.jnotepad.component.module.TextCodeArea;
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox; import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
@ -106,7 +106,7 @@ public class BottomStatusBoxManager {
if (instance.getSelected() == null) { if (instance.getSelected() == null) {
return; return;
} }
CodeArea textArea = instance.getSelected().getLineNumberTextArea(); TextCodeArea textArea = instance.getSelected().getLineNumberTextArea();
int caretPosition = textArea.getCaretPosition(); int caretPosition = textArea.getCaretPosition();
int row = getRow(caretPosition, textArea.getText()); int row = getRow(caretPosition, textArea.getText());
int column = getColumn(caretPosition, textArea.getText()); int column = getColumn(caretPosition, textArea.getText());
@ -128,7 +128,7 @@ public class BottomStatusBoxManager {
updateEncodingLabel(centerTab.getCharset().name()); updateEncodingLabel(centerTab.getCharset().name());
// 添加光标位置变化监听器 // 添加光标位置变化监听器
CodeArea textArea = centerTab.getLineNumberTextArea(); TextCodeArea textArea = centerTab.getLineNumberTextArea();
textArea.caretPositionProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> updateRowColumnLabel(textArea.getCaretPosition(), textArea.getText())); textArea.caretPositionProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> updateRowColumnLabel(textArea.getCaretPosition(), textArea.getText()));
} }
} }

View File

@ -3,10 +3,10 @@ package org.jcnc.jnotepad.views.manager;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.jcnc.jnotepad.cache.enums.CacheExpirationTime;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager; import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
import org.jcnc.jnotepad.component.module.CodeArea; import org.jcnc.jnotepad.component.module.TextCodeArea;
import org.jcnc.jnotepad.controller.config.UserConfigController; import org.jcnc.jnotepad.controller.config.UserConfigController;
import org.jcnc.jnotepad.model.enums.CacheExpirationTime;
import org.jcnc.jnotepad.util.FileUtil; import org.jcnc.jnotepad.util.FileUtil;
import org.jcnc.jnotepad.util.PopUpUtil; import org.jcnc.jnotepad.util.PopUpUtil;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
@ -79,7 +79,7 @@ public class CenterTabPaneManager {
} }
if (tab.isRelevance()) { if (tab.isRelevance()) {
// 获取当前文本域对象 // 获取当前文本域对象
CodeArea codeArea = tab.getLineNumberTextArea(); TextCodeArea textCodeArea = tab.getLineNumberTextArea();
// 获取当前标签页对应文件上次修改时间 // 获取当前标签页对应文件上次修改时间
Long lastModifiedTime = tab.getLastModifiedTimeOfAssociatedFile(); Long lastModifiedTime = tab.getLastModifiedTimeOfAssociatedFile();
// 获取对应文件上次修改时间 // 获取对应文件上次修改时间
@ -95,8 +95,8 @@ public class CenterTabPaneManager {
PopUpUtil.questionAlert( PopUpUtil.questionAlert(
"重新加载", file.getAbsolutePath(), "此文件已被外部修改,是否重新加载该文件?", "重新加载", file.getAbsolutePath(), "此文件已被外部修改,是否重新加载该文件?",
appDialog -> { appDialog -> {
codeArea.clear(); textCodeArea.clear();
codeArea.appendText(fileText); textCodeArea.appendText(fileText);
appDialog.close(); appDialog.close();
}, Stage::close, "", ""); }, Stage::close, "", "");
} }

View File

@ -3,9 +3,9 @@ package org.jcnc.jnotepad.views.manager;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.scene.control.SplitPane; import javafx.scene.control.SplitPane;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
import org.jcnc.jnotepad.cache.entity.DirFileModel;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager; import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenDirectory; import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenDirectory;
import org.jcnc.jnotepad.model.entity.DirFileModel;
import org.jcnc.jnotepad.util.FileUtil; import org.jcnc.jnotepad.util.FileUtil;
import org.jcnc.jnotepad.views.root.center.main.MainBorderPane; import org.jcnc.jnotepad.views.root.center.main.MainBorderPane;
import org.jcnc.jnotepad.views.root.center.main.center.directory.DirectorySidebarPane; import org.jcnc.jnotepad.views.root.center.main.center.directory.DirectorySidebarPane;

View File

@ -6,8 +6,8 @@ import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyCombination;
import org.jcnc.jnotepad.api.core.views.manager.AbstractManager; import org.jcnc.jnotepad.api.core.views.manager.AbstractManager;
import org.jcnc.jnotepad.cache.entity.ShortcutKey;
import org.jcnc.jnotepad.controller.config.UserConfigController; import org.jcnc.jnotepad.controller.config.UserConfigController;
import org.jcnc.jnotepad.model.entity.ShortcutKey;
import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.views.root.top.menubar.TopMenuBar; import org.jcnc.jnotepad.views.root.top.menubar.TopMenuBar;
import org.jcnc.jnotepad.views.root.top.menubar.menu.*; import org.jcnc.jnotepad.views.root.top.menubar.menu.*;

View File

@ -2,8 +2,8 @@ package org.jcnc.jnotepad.views.root.center.main.center.directory;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView; import javafx.scene.control.TreeView;
import org.jcnc.jnotepad.cache.entity.DirFileModel;
import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenFile; import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenFile;
import org.jcnc.jnotepad.model.entity.DirFileModel;
import java.io.File; import java.io.File;
import java.util.Objects; import java.util.Objects;

View File

@ -2,7 +2,7 @@ package org.jcnc.jnotepad.views.root.center.main.center.tab;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import org.fxmisc.flowless.VirtualizedScrollPane; import org.fxmisc.flowless.VirtualizedScrollPane;
import org.jcnc.jnotepad.component.module.CodeArea; import org.jcnc.jnotepad.component.module.TextCodeArea;
import org.jcnc.jnotepad.controller.config.UserConfigController; import org.jcnc.jnotepad.controller.config.UserConfigController;
import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager; import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager;
@ -23,7 +23,7 @@ import java.nio.charset.Charset;
*/ */
public class CenterTab extends Tab { public class CenterTab extends Tab {
Logger logger = LogUtil.getLogger(this.getClass()); Logger logger = LogUtil.getLogger(this.getClass());
private final CodeArea codeArea; private final TextCodeArea textCodeArea;
/** /**
* 默认关闭自动换行 * 默认关闭自动换行
*/ */
@ -39,18 +39,18 @@ public class CenterTab extends Tab {
private Charset charset = Charset.defaultCharset(); private Charset charset = Charset.defaultCharset();
public CenterTab(String tabTitle) { public CenterTab(String tabTitle) {
this(tabTitle, new CodeArea()); this(tabTitle, new TextCodeArea());
} }
public CenterTab(String tabTitle, CodeArea textArea) { public CenterTab(String tabTitle, TextCodeArea textArea) {
this(tabTitle, textArea, Charset.defaultCharset()); this(tabTitle, textArea, Charset.defaultCharset());
} }
public CenterTab(String tabTitle, CodeArea textArea, Charset charset) { public CenterTab(String tabTitle, TextCodeArea textArea, Charset charset) {
super(tabTitle); super(tabTitle);
codeArea = textArea; textCodeArea = textArea;
initTextAreaListeners(); initTextAreaListeners();
this.setContent(new VirtualizedScrollPane<>(codeArea)); this.setContent(new VirtualizedScrollPane<>(textCodeArea));
setAutoLine(UserConfigController.getInstance().getAutoLineConfig()); setAutoLine(UserConfigController.getInstance().getAutoLineConfig());
this.charset = charset; this.charset = charset;
} }
@ -69,11 +69,11 @@ public class CenterTab extends Tab {
public void setAutoLine(boolean autoLine) { public void setAutoLine(boolean autoLine) {
this.autoLine = autoLine; this.autoLine = autoLine;
codeArea.setWrapText(autoLine); textCodeArea.setWrapText(autoLine);
} }
public CodeArea getLineNumberTextArea() { public TextCodeArea getLineNumberTextArea() {
return codeArea; return textCodeArea;
} }
public Charset getCharset() { public Charset getCharset() {
@ -126,7 +126,7 @@ public class CenterTab extends Tab {
*/ */
private void initTextAreaListeners() { private void initTextAreaListeners() {
// 监听主要文本区域的文本变化 // 监听主要文本区域的文本变化
codeArea.textProperty().addListener((observable, oldValue, newValue) -> { textCodeArea.textProperty().addListener((observable, oldValue, newValue) -> {
BottomStatusBoxManager.getInstance().updateWordCountStatusLabel(); BottomStatusBoxManager.getInstance().updateWordCountStatusLabel();
saveSelectedFileTab(); saveSelectedFileTab();
}); });

11
tool/jpackage.sh Normal file
View File

@ -0,0 +1,11 @@
#!/bin/bash
#请在jlink之后通过文件管理器打开tool双击这个脚本而不是直接使用Idea执行
cd ..
jpackage \
--name JNotepad \
--type app-image \
-m org.jcnc.jnotepad/org.jcnc.jnotepad.LunchApp \
--runtime-image ./target/JNotepad/ \
--icon src/main/resources/img/icon.ico \
--app-version 1.1.13 \
--vendor "JCNC"