Merge branch 'release-v1.1.13' of https://gitee.com/jcnc-org/JNotepad into develop

This commit is contained in:
gewuyou 2023-10-02 21:32:38 +08:00
commit 49ea34ac7a
20 changed files with 478 additions and 11 deletions

View File

@ -13,6 +13,7 @@ public class TextConstants {
public static final String FILE = "FILE"; public static final String FILE = "FILE";
public static final String NEW = "NEW"; public static final String NEW = "NEW";
public static final String OPEN = "OPEN"; 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 SAVE_AS = "SAVE_AS";
public static final String RENAME = "RENAME"; public static final String RENAME = "RENAME";
public static final String SET = "SET"; public static final String SET = "SET";

View File

@ -0,0 +1,62 @@
package org.jcnc.jnotepad.controller.event.handler.menubar;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.common.manager.ApplicationCacheManager;
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.ui.dialog.factory.impl.BasicDirectoryChooserFactory;
import org.jcnc.jnotepad.util.FileUtil;
import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.DirectorySidebarManager;
import java.io.File;
/**
* @author : cccqyu
* @createTime 2023/10/2 1:29
* @description 当用户选择打开文件夹时将创建一个左侧树型结构目录
*/
public class OpenDirectory implements EventHandler<ActionEvent> {
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
private static final DirectorySidebarManager DIRECTORY_SIDEBAR_MANAGER=DirectorySidebarManager.getInstance();
@Override
public void handle(ActionEvent actionEvent) {
// 获取缓存
Cache cache = CACHE_MANAGER.getCache("directory", "openDirectory");
// 显示文件选择对话框并获取选中的文件
File file = BasicDirectoryChooserFactory.getInstance().createDirectoryChooser(
UiResourceBundle.getContent(TextConstants.OPEN),
cache == null ? null : new File((String) cache.getCacheData())
)
.showDialog(UiUtil.getAppWindow());
if (file == null) {
return;
}
// 设置缓存
if (cache == null) {
CACHE_MANAGER.addCache(CACHE_MANAGER.createCache("directory", "openDirectory", file.getAbsolutePath(), CacheExpirationTime.NEVER_EXPIRES.getValue()));
} else {
cache.setCacheData(file.getParent());
CACHE_MANAGER.addCache(cache);
}
flushDirSidebar(file);
}
public void flushDirSidebar(File file){
// 将文件转为实体类
DirFileModel dirFileModel = FileUtil.getDirFileModel(file);
// 打开侧边栏
DIRECTORY_SIDEBAR_MANAGER.controlShow(true);
// 设置文件树功能
DIRECTORY_SIDEBAR_MANAGER.setTreeView(dirFileModel);
}
}

View File

@ -0,0 +1,20 @@
package org.jcnc.jnotepad.controller.event.handler.setting;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import org.jcnc.jnotepad.views.manager.DirectorySidebarManager;
/**
* @author : cccqyu
* @createTime 2023/10/2 17:24
* @description 文件树按钮事件的事件处理程序
*/
public class DirTreeBtn implements EventHandler<ActionEvent> {
private static final DirectorySidebarManager DIRECTORY_SIDEBAR_MANAGER = DirectorySidebarManager.getInstance();
@Override
public void handle(ActionEvent actionEvent) {
DIRECTORY_SIDEBAR_MANAGER.controlShow();
}
}

View File

@ -0,0 +1,50 @@
package org.jcnc.jnotepad.model.entity;
import java.util.List;
/**
* @author : cccqyu
* @createTime 2023/10/2 20:31
* @description 文件夹实体类
*/
public class DirFileModel {
private String path;
private String name;
private List<DirFileModel> childFile;
public DirFileModel(String path, String name, List<DirFileModel> childFile) {
this.path = path;
this.name = name;
this.childFile = childFile;
}
public List<DirFileModel> getChildFile() {
return childFile;
}
public void setChildFile(List<DirFileModel> childFile) {
this.childFile = childFile;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}

View File

@ -0,0 +1,28 @@
package org.jcnc.jnotepad.ui.dialog.factory;
import javafx.stage.DirectoryChooser;
import java.io.File;
/**
* @author : cccqyu
* @createTime 2023/10/2 1:49
* @description 文件夹选择对话框工厂,该工厂接口用于创建文件夹选择对话框包括原始和详细两种类型
*/
public interface DirectoryChooserFactory {
/**
* 创建原始文件选择对话框
*
* @return javafx.stage.DirectoryChooser 原始文件夹选择对话框对象
*/
DirectoryChooser createDirectoryChooser();
/**
* 创建详细的文件选择对话框
*
* @param title 对话框标题
* @param directory 初始目录
* @return javafx.stage.FileChooser 详细文件选择对话框对象
*/
DirectoryChooser createDirectoryChooser(String title, File directory);
}

View File

@ -0,0 +1,56 @@
package org.jcnc.jnotepad.ui.dialog.factory.impl;
import javafx.stage.DirectoryChooser;
import org.jcnc.jnotepad.ui.dialog.factory.DirectoryChooserFactory;
import java.io.File;
/**
* @author : cccqyu@outlook.com
* @createTime 2023/10/2 1:54
* @description 基本文件夹选择对话框
*/
public class BasicDirectoryChooserFactory implements DirectoryChooserFactory {
private static final BasicDirectoryChooserFactory INSTANCE = new BasicDirectoryChooserFactory();
private BasicDirectoryChooserFactory() {
}
public static BasicDirectoryChooserFactory getInstance() {
return INSTANCE;
}
/**
* 创建原始文件选择对话框
*
* @return javafx.stage.DirectoryChooser 原始文件夹选择对话框对象
*/
@Override
public DirectoryChooser createDirectoryChooser() {
return new DirectoryChooser();
}
/**
* 创建详细的文件选择对话框
*
* @param title 对话框标题
* @param directory 初始目录
* @return javafx.stage.FileChooser 详细文件选择对话框对象
*/
@Override
public DirectoryChooser createDirectoryChooser(String title, File directory) {
DirectoryChooser directoryChooser= createDirectoryChooser();
// 设置窗口名称
directoryChooser.setTitle(title);
if (directory != null) {
// 设置打开的目录
directoryChooser.setInitialDirectory(directory);
}
return directoryChooser;
}
}

View File

@ -0,0 +1,43 @@
package org.jcnc.jnotepad.util;
import org.jcnc.jnotepad.model.entity.DirFileModel;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author : cccqyu
* @createTime 2023/10/2 2:31
* @description 文件工具类
*/
public class FileUtil {
/**
* 将文件夹转为DirFileModel
*
* @param file 文件
* @return DirFileModel 存储文件夹与文件关系的实体类
*/
public static DirFileModel getDirFileModel(File file) {
if (!file.exists()) {
return null;
}
DirFileModel dirFileModel = new DirFileModel(file.getAbsolutePath(), file.getName(), new ArrayList<>());
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
DirFileModel childDirFileModel = getDirFileModel(f);
dirFileModel.getChildFile().add(childDirFileModel);
} else {
dirFileModel.getChildFile().add(new DirFileModel(f.getAbsolutePath(), f.getName(), null));
}
}
}
return dirFileModel;
}
}

View File

@ -0,0 +1,92 @@
package org.jcnc.jnotepad.views.manager;
import javafx.scene.control.TreeItem;
import org.jcnc.jnotepad.model.entity.DirFileModel;
import org.jcnc.jnotepad.views.root.center.main.MainBorderPane;
import org.jcnc.jnotepad.views.root.center.main.center.directory.DirectorySidebarPane;
import java.util.List;
/**
* @author : cccqyu
* @createTime 2023/10/2 20:33
* @description 文件树管理类
*/
public class DirectorySidebarManager {
private DirectorySidebarManager() {
}
;
/**
* 单例模式保证只有一个 DirectorySidebar 实例
*/
private static final DirectorySidebarManager INSTANCE = new DirectorySidebarManager();
public static DirectorySidebarManager getInstance() {
return INSTANCE;
}
private static final MainBorderPane MAIN_BORDER_PANE = MainBorderPane.getInstance();
private static final DirectorySidebarPane DIRECTORY_SIDEBAR_PANE = DirectorySidebarPane.getInstance();
/**
* 控制文件树显示
* */
public void controlShow() {
boolean isVisible = DIRECTORY_SIDEBAR_PANE.isVisible();
// 设置自身显示
DIRECTORY_SIDEBAR_PANE.setVisible(!isVisible);
if (isVisible) {
// 布局中移除
MAIN_BORDER_PANE.setLeft(null);
} else {
MAIN_BORDER_PANE.setLeft(DIRECTORY_SIDEBAR_PANE);
}
}
/**
* 控制文件树显示
* @param bool 打开
* */
public void controlShow(boolean bool) {
// 设置自身显示
DIRECTORY_SIDEBAR_PANE.setVisible(bool);
if (!MAIN_BORDER_PANE.getChildren().contains(DIRECTORY_SIDEBAR_PANE)) {
MAIN_BORDER_PANE.setLeft(DIRECTORY_SIDEBAR_PANE);
}
}
/**
* 设置文件树内容
* @param dirFileModel 文件
* */
public void setTreeView(DirFileModel dirFileModel) {
TreeItem<DirFileModel> rootItem = new TreeItem<DirFileModel>(dirFileModel);
DIRECTORY_SIDEBAR_PANE.setRoot(rootItem);
expandFolder(dirFileModel, rootItem);
}
/**
* 递归展开 dirFileModel
* @param dirFileModel 文件
* @param item 文件树子项内容
* */
private void expandFolder(DirFileModel dirFileModel, TreeItem<DirFileModel> item) {
List<DirFileModel> childFileList = dirFileModel.getChildFile();
if (childFileList != null) {
for (DirFileModel childFile : childFileList) {
TreeItem<DirFileModel> childItem = new TreeItem<>(childFile);
item.getChildren().add(childItem);
expandFolder(childFile, childItem);
}
}
}
}

View File

@ -4,6 +4,7 @@ import org.jcnc.jnotepad.views.root.RootBorderPane;
import org.jcnc.jnotepad.views.root.bottom.RootBottomSideBarVerticalBox; import org.jcnc.jnotepad.views.root.bottom.RootBottomSideBarVerticalBox;
import org.jcnc.jnotepad.views.root.center.main.MainBorderPane; import org.jcnc.jnotepad.views.root.center.main.MainBorderPane;
import org.jcnc.jnotepad.views.root.left.sidebar.tools.ToolHorizontalBox; import org.jcnc.jnotepad.views.root.left.sidebar.tools.ToolHorizontalBox;
import org.jcnc.jnotepad.views.root.left.sidebar.tools.ToolVerticalBox;
import org.jcnc.jnotepad.views.root.right.RootRightSideBarVerticalBox; import org.jcnc.jnotepad.views.root.right.RootRightSideBarVerticalBox;
import org.jcnc.jnotepad.views.root.top.RootTopBorderPane; import org.jcnc.jnotepad.views.root.top.RootTopBorderPane;
@ -36,7 +37,8 @@ public class RootBorderPaneManager {
// 中间用于显示主界面 // 中间用于显示主界面
rootBorderPane.setCenterComponent(MainBorderPane.getInstance()); rootBorderPane.setCenterComponent(MainBorderPane.getInstance());
// 主界面的左边工具栏 // 主界面的左边工具栏
rootBorderPane.setLeftComponent(ToolHorizontalBox.getInstance()); // rootBorderPane.setLeftComponent(ToolHorizontalBox.getInstance());
rootBorderPane.setLeftComponent(ToolVerticalBox.getInstance());
// 主界面的右边侧边栏 // 主界面的右边侧边栏
rootBorderPane.setRightComponent(RootRightSideBarVerticalBox.getInstance()); rootBorderPane.setRightComponent(RootRightSideBarVerticalBox.getInstance());
// 主界面的上面菜单栏 // 主界面的上面菜单栏

View File

@ -3,6 +3,7 @@ package org.jcnc.jnotepad.views.manager;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import org.jcnc.jnotepad.controller.event.handler.setting.DirTreeBtn;
import org.jcnc.jnotepad.controller.event.handler.setting.SetBtn; import org.jcnc.jnotepad.controller.event.handler.setting.SetBtn;
import org.jcnc.jnotepad.views.manager.builder.SideBarButtonBuilder; import org.jcnc.jnotepad.views.manager.builder.SideBarButtonBuilder;
import org.jcnc.jnotepad.views.root.left.sidebar.tools.SidebarToolBar; import org.jcnc.jnotepad.views.root.left.sidebar.tools.SidebarToolBar;
@ -43,19 +44,20 @@ public class SidebarToolBarManager extends AbstractManager<Node> {
.setImageViewEssentialAttribute(10D, 10D, true, 2.5D, 2.5D) .setImageViewEssentialAttribute(10D, 10D, true, 2.5D, 2.5D)
.setButtonEssentialAttribute(20D, 20D) .setButtonEssentialAttribute(20D, 20D)
.setEventHandler(new SetBtn()).build()); .setEventHandler(new SetBtn()).build());
// 注册文件树按钮
registerNode( registerNode(
new SideBarButtonBuilder() new SideBarButtonBuilder()
.setButton(sidebarToolBar.getFileButton()) .setButton(sidebarToolBar.getDirTreeButton())
.setImageView(new ImageView(new Image("tools.png"))) .setImageView(new ImageView(new Image("directory.png")))
.setImageViewEssentialAttribute(10D, 10D, true, 2.5D, 2.5D) .setImageViewEssentialAttribute(10D, 10D, true, 2.5D, 2.5D)
.setButtonEssentialAttribute(20D, 20D) .setButtonEssentialAttribute(20D, 20D)
// TODO: 2023/10/2 修改点击事件 .setEventHandler(new DirTreeBtn()).build());
.setEventHandler(new SetBtn()).build());
} }
/** /**
* 获取节点列表 * 获取节点列表
* *

View File

@ -23,6 +23,7 @@ import org.slf4j.Logger;
import java.util.*; import java.util.*;
import static org.jcnc.jnotepad.common.constants.TextConstants.*; import static org.jcnc.jnotepad.common.constants.TextConstants.*;
import static org.jcnc.jnotepad.common.constants.TextConstants.OPEN_DIRECTORY;
/** /**
* 顶部菜单栏管理类 * 顶部菜单栏管理类
@ -89,6 +90,8 @@ public class TopMenuBarManager extends AbstractManager<Menu> {
registerFileMenuItem(topMenuBar.getSaveItem(), SAVE, "saveItem", new SaveFile()); registerFileMenuItem(topMenuBar.getSaveItem(), SAVE, "saveItem", new SaveFile());
registerFileMenuItem(topMenuBar.getSaveAsItem(), SAVE_AS, "saveAsItem", new SaveAsFile()); registerFileMenuItem(topMenuBar.getSaveAsItem(), SAVE_AS, "saveAsItem", new SaveAsFile());
registerFileMenuItem(topMenuBar.getRenameItem(), RENAME, "renameItem", new RenameFile()); registerFileMenuItem(topMenuBar.getRenameItem(), RENAME, "renameItem", new RenameFile());
// 打开文件夹按钮
registerFileMenuItem(topMenuBar.getOpenDirItem(), OPEN_DIRECTORY, "openDirItem", new OpenDirectory());
// 语言菜单 // 语言菜单
registerLanguageMenuItem(topMenuBar.getChineseItem(), UPPER_CHINESE, Locale.CHINESE, this::toggleLanguage); registerLanguageMenuItem(topMenuBar.getChineseItem(), UPPER_CHINESE, Locale.CHINESE, this::toggleLanguage);

View File

@ -0,0 +1,49 @@
package org.jcnc.jnotepad.views.root.center.main.center.directory;
import javafx.event.EventHandler;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.MouseEvent;
import org.jcnc.jnotepad.controller.event.handler.menubar.OpenFile;
import org.jcnc.jnotepad.model.entity.DirFileModel;
import java.io.File;
import java.util.Objects;
/**
* @author : cccqyu
* @createTime 2023/10/2 20:34
* @description TreeView封装
*/
public class DirectorySidebarPane extends TreeView<DirFileModel> {
private static final DirectorySidebarPane INSTANCE = new DirectorySidebarPane();
private DirectorySidebarPane() {
this.setVisible(false);
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getClickCount() == 2) {
TreeItem<DirFileModel> item = DirectorySidebarPane.this.getSelectionModel().getSelectedItem();
if (Objects.isNull(item)) return;
File file = new File(item.getValue().getPath());
if(!file.isFile()){
return;
}
new OpenFile().openFile(file);
}
}
});
}
public static DirectorySidebarPane getInstance() {
return INSTANCE;
}
}

View File

@ -23,15 +23,23 @@ public class SidebarToolBar extends javafx.scene.control.ToolBar {
*/ */
Button setButton = new Button(); Button setButton = new Button();
/**
* 工具栏上的文件树
*/
Button dirTreeButton = new Button();
/** /**
* 工具栏上的文本侧边栏按钮 * 工具栏上的文本侧边栏按钮
*/ */
Button fileButton = new Button(); Button fileButton = new Button();
private SidebarToolBar() { private SidebarToolBar() {
// 垂直排列
this.setOrientation(Orientation.VERTICAL); this.setOrientation(Orientation.VERTICAL);
} }
/** /**
* 获取 JNotepadToolBar 的单例实例 * 获取 JNotepadToolBar 的单例实例
* *
@ -49,12 +57,13 @@ public class SidebarToolBar extends javafx.scene.control.ToolBar {
public Button getSetButton() { public Button getSetButton() {
return setButton; return setButton;
} }
/** /**
* 获取工具栏上的文件侧边栏按钮 * 获取工具栏上的文件按钮
* *
* @return 文件侧边栏按钮 * @return 文件按钮
*/ */
public Button getFileButton() { public Button getDirTreeButton() {
return fileButton; return dirTreeButton;
} }
} }

View File

@ -0,0 +1,35 @@
package org.jcnc.jnotepad.views.root.left.sidebar.tools;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.jcnc.jnotepad.ui.module.AbstractVerticalBox;
/**
* @author : cccqyu
* @createTime 2023/10/2 20:40
* @description 垂直布局
*/
public class ToolVerticalBox extends AbstractVerticalBox {
/**
* 单例模式保证只有一个 ToolVBox 实例
*/
private static final ToolVerticalBox INSTANCE = new ToolVerticalBox();
private ToolVerticalBox() {
// 设置子节点垂直拉伸
VBox.setVgrow(SidebarToolBar.getInstance(), Priority.ALWAYS);
// JNotepadToolBar 添加为子节点
getChildren().add(SidebarToolBar.getInstance());
getStyleClass().add("tool-vertical-box");
}
/**
* 获取 ToolVBox 的单例实例
*
* @return ToolVBox 的单例实例
*/
public static ToolVerticalBox getInstance() {
return INSTANCE;
}
}

View File

@ -59,6 +59,10 @@ public class TopMenuBar extends MenuBar {
* 打开 * 打开
*/ */
private final MenuItem openItem = new MenuItem(); private final MenuItem openItem = new MenuItem();
/**
* 打开文件夾
*/
private final MenuItem openDirItem = new MenuItem();
/** /**
* 另存为 * 另存为
*/ */
@ -198,4 +202,8 @@ public class TopMenuBar extends MenuBar {
public MenuItem getPluginManagerItem() { public MenuItem getPluginManagerItem() {
return pluginManagerItem; return pluginManagerItem;
} }
public MenuItem getOpenDirItem() {
return openDirItem;
}
} }

View File

@ -19,7 +19,11 @@
-fx-border-width: 0 1 0 0; -fx-border-width: 0 1 0 0;
-fx-border-color: -color-border-default; -fx-border-color: -color-border-default;
} }
/*左侧边栏*/
.tool-horizontal-box {
-fx-border-width: 0 1 0 0;
-fx-border-color: -color-border-default;
}
.paragraph-box .has-caret { .paragraph-box .has-caret {
-fx-background-color: -color-neutral-muted -fx-background-color: -color-neutral-muted

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -9,6 +9,7 @@ PLUGIN=插件
CHINESE=中文 CHINESE=中文
title=JNotepad title=JNotepad
OPEN=打开 OPEN=打开
OPEN_DIRECTORY=打开文件夹
ABOUT=关于 ABOUT=关于
HELP=帮助 HELP=帮助
OPEN_CONFIGURATION_FILE=打开配置文件 OPEN_CONFIGURATION_FILE=打开配置文件

View File

@ -10,6 +10,7 @@ PLUGIN=Plugins
CHINESE=Chinese CHINESE=Chinese
title=JNotepad title=JNotepad
OPEN=Open OPEN=Open
OPEN_DIRECTORY=Open Directory
HELP=Help HELP=Help
OPEN_CONFIGURATION_FILE=Open Configuration File OPEN_CONFIGURATION_FILE=Open Configuration File
RENAME=Rename RENAME=Rename

View File

@ -9,6 +9,7 @@ PLUGIN=插件
CHINESE=中文 CHINESE=中文
title=JNotepad title=JNotepad
OPEN=打开 OPEN=打开
OPEN_DIRECTORY=打开文件夹
HELP=帮助 HELP=帮助
ABOUT=关于 ABOUT=关于
OPEN_CONFIGURATION_FILE=打开配置文件 OPEN_CONFIGURATION_FILE=打开配置文件