♻️ ️ 优化性能重构并优化标签页右键菜单

This commit is contained in:
gewuyou 2023-10-14 18:33:29 +08:00
parent fb486a87ba
commit 694cd2a448
50 changed files with 616 additions and 637 deletions

View File

@ -1,138 +0,0 @@
package org.jcnc.jnotepad.api.core.component.stage;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.*;
/**
* 抽象菜单建造者类
*
* <p>
* 该抽象类用于构建菜单包括菜单项单选菜单项复选菜单项分割线等
* 子类应继承此类以实现具体的菜单构建逻辑
* </p>
*
* @param <B> 建造者类型
* @param <T> 构建结果类型
*
* @author gewuyou
*/
public abstract class AbstractMenuBuilder<B, T> {
/**
* 获取子类的建造者实例
*
* @return 建造者实例
*/
protected abstract B getBuilder();
/**
* 获取菜单的菜单项列表
*
* @return 菜单项列表
*/
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);
getItems().add(menuItem);
return getBuilder();
}
/**
* 添加菜单项
*
* @param label 菜单项名称
* @param eventHandler 事件处理器
* @param disable 是否禁用
* @return 当前建造者实例
*/
public B addMenuItem(String label, EventHandler<ActionEvent> eventHandler, boolean disable) {
if (!disable) {
return getBuilder();
}
MenuItem menuItem = new MenuItem(label);
menuItem.setOnAction(eventHandler);
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);
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);
getItems().add(menuItem);
return getBuilder();
}
/**
* 添加菜单
*
* @param menu 菜单
* @return 当前建造者实例
*/
public B addMenu(Menu menu) {
getItems().add(menu);
return getBuilder();
}
/**
* 添加菜单
*
* @param menu 菜单
* @param disable 是否禁用
* @return 当前建造者实例
*/
public B addMenu(Menu menu, boolean disable) {
if (!disable) {
return getBuilder();
}
getItems().add(menu);
return getBuilder();
}
/**
* 添加分割线
*
* @return 当前建造者实例
*/
public B addSeparatorMenuItem() {
getItems().add(new SeparatorMenuItem());
return getBuilder();
}
/**
* 构建菜单
*
* @return 构建的菜单
*/
public abstract T build();
}

View File

@ -22,7 +22,6 @@ import java.nio.file.Paths;
* </p>
*
* @param <T> 配置文件类型
*
* @author gewuyou
*/
public abstract class BaseConfigController<T> implements ConfigController<T> {
@ -30,9 +29,8 @@ public abstract class BaseConfigController<T> implements ConfigController<T> {
protected static final String ROOT_CONFIG_DIR = "config";
protected static final String SYSTEM_CONFIG_DIR = "system";
protected T config;
private final Logger logger = LogUtil.getLogger(getClass());
protected T config;
/**
* 获取配置文件Class类

View File

@ -1,14 +1,11 @@
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.controller.config.UserConfigController;
import org.jcnc.jnotepad.ui.views.root.top.menubar.TopMenuBar;
import java.util.HashMap;
import java.util.Map;
/**
* 抽象基础菜单类
*
@ -20,7 +17,6 @@ import java.util.Map;
*/
public abstract class AbstractBaseMenu extends AbstractMenu<Menu> {
protected final TopMenuBar topMenuBar = TopMenuBar.getInstance();
protected final UserConfigController userConfigController = UserConfigController.getInstance();
/**
* 获取菜单名称
@ -30,23 +26,13 @@ public abstract class AbstractBaseMenu extends AbstractMenu<Menu> {
public abstract String getMenuName();
/**
* 初始化菜单项
* 获取菜单项
*
* @param menuItems 菜单项集合
* @param menu 菜单
* @return 菜单项集合
*/
@Override
protected void initMenuItems(Map<String, MenuItem> menuItems, Menu menu) {
logger.info("初始化菜单项!");
Map<String, MenuItem> menuItemMap = new HashMap<>(16);
// 本地化
menuItems.forEach((key, value) -> {
UiResourceBundle.bindStringProperty(value.textProperty(), key);
menuItemMap.put((String) value.getUserData(), value);
menu.getItems().add(value);
});
userConfigController.getMenuItems().add(menuItemMap);
userConfigController.initShortcutKeys(menuItemMap);
protected ObservableList<MenuItem> getItems() {
return getMenu().getItems();
}
/**
@ -60,6 +46,6 @@ public abstract class AbstractBaseMenu extends AbstractMenu<Menu> {
// 菜单名称国际化
UiResourceBundle.bindStringProperty(menu.textProperty(), getMenuName());
// 初始化菜单项
initMenuItems(getMenuItems(), menu);
initMenuItems(getMenuItems());
}
}

View File

@ -1,15 +1,18 @@
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.app.utils.LogUtil;
import org.jcnc.jnotepad.controller.config.UserConfigController;
import org.slf4j.Logger;
import java.util.HashMap;
import java.util.Map;
/**
@ -19,6 +22,7 @@ import java.util.Map;
*/
public abstract class AbstractMenu<T> {
protected Logger logger = LogUtil.getLogger(this.getClass());
UserConfigController userConfigController = UserConfigController.getInstance();
/**
* 获取菜单
@ -44,6 +48,13 @@ public abstract class AbstractMenu<T> {
*/
protected abstract void initMenu();
/**
* 获取菜单项
*
* @return 菜单项集合
*/
protected abstract ObservableList<MenuItem> getItems();
/**
* 注册菜单项
@ -59,20 +70,6 @@ public abstract class AbstractMenu<T> {
menuItem.setOnAction(eventHandler);
}
/**
* 注册菜单项
*
* @param menuItem 菜单项
* @param menuItemName 菜单项名称
* @param userData 用户数据用来存放必要的数据比如按钮菜单项名称
* @param eventHandler 事件处理器
*/
public void registerMenuItem(MenuItem menuItem, String menuItemName, Object userData, EventHandler<ActionEvent> eventHandler, boolean isDisable) {
if (!isDisable) {
registerMenuItem(menuItem, menuItemName, userData, eventHandler);
}
}
/**
* 注册检查菜单项
*
@ -87,32 +84,6 @@ public abstract class AbstractMenu<T> {
checkMenuItem.selectedProperty().addListener(listener);
}
/**
* 在给定菜单映射中注册具有指定名称用户数据和事件处理程序的菜单项
*
* @param menu 菜单项映射
* @param menuItemName 要注册的菜单项的名称
* @param userData 与菜单项关联的用户数据
*/
public void registerMenu(Menu menu, String menuItemName, Object userData) {
getMenuItems().put(menuItemName, menu);
menu.setUserData(userData);
}
/**
* Registers a menu item in the specified menu with the given name and user data.
*
* @param menu the menu to register the item in
* @param menuItemName the name of the menu item
* @param userData the user data associated with the menu item
* @param isDisable whether the menu item is disabled
*/
public void registerMenu(Menu menu, String menuItemName, Object userData, boolean isDisable) {
if (!isDisable) {
registerMenu(menu, menuItemName, userData);
}
}
/**
* 注册单选菜单项
*
@ -127,12 +98,22 @@ public abstract class AbstractMenu<T> {
radioMenuItem.setOnAction(eventHandler);
}
/**
* 初始化菜单项
*
* @param menuItems 菜单项集合
* @param menu 菜单
*/
protected abstract void initMenuItems(Map<String, MenuItem> menuItems, T menu);
protected void initMenuItems(Map<String, MenuItem> menuItems) {
logger.info("初始化菜单项!");
Map<String, MenuItem> menuItemMap = new HashMap<>(16);
menuItems.forEach((key, value) -> {
UiResourceBundle.bindStringProperty(value.textProperty(), key);
menuItemMap.put((String) value.getUserData(), value);
getItems().add(value);
});
userConfigController.getMenuItems().add(menuItemMap);
userConfigController.initShortcutKeys(menuItemMap);
}
}

View File

@ -1,9 +1,15 @@
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;
/**
* 抽象菜单建造者类
@ -11,6 +17,11 @@ import javafx.scene.control.*;
* @author gewuyou
*/
public abstract class AbstractMenuBuilder<B, T> {
/**
* 上下文菜单项
*/
protected final Map<String, MenuItem> menuItems = new HashMap<>();
/**
* Get subclass builder
*
@ -18,6 +29,13 @@ public abstract class AbstractMenuBuilder<B, T> {
*/
protected abstract B getBuilder();
/**
* 获取菜单
*
* @return 菜单
*/
protected abstract T getMenu();
/**
* Retrieves the items of the menu.
*
@ -35,6 +53,7 @@ public abstract class AbstractMenuBuilder<B, T> {
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();
}
@ -44,15 +63,15 @@ public abstract class AbstractMenuBuilder<B, T> {
*
* @param label 菜单项名称
* @param eventHandler 事件
* @param disable 是否禁用
* @param visible 是否可见
* @return 建造者
*/
public B addMenuItem(String label, EventHandler<ActionEvent> eventHandler, boolean disable) {
if (!disable) {
return getBuilder();
}
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();
}
@ -67,6 +86,7 @@ public abstract class AbstractMenuBuilder<B, T> {
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();
}
@ -81,10 +101,19 @@ public abstract class AbstractMenuBuilder<B, T> {
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();
}
/**
* 添加菜单
*
@ -92,6 +121,7 @@ public abstract class AbstractMenuBuilder<B, T> {
* @return 建造者
*/
public B addMenu(Menu menu) {
menuItems.put(menu.getText(), menu);
getItems().add(menu);
return getBuilder();
}
@ -100,17 +130,18 @@ public abstract class AbstractMenuBuilder<B, T> {
* 添加菜单
*
* @param menu 菜单
* @param disable 是否禁用
* @param visible 是否隐藏
* @return 建造者
*/
public B addMenu(Menu menu, boolean disable) {
if (!disable) {
return getBuilder();
}
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();
}
/**
* 添加分割线
*
@ -121,11 +152,35 @@ public abstract class AbstractMenuBuilder<B, T> {
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();
}
/**
* Build menu
*
* @return menu
*/
public abstract T build();
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();
}
}

View File

@ -1,7 +1,9 @@
package org.jcnc.jnotepad.api.core.views.menu.builder;
import javafx.beans.property.BooleanProperty;
import javafx.collections.ObservableList;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
/**
@ -12,28 +14,15 @@ import javafx.scene.control.MenuItem;
* </p>
*
* @author gewuyou
*
*/
public class ContextMenuBuilder extends AbstractMenuBuilder<ContextMenuBuilder, ContextMenu> {
private final ContextMenu contextMenu;
/**
* 构造上下文菜单建造者
*/
public ContextMenuBuilder() {
contextMenu = new ContextMenu();
}
/**
* 构建并返回上下文菜单对象
*
* @return 构建的上下文菜单对象
*/
@Override
public ContextMenu build() {
return contextMenu;
}
/**
* 获取子类的建造者实例
*
@ -44,6 +33,16 @@ public class ContextMenuBuilder extends AbstractMenuBuilder<ContextMenuBuilder,
return this;
}
/**
* 获取菜单
*
* @return 菜单
*/
@Override
protected ContextMenu getMenu() {
return contextMenu;
}
/**
* 获取上下文菜单的菜单项列表
*
@ -53,4 +52,19 @@ public class ContextMenuBuilder extends AbstractMenuBuilder<ContextMenuBuilder,
protected ObservableList<MenuItem> getItems() {
return contextMenu.getItems();
}
/**
* 添加菜单
*
* @param menu 菜单
* @param visible 是否隐藏
* @return 建造者
*/
@Override
public ContextMenuBuilder addMenu(Menu menu, BooleanProperty visible) {
menu.setVisible(visible.get());
visible.addListener((observable, oldValue, newValue) -> menu.setVisible(Boolean.TRUE.equals(newValue)));
getItems().add(menu);
return getBuilder();
}
}

View File

@ -12,11 +12,12 @@ import javafx.scene.control.MenuItem;
* </p>
*
* @author gewuyou
*
*/
public class MenuBuilder extends AbstractMenuBuilder<MenuBuilder, Menu> {
private final Menu menu;
/**
* 构造菜单建造者
*
@ -36,6 +37,16 @@ public class MenuBuilder extends AbstractMenuBuilder<MenuBuilder, Menu> {
return this;
}
/**
* 获取菜单
*
* @return 菜单
*/
@Override
protected Menu getMenu() {
return menu;
}
/**
* 获取菜单的菜单项列表
*
@ -46,13 +57,4 @@ public class MenuBuilder extends AbstractMenuBuilder<MenuBuilder, Menu> {
return menu.getItems();
}
/**
* 构建菜单
*
* @return 构建的菜单对象
*/
@Override
public Menu build() {
return menu;
}
}

View File

@ -13,7 +13,6 @@ import org.jcnc.jnotepad.ui.views.root.bottom.function.FunctionBox;
* </p>
*
* @author gewuyou
*
*/
public abstract class AbstractFunctionChildrenBox {
protected final FunctionBox functionBox;

View File

@ -169,6 +169,81 @@ public class TextConstants {
*/
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() {
}

View File

@ -19,13 +19,8 @@ import static org.jcnc.jnotepad.app.common.constants.AppConstants.PROGRAM_FILE_D
* </p>
*
* @author gewuyou
*
*/
public class AppConfig {
/**
* 程序根路径
*/
private String rootPath;
/**
* 排除的文件夹
*/
@ -36,6 +31,10 @@ public class AppConfig {
*/
@JsonIgnore
private final Set<File> ignoreFile;
/**
* 程序根路径
*/
private String rootPath;
/**
* 上次的程序根路径
*/

View File

@ -12,7 +12,6 @@ import java.util.List;
* </p>
*
* @author gewuyou
*
*/
public class PluginConfig {
private List<PluginDescriptor> plugins;

View File

@ -13,7 +13,6 @@ import java.util.List;
* </p>
*
* @author luke
*
*/
public class UserConfig {

View File

@ -316,5 +316,9 @@ public class FileUtil {
}
return orDefault;
}
public static void openTerminal(File file) {
//todo @luke 请你在此设置打开文件所在文件夹路径于终端
}
}

View File

@ -28,6 +28,7 @@ import java.nio.charset.Charset;
import java.util.Comparator;
import java.util.List;
import static org.jcnc.jnotepad.app.common.constants.TextConstants.*;
import static org.jcnc.jnotepad.app.utils.FileUtil.getFileText;
import static org.jcnc.jnotepad.controller.config.UserConfigController.CONFIG_NAME;
@ -51,7 +52,7 @@ public class TabUtil {
return;
}
// 如果打开的是非关联文件则调用另存为方法
if (!tab.isRelevance()) {
if (!tab.getRelevanceProperty()) {
logger.info("当前保存文件为非关联打开文件,调用另存为方法");
saveAsFile(tab);
} else {
@ -99,7 +100,7 @@ public class TabUtil {
logger.info("正在保存文件: {}", file.getName());
tab.save(file);
// 将保存后的文件设置为关联文件
tab.setRelevance(true);
tab.setRelevanceProperty(true);
// 更新标签页上的文件名
tab.setText(file.getName());
}
@ -113,7 +114,7 @@ public class TabUtil {
return;
}
// 判断当前是否为关联文件
if (tab.isRelevance()) {
if (tab.getRelevanceProperty()) {
// 重命名关联文件
handleRenameRelevanceFile(tab);
}
@ -273,8 +274,6 @@ public class TabUtil {
CenterTab centerTab = new CenterTab(
tabTitle.toString(),
textArea);
// 设置当前标签页与本地文件无关联
centerTab.setRelevance(false);
// 将Tab页添加到TabPane中
CenterTabPaneManager.getInstance().addNewTab(centerTab);
// 更新编码信息
@ -317,11 +316,8 @@ public class TabUtil {
String fileText = getFileText(file, encoding);
LogUtil.getLogger(OpenFile.class).info("已调用读取文件功能");
textCodeArea.appendText(fileText);
CenterTab tab = new CenterTab(file.getName(), textCodeArea, encoding);
// 设置当前标签页关联本地文件
tab.setRelevance(true);
// 设置标签页关联文件
tab.setUserData(file);
// 设置当前标签页关联本地文件 设置标签页关联文件
CenterTab tab = new CenterTab(file.getName(), textCodeArea, encoding, file, true);
// 设置关联文件最后的修改时间
tab.setLastModifiedTimeOfAssociatedFile(file.lastModified());
CenterTabPaneManager.getInstance().addNewTab(tab);
@ -332,76 +328,69 @@ public class TabUtil {
*
* @param tab The tab for which the context menu is being updated.
*/
public static void updateTabContextMenu(CenterTab tab) {
public static void initTabContextMenu(CenterTab tab) {
ContextMenuBuilder builder = new ContextMenuBuilder();
CenterTabPaneManager centerTabPaneManager = CenterTabPaneManager.getInstance();
File file = (File) tab.getUserData();
//todo 设置上下文菜单
// 设置上下文菜单
tab.setContextMenu(
builder
.addMenuItem(
"关闭",
CLOSE,
e -> centerTabPaneManager.removeTab(tab))
.addMenuItem(
"关闭其它标签页",
CLOSE_OTHER_TABS,
e -> centerTabPaneManager.removeOtherTabs(tab),
centerTabPaneManager.hasOtherTabs()
tab.hasOtherTabsPropertyProperty()
)
.addMenuItem(
"关闭所有标签页",
CLOSE_ALL_TABS,
e -> centerTabPaneManager.removeAllTabs())
.addMenuItem(
"关闭左侧标签页",
CLOSE_LEFT_TABS,
e -> centerTabPaneManager.removeLeftTabs(tab),
centerTabPaneManager.hasLeftTabs(tab)
tab.hasLeftTabsPropertyProperty()
)
.addMenuItem(
"关闭右侧标签页",
CLOSE_RIGHT_TABS,
e -> centerTabPaneManager.removeRightTabs(tab),
centerTabPaneManager.hasRightTabs(tab)
tab.hasRightTabsPropertyProperty()
)
.addSeparatorMenuItem()
.addSeparatorMenuItem(tab.relevancePropertyProperty())
.addMenu(
new MenuBuilder("复制")
.addMenuItem("文件名", e -> {
new MenuBuilder(COPY)
.addMenuItem(FILE_NAME, e -> {
ClipboardUtil.writeTextToClipboard(file.getName());
NotificationUtil.infoNotification("已复制文件名!");
}, tab.isRelevance())
.addMenuItem("文件路径", e -> {
})
.addMenuItem(FILE_PATH, e -> {
ClipboardUtil.writeTextToClipboard(file.getAbsolutePath());
NotificationUtil.infoNotification("已复制文件路径!");
}, tab.isRelevance())
.addMenuItem("所在文件夹", e -> {
})
.addMenuItem(FOLDER_PATH, e -> {
ClipboardUtil.writeTextToClipboard(file.getParent());
NotificationUtil.infoNotification("已复制所在文件夹!");
}, tab.isRelevance())
})
.build()
, tab.relevancePropertyProperty()
)
.addSeparatorMenuItem()
.addMenuItem("保存", e -> saveFile(tab))
.addMenuItem("另存为", e -> saveAsFile(tab), tab.isRelevance())
.addMenuItem("重命名", e -> rename(tab))
.addSeparatorMenuItem()
.addMenu(new MenuBuilder("打开于")
.addMenuItem("资源管理器", e -> FileUtil.openExplorer(file))
.addMenuItem("终端", e -> {
.addMenuItem(SAVE, e -> saveFile(tab))
.addMenuItem(SAVE_AS, e -> saveAsFile(tab), tab.relevancePropertyProperty())
.addMenuItem(RENAME, e -> rename(tab))
.addSeparatorMenuItem(tab.relevancePropertyProperty())
.addMenu(new MenuBuilder(OPEN_ON)
.addMenuItem(EXPLORER, e -> FileUtil.openExplorer(file))
.addMenuItem(TERMINAL, e -> {
//todo @luke 请你在此设置打开文件所在文件夹路径于终端
})
.build(), tab.isRelevance())
.build(), tab.relevancePropertyProperty())
.addSeparatorMenuItem()
.addMenuItem("固定标签页",
e -> centerTabPaneManager.updateTabPinnedState(tab),
!tab.isFixed())
.addMenuItem("取消固定",
e -> centerTabPaneManager.updateTabPinnedState(tab),
tab.isFixed())
.addCheckMenuItem(FIXED_TAB,
e -> centerTabPaneManager.updateTabPinnedState(tab))
.addSeparatorMenuItem()
.addMenuItem("只读",
e -> centerTabPaneManager.updateReadOnlyProperty(tab),
tab.getTextCodeArea().isEditable())
.addMenuItem("取消只读",
e -> centerTabPaneManager.updateReadOnlyProperty(tab),
!tab.getTextCodeArea().isEditable())
.addCheckMenuItem(tab.getReadOnly(),
e -> centerTabPaneManager.updateReadOnlyProperty(tab))
.build());
}
}

View 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 = LogUtil.getLogger(this.getClass());
private String cacheDir;
private CacheController() {

View File

@ -15,17 +15,11 @@ import static org.jcnc.jnotepad.app.common.constants.AppConstants.PROGRAM_FILE_D
*/
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() {
@ -33,6 +27,10 @@ public class AppConfigController extends BaseConfigController<AppConfig> {
loadConfig();
}
public static AppConfigController getInstance() {
return INSTANCE;
}
/**
* 获取配置文件Class类
*

View File

@ -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;
}
/**
* 获取插件路径
*

View File

@ -34,11 +34,9 @@ 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 String configDir;
private final List<Map<String, MenuItem>> menuItems = new ArrayList<>();
Logger logger = LogUtil.getLogger(this.getClass());
private String configDir;
private UserConfigController() {
configDir = Paths.get(AppConfigController.getInstance().getConfig().getRootPath(), PROGRAM_FILE_DIRECTORY, ROOT_CONFIG_DIR).toString();

View 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) {
// 获取缓存

View File

@ -8,7 +8,6 @@ import org.jcnc.jnotepad.ui.views.manager.BuildPanelManager;
/**
* 终端处理器
*
*
* @author cccqyu
*/
public class RunBtn implements EventHandler<ActionEvent> {

View File

@ -34,16 +34,15 @@ public class PluginManager {
* 插件类别
*/
private final Map<String, List<String>> categories = new HashMap<>();
Logger logger = LogUtil.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() {

View File

@ -48,6 +48,10 @@ public class DirFileModel {
return childFile;
}
public void setChildFile(List<DirFileModel> childFile) {
this.childFile = childFile;
}
public String getPath() {
return path;
}
@ -77,16 +81,11 @@ public class DirFileModel {
this.iconIsNotSelected = iconIsNotSelected;
}
public void setIconIsSelected(Node iconIsSelected) {
this.iconIsSelected = iconIsSelected;
}
public Node getIconIsSelected() {
return iconIsSelected;
}
public void setChildFile(List<DirFileModel> childFile) {
this.childFile = childFile;
public void setIconIsSelected(Node iconIsSelected) {
this.iconIsSelected = iconIsSelected;
}
}

View File

@ -52,8 +52,6 @@ public class TextCodeArea extends CodeArea {
"//[^\n]*" + "|" + "/\\*(.|\\R)*?\\*/"
// 用于可见段落处理逐行
+ "|" + "/\\*\\V*" + "|" + "^\\h*\\*(\\V*|/)";
/**
* 使用正则表达式将关键字括号分号字符串和注释的模式组合成一个复合模式
*/
@ -110,22 +108,6 @@ public class TextCodeArea extends CodeArea {
this.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/jcnc/app/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"));
@ -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();
}
}

View File

@ -13,33 +13,18 @@ import org.jcnc.jnotepad.ui.component.module.vbox.components.RunBox;
*
* <p>可以通过调用getInstance方法获取单例实例</p>
*
* @author cccqyu
* @see CmdTerminalBox
* @see RunBox
* @see DebugBox
* @see TabPane
* @author cccqyu
*/
public class BuildPanel extends TabPane {
private static BuildPanel instance = null;
/**
* 获取BuildPanel的单例实例
*
* @return BuildPanel的单例实例
*/
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();
@ -56,6 +41,19 @@ public class BuildPanel extends TabPane {
this.getTabs().addAll(runTab, buildTab, cmdTab);
}
/**
* 获取BuildPanel的单例实例
*
* @return BuildPanel的单例实例
*/
public static BuildPanel getInstance() {
if (instance == null) {
instance = new BuildPanel();
}
return instance;
}
/**
* 获取命令终端组件
*

View File

@ -36,6 +36,7 @@ public class CmdTerminalBox extends VBox {
* 用户输入命令的文本框
*/
private final TextField cmdInput;
String currentDirectory;
/**
* 用于运行命令的进程
*/
@ -45,8 +46,6 @@ public class CmdTerminalBox extends VBox {
*/
private PrintWriter cmdInputWriter;
String currentDirectory;
/**
* 创建CmdTerminal对象的构造函数
*/

View File

@ -23,8 +23,8 @@ public interface DirectoryChooserFactory {
/**
* 创建详细的文件选择对话框
*
* @param title 对话框标题
* @param directory 初始目录
* @param title 对话框标题
* @param directory 初始目录
* @return javafx.stage.FileChooser 详细文件选择对话框对象
*/
DirectoryChooser createDirectoryChooser(String title, File directory);

View File

@ -37,14 +37,14 @@ public class BasicDirectoryChooserFactory implements DirectoryChooserFactory {
/**
* 创建详细的文件选择对话框
*
* @param title 对话框标题
* @param directory 初始目录
* @param title 对话框标题
* @param directory 初始目录
* @return javafx.stage.FileChooser 详细文件选择对话框对象
*/
@Override
public DirectoryChooser createDirectoryChooser(String title, File directory) {
DirectoryChooser directoryChooser= createDirectoryChooser();
DirectoryChooser directoryChooser = createDirectoryChooser();
// 设置窗口名称
directoryChooser.setTitle(title);

View File

@ -10,6 +10,7 @@ import org.jcnc.jnotepad.ui.component.stage.dialog.AppDialogStage;
public interface DialogButtonAction {
/**
* 处理按钮的操作子类必须实现此方法以定义按钮的行为
*
* @param appDialogStage 对话框
* @apiNote
* @since 2023/9/3 22:53

View File

@ -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;
/**
* 私有构造方法以实现单例模式

View File

@ -53,27 +53,23 @@ import java.util.Map;
* @author luke
*/
public class PluginManagementPane extends AbstractPaneStage {
PluginManager pluginManager = PluginManager.getInstance();
/**
* 图标大小常量
*/
public static int ICON_SIZE = 40;
/**
* 日志记录器
*/
Logger logger = LogUtil.getLogger(this.getClass());
/**
* 自定义分割面板
*/
private CustomSplitPane customSplitPane;
/**
* 用于存储Tile与其内容节点的映射关系
*/
private final Map<Tile, Node> tileContentMap = new HashMap<>();
PluginManager pluginManager = PluginManager.getInstance();
/**
* 日志记录器
*/
Logger logger = LogUtil.getLogger(this.getClass());
/**
* 自定义分割面板
*/
private CustomSplitPane customSplitPane;
/**
* 创建一个插件管理面板的实例
@ -81,6 +77,7 @@ public class PluginManagementPane extends AbstractPaneStage {
public PluginManagementPane() {
initialize();
}
/**
* 初始化插件管理面板
*/

View File

@ -71,6 +71,14 @@ public class BottomStatusBoxManager {
registerChildren(statusLabel);
statusLabel.setText(getStatusBarFormattedText(0, 0, 1));
registerChildren(BOTTOM_STATUS_BOX.getEncodingLabel());
Button readOnlyButton = BOTTOM_STATUS_BOX.getReadOnlyButton();
BottomStatusBoxButtonBuilder builder = new BottomStatusBoxButtonBuilder(readOnlyButton);
FontIcon icon = FontIcon.of(UNLOCK);
registerChildren(builder
.setFontIcon(icon)
.setEventHandler(e -> CenterTabPaneManager.getInstance().updateReadOnlyProperty(CenterTabPaneManager.getInstance().getSelected()))
.build());
}
/**
@ -213,33 +221,16 @@ public class BottomStatusBoxManager {
* @param tabs the list of tabs in the center tab pane
*/
public void updateReadOnlyProperty(CenterTab tab, ObservableList<Tab> tabs) {
ObservableList<Node> children = BOTTOM_STATUS_BOX.getChildren();
Button readOnlyButton = BOTTOM_STATUS_BOX.getReadOnlyButton();
BottomStatusBoxButtonBuilder builder = new BottomStatusBoxButtonBuilder(readOnlyButton);
readOnlyButton.setVisible(!tabs.isEmpty());
FontIcon icon;
if (tab.getTextCodeArea().isEditable()) {
FontIcon icon = FontIcon.of(UNLOCK);
if (children.contains(readOnlyButton)) {
readOnlyButton.setGraphic(icon);
} else {
registerChildren(builder
.setFontIcon(icon)
.setEventHandler(e -> CenterTabPaneManager.getInstance().updateReadOnlyProperty(tab))
.build());
}
icon = FontIcon.of(UNLOCK);
readOnlyButton.setGraphic(icon);
} else {
FontIcon icon = FontIcon.of(LOCK);
if (children.contains(readOnlyButton)) {
readOnlyButton.setGraphic(icon);
} else {
registerChildren(builder
.setFontIcon(icon)
.setEventHandler(e -> CenterTabPaneManager.getInstance().updateReadOnlyProperty(tab))
.build());
}
}
if (tabs.isEmpty()) {
children.remove(readOnlyButton);
icon = FontIcon.of(LOCK);
readOnlyButton.setGraphic(icon);
}
tab.getReadOnly().setSelected(!tab.getTextCodeArea().isEditable());
}
}

View File

@ -13,23 +13,21 @@ import org.jcnc.jnotepad.ui.views.root.center.main.MainBorderPane;
*/
public class BuildPanelManager {
private BuildPanelManager() {
}
/**
* 单例模式保证只有一个 BuildPanelManager 实例
*/
private static final BuildPanelManager INSTANCE = new BuildPanelManager();
private static final MainBorderPane MAIN_BORDER_PANE = MainBorderPane.getInstance();
private boolean isShow = false;
private BuildPanelManager() {
}
public static BuildPanelManager getInstance() {
return INSTANCE;
}
private static final MainBorderPane MAIN_BORDER_PANE = MainBorderPane.getInstance();
private boolean isShow = false;
/**
* 控制终端显示
*/

View File

@ -1,5 +1,6 @@
package org.jcnc.jnotepad.ui.views.manager;
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.control.Tab;
@ -44,7 +45,10 @@ public class CenterTabPaneManager {
* 初始化标签页布局组件
*/
public void initCenterTabPane() {
initListeners();
Platform.runLater(() -> {
initListeners();
addTabsListener();
});
}
@ -79,7 +83,7 @@ public class CenterTabPaneManager {
if (tab == null) {
return;
}
if (tab.isRelevance()) {
if (tab.getRelevanceProperty()) {
// 获取当前文本域对象
TextCodeArea textCodeArea = tab.getTextCodeArea();
// 获取当前标签页对应文件上次修改时间
@ -115,9 +119,8 @@ public class CenterTabPaneManager {
}
// 将标签页加入标签页列表
centerTabPane.getTabs().add(tab);
// 设置索引
centerTabPane.getSelectionModel().select(tab);
// 将标签页设置为选中状态
// 异步刷新界面 将标签页设置为选中状态
Platform.runLater(() -> centerTabPane.getSelectionModel().select(tab));
fireTabSelected();
}
@ -187,7 +190,7 @@ public class CenterTabPaneManager {
if (centerTab.equals(currTab)) {
return false;
}
return !centerTab.isFixed() && !centerTab.equals(currTab);
return centerTab.getNotFixedProperty() && !centerTab.equals(currTab);
});
}
@ -204,7 +207,7 @@ public class CenterTabPaneManager {
if (tab.equals(centerTab)) {
return;
}
if (!tab.isFixed()) {
if (tab.getNotFixedProperty()) {
iterator.remove();
}
}
@ -225,96 +228,20 @@ public class CenterTabPaneManager {
flag = true;
continue;
}
if (flag && !tab.isFixed()) {
if (flag && tab.getNotFixedProperty()) {
iterator.remove();
}
}
}
/**
* 判断是否有其它标签页
*
* @return 是否有其它标签页
*/
public boolean hasOtherTabs() {
return centerTabPane.getTabs().size() > 1;
}
/**
* 判断是否有左侧标签页
*
* @param centerTab 标签页
* @apiNote 由于不知道怎么监听固定状态因此还是使用简单的判断如果能够监听固定状态时可以把代码修改为
* <blockquote><pre>
* public boolean hasLeftTabs(CenterTab centerTab) {
* ObservableList<Tab> tabs = centerTabPane.getTabs();
* int edge = tabs.indexOf(centerTab);
* if (edge == 0) {
* return false;
* }
* for (int i = 0; i < edge; i++) {
* CenterTab tab = (CenterTab) tabs.get(i);
* if (!tab.isFixed()) {
* return true;
* }
* }
* return false;
* }
* <blockquote><pre>
* @return 是否有左侧标签页
*/
public boolean hasLeftTabs(CenterTab centerTab) {
int index = centerTabPane.getTabs().indexOf(centerTab);
return index > 0;
}
/**
* 判断是否有右侧标签页
*
* @param centerTab 标签页
* @return 是否有右侧标签页
* @apiNote 由于不知道怎么监听固定状态因此还是使用简单的判断如果能够监听固定状态时可以把代码修改为
* <blockquote><pre>
* public boolean hasRightTabs(CenterTab centerTab) {
* ObservableList<Tab> tabs = centerTabPane.getTabs();
* for (int i = tabs.indexOf(centerTab)+1; i < tabs.size(); i++) {
* CenterTab tab = (CenterTab) tabs.get(i);
* if (!tab.isFixed()) {
* return true;
* }
* }
* return false;
* }
* </pre></blockquote>
*/
public boolean hasRightTabs(CenterTab centerTab) {
ObservableList<Tab> tabs = centerTabPane.getTabs();
int index = tabs.indexOf(centerTab);
return index != tabs.size() - 1;
}
/**
* Sets a listener for the tabs in the center tab pane.
*
* @param tab the tab to set the listener for
*/
public void setTabsListener(CenterTab tab) {
ObservableList<Tab> tabs = centerTabPane.getTabs();
tabs.addListener((ListChangeListener<Tab>) c -> {
tab.contextMenuMonitor();
BottomStatusBoxManager.getInstance().updateReadOnlyProperty(tab, tabs);
});
}
/**
* Updates the pinned state of the given center tab.
*
* @param tab the center tab to update
*/
public void updateTabPinnedState(CenterTab tab) {
tab.setFixed(!tab.isFixed());
tab.setClosable(!tab.isFixed());
tab.setFixedProperty(tab.getNotFixedProperty());
tab.setClosable(tab.getNotFixedProperty());
}
/**
@ -325,7 +252,57 @@ public class CenterTabPaneManager {
public void updateReadOnlyProperty(CenterTab tab) {
TextCodeArea textCodeArea = tab.getTextCodeArea();
textCodeArea.setEditable(!textCodeArea.isEditable());
tab.contextMenuMonitor();
BottomStatusBoxManager.getInstance().updateReadOnlyProperty(tab, centerTabPane.getTabs());
}
/**
* Adds a listener to the tabs in the center tab pane.
*/
private void addTabsListener() {
centerTabPane.getTabs().addListener((ListChangeListener<Tab>) change -> {
ObservableList<? extends Tab> list = change.getList();
list.forEach(tab -> {
CenterTab centerTab = (CenterTab) tab;
// 判断标签页
checkTabs(list, centerTab);
});
});
}
/**
* Checks the tabs in the given list and updates the properties of the centerTab accordingly.
*
* @param list the list of tabs to check
* @param centerTab the centerTab to update
*/
public void checkTabs(ObservableList<? extends Tab> list, CenterTab centerTab) {
int index = list.indexOf(centerTab);
boolean hasOther = false;
boolean hasLeft = false;
boolean hasRight = false;
int tabCount = list.size();
for (int i = 0; i < tabCount; i++) {
CenterTab temp = (CenterTab) list.get(i);
// 判断是否有其他标签页
if (!centerTab.equals(temp) && temp.getNotFixedProperty()) {
hasOther = true;
}
// 判断是否有左侧标签页
if (!centerTab.equals(temp) && i < index && temp.getNotFixedProperty()) {
hasLeft = true;
}
// 判断是否有右侧标签页
if (!centerTab.equals(temp) && i > index && temp.getNotFixedProperty()) {
hasRight = true;
}
}
centerTab.setHasOtherTabsProperty(hasOther);
centerTab.setHasLeftTabsProperty(hasLeft);
centerTab.setHasRightTabsProperty(hasRight);
}
}

View File

@ -23,29 +23,49 @@ import java.util.List;
*/
public class DirectorySidebarManager {
private DirectorySidebarManager() {
}
private static final ApplicationCacheManager CACHE_MANAGER = ApplicationCacheManager.getInstance();
/**
* 单例模式保证只有一个 DirectorySidebar 实例
*/
private static final DirectorySidebarManager INSTANCE = new DirectorySidebarManager();
private static final MainBorderPane MAIN_BORDER_PANE = MainBorderPane.getInstance();
private static final DirectorySidebarPane DIRECTORY_SIDEBAR_PANE = DirectorySidebarPane.getInstance();
private static final double LAST_DIVIDER_POSITION = 0.3;
private static boolean isShow = false;
private DirectorySidebarManager() {
}
public static DirectorySidebarManager getInstance() {
return INSTANCE;
}
private static final MainBorderPane MAIN_BORDER_PANE = MainBorderPane.getInstance();
/**
* 设置文件树项监听事件
*
* @param item 文件树项
* @return 监听事件
*/
private static ChangeListener<Boolean> getTreeItemListener(TreeItem<DirFileModel> item) {
return (observable, oldValue, newValue) -> {
if (Boolean.TRUE.equals(newValue)) {
item.setGraphic(item.getValue().getIconIsSelected());
} else {
item.setGraphic(item.getValue().getIconIsNotSelected());
}
};
}
private static final DirectorySidebarPane DIRECTORY_SIDEBAR_PANE = DirectorySidebarPane.getInstance();
private static final double LAST_DIVIDER_POSITION = 0.3;
private static boolean isShow = false;
/**
* Check if the given `DirFileModel` represents a directory.
*
* @param childFile the `DirFileModel` to check
* @return `true` if the `childFile` represents a directory, `false` otherwise
*/
private static boolean isDirectoryByDirFileModel(DirFileModel childFile) {
return new File(childFile.getPath()).isDirectory();
}
/**
* 控制文件树显示
@ -83,22 +103,6 @@ public class DirectorySidebarManager {
}
}
/**
* 设置文件树项监听事件
*
* @param item 文件树项
* @return 监听事件
*/
private static ChangeListener<Boolean> getTreeItemListener(TreeItem<DirFileModel> item) {
return (observable, oldValue, newValue) -> {
if (Boolean.TRUE.equals(newValue)) {
item.setGraphic(item.getValue().getIconIsSelected());
} else {
item.setGraphic(item.getValue().getIconIsNotSelected());
}
};
}
/**
* 设置文件树内容
*
@ -112,16 +116,6 @@ public class DirectorySidebarManager {
expandFolder(dirFileModel, rootItem);
}
/**
* Check if the given `DirFileModel` represents a directory.
*
* @param childFile the `DirFileModel` to check
* @return `true` if the `childFile` represents a directory, `false` otherwise
*/
private static boolean isDirectoryByDirFileModel(DirFileModel childFile) {
return new File(childFile.getPath()).isDirectory();
}
/**
* 递归展开 dirFileModel
*

View File

@ -24,11 +24,11 @@ import org.jcnc.jnotepad.ui.views.root.RootBorderPane;
public class RootManager {
private static RootManager instance = null;
StackPane rootStackPane;
/**
* 主布局
*/
private final BorderPane root;
StackPane rootStackPane;
/**
* 私有构造函数设置场景和根布局
@ -67,23 +67,6 @@ public class RootManager {
}
}
/**
* 初始化屏幕组件
*
* @param scene 与视图相关联的 JavaFX 场景
*/
public void initScreen(Scene scene) {
rootStackPane = new StackPane();
// 创建主界面布局
root.setCenter(RootBorderPane.getInstance());
rootStackPane.getChildren().addAll(root);
scene.setRoot(rootStackPane);
}
/**
* 将提示框添加到 StackPane
*
@ -155,6 +138,22 @@ public class RootManager {
timeline.play();
}
/**
* 初始化屏幕组件
*
* @param scene 与视图相关联的 JavaFX 场景
*/
public void initScreen(Scene scene) {
rootStackPane = new StackPane();
// 创建主界面布局
root.setCenter(RootBorderPane.getInstance());
rootStackPane.getChildren().addAll(root);
scene.setRoot(rootStackPane);
}
public StackPane getRootStackPane() {
return rootStackPane;
}

View File

@ -19,11 +19,11 @@ import java.util.List;
*/
public class SidebarToolBarManager extends AbstractManager<Node> {
private static final SidebarToolBarManager INSTANCE = new SidebarToolBarManager();
private final List<Node> nodeList = new ArrayList<>();
/**
* 工具栏
*/
SidebarToolBar sidebarToolBar = SidebarToolBar.getInstance();
private final List<Node> nodeList = new ArrayList<>();
public static SidebarToolBarManager getInstance() {
return INSTANCE;

View File

@ -31,7 +31,7 @@ public class TopMenuBarManager extends AbstractManager<Menu> {
SettingTopMenu settingTopMenu = SettingTopMenu.getInstance();
RunTopMenu runTopMenu=RunTopMenu.getInstance();
RunTopMenu runTopMenu = RunTopMenu.getInstance();
PluginTopMenu pluginTopMenu = PluginTopMenu.getInstance();
HelpTopMenu helpTopMenu = HelpTopMenu.getInstance();

View File

@ -12,11 +12,16 @@ import org.jcnc.jnotepad.ui.component.module.base.AbstractVerticalBox;
*/
public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox();
/**
* VBox实例
*/
private final VBox vBox = new VBox();
private RootBottomSideBarVerticalBox() {
}
/**
* 获取 RootBottomSideBarVerticalBox 的唯一实例
*
@ -26,10 +31,6 @@ public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
return INSTANCE;
}
private RootBottomSideBarVerticalBox() {
}
/**
* 获取vbox实例
*
@ -39,6 +40,4 @@ public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
return vBox;
}
private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox();
}

View File

@ -1,7 +1,10 @@
package org.jcnc.jnotepad.ui.views.root.center.main.center.tab;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ObservableList;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Tab;
import org.fxmisc.flowless.VirtualizedScrollPane;
import org.jcnc.jnotepad.app.utils.FileUtil;
@ -19,6 +22,8 @@ import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import static org.jcnc.jnotepad.app.common.constants.TextConstants.READ_ONLY;
/**
* 封装标签页组件增加属于标签页的属性例如自动换行开关
* 每个Tab关联一个TextCodeArea
@ -26,55 +31,81 @@ import java.nio.charset.Charset;
* @author songdragon
*/
public class CenterTab extends Tab {
Logger logger = LogUtil.getLogger(this.getClass());
private final TextCodeArea textCodeArea;
/**
* 默认关闭自动换行
*/
private boolean autoLine = false;
/**
* 是否与本地文件关联
*/
private boolean isRelevance = false;
private final BooleanProperty relevanceProperty = new SimpleBooleanProperty(false);
/**
* 是否固定
*/
private final BooleanProperty isFixed = new SimpleBooleanProperty(false);
private final BooleanProperty fixedProperty = new SimpleBooleanProperty(false);
/**
* 只读菜单项
*/
private final CheckMenuItem readOnly = new CheckMenuItem(READ_ONLY);
private final BooleanProperty hasLeftTabsProperty = new SimpleBooleanProperty(false);
private final BooleanProperty hasRightTabsProperty = new SimpleBooleanProperty(false);
private final BooleanProperty hasOtherTabsProperty = new SimpleBooleanProperty(false);
Logger logger = LogUtil.getLogger(this.getClass());
/**
* 默认关闭自动换行
*/
private boolean autoLine;
/**
* 关联文件上次修改时间
*/
private Long lastModifiedTimeOfAssociatedFile;
private Charset charset = Charset.defaultCharset();
/**
* 编码
*/
private Charset charset;
public CenterTab(String tabTitle) {
this(tabTitle, new TextCodeArea());
}
public CenterTab(String tabTitle, TextCodeArea textArea) {
this(tabTitle, textArea, Charset.defaultCharset());
this(tabTitle, textArea, Charset.defaultCharset(), null, false);
}
public CenterTab(String tabTitle, TextCodeArea textArea, Charset charset) {
public CenterTab(String tabTitle, TextCodeArea textCodeArea, Charset charset, File file, boolean relevanceProperty) {
super(tabTitle);
// 在此根据标签页名称设置文件图标
this.setGraphic(FileUtil.getIconCorrespondingToFileName(tabTitle));
textCodeArea = textArea;
initTextAreaListeners();
this.setContent(new VirtualizedScrollPane<>(textCodeArea));
setAutoLine(UserConfigController.getInstance().getAutoLineConfig());
this.textCodeArea = textCodeArea;
this.setContent(new VirtualizedScrollPane<>(this.textCodeArea));
this.autoLine = UserConfigController.getInstance().getAutoLineConfig();
this.charset = charset;
// 绑定标签页监听
CenterTabPaneManager.getInstance().setTabsListener(this);
isFixed.addListener((observable, oldValue, newValue) -> this.contextMenuMonitor());
this.relevanceProperty.set(relevanceProperty);
this.setUserData(file);
// 将监听器于上下文菜单集中处理
Platform.runLater(() -> {
initTextAreaListeners();
this.contextMenuMonitor();
initFixedStateListener();
});
}
public boolean isRelevance() {
return isRelevance;
private void initFixedStateListener() {
fixedProperty.addListener((observable, oldValue, newValue) -> {
ObservableList<Tab> tabs = CenterTabPane.getInstance().getTabs();
tabs.forEach(tab -> CenterTabPaneManager.getInstance().checkTabs(tabs, (CenterTab) tab));
});
}
public void setRelevance(boolean relevance) {
isRelevance = relevance;
public boolean getRelevanceProperty() {
return relevanceProperty.get();
}
public void setRelevanceProperty(boolean relevanceProperty) {
this.relevanceProperty.set(relevanceProperty);
}
public BooleanProperty relevancePropertyProperty() {
return relevanceProperty;
}
public boolean isAutoLine() {
@ -102,7 +133,7 @@ public class CenterTab extends Tab {
* Monitors the context menu.
*/
public void contextMenuMonitor() {
TabUtil.updateTabContextMenu(this);
TabUtil.initTabContextMenu(this);
}
@ -144,7 +175,7 @@ public class CenterTab extends Tab {
}
/**
* 初始化监听器方法
* 初始化文本监听器方法
*/
private void initTextAreaListeners() {
// 监听主要文本区域的文本变化
@ -175,11 +206,42 @@ public class CenterTab extends Tab {
this.lastModifiedTimeOfAssociatedFile = lastModifiedTimeOfAssociatedFile;
}
public boolean isFixed() {
return isFixed.get();
public boolean getNotFixedProperty() {
return !fixedProperty.get();
}
public void setFixed(boolean fixed) {
isFixed.set(fixed);
public void setFixedProperty(boolean fixedProperty) {
this.fixedProperty.set(fixedProperty);
}
public BooleanProperty hasLeftTabsPropertyProperty() {
return hasLeftTabsProperty;
}
public BooleanProperty hasRightTabsPropertyProperty() {
return hasRightTabsProperty;
}
public BooleanProperty hasOtherTabsPropertyProperty() {
return hasOtherTabsProperty;
}
public CheckMenuItem getReadOnly() {
return readOnly;
}
public void setHasLeftTabsProperty(boolean hasLeftTabsProperty) {
this.hasLeftTabsProperty.set(hasLeftTabsProperty);
}
public void setHasRightTabsProperty(boolean hasRightTabsProperty) {
this.hasRightTabsProperty.set(hasRightTabsProperty);
}
public void setHasOtherTabsProperty(boolean hasOtherTabsProperty) {
this.hasOtherTabsProperty.set(hasOtherTabsProperty);
}
}

View File

@ -38,7 +38,7 @@ public class SidebarToolBar extends javafx.scene.control.ToolBar {
private SidebarToolBar() {
// 垂直排列
this.setOrientation(Orientation.VERTICAL);
this.setPadding(new Insets(1,5,0,0));
this.setPadding(new Insets(1, 5, 0, 0));
this.setOnMouseClicked(event -> {
// SidebarToolBar 点击事件
});

View File

@ -12,10 +12,6 @@ import org.jcnc.jnotepad.ui.views.root.center.main.center.tab.CenterTab;
public class TopMenuBar extends MenuBar {
private static final TopMenuBar MENU_BAR = new TopMenuBar();
/**
* 标签页布局组件封装
*/
CenterTabPaneManager centerTabPane = CenterTabPaneManager.getInstance();
/**
* 文件菜单
*/
@ -24,23 +20,20 @@ public class TopMenuBar extends MenuBar {
* 设置菜单
*/
private final Menu setMenu = new Menu();
/**
* 帮助菜单
*/
private final Menu helpMenu = new Menu();
/**
* 运行菜单
*/
private final Menu runMenu = new Menu();
/// 菜单按钮
/**
* 插件菜单
*/
private final Menu pluginMenu = new Menu();
/// 菜单按钮
/**
* 语言菜单
*/
@ -49,12 +42,10 @@ public class TopMenuBar extends MenuBar {
* 新建
*/
private final MenuItem newItem = new MenuItem();
/**
* 关于
*/
private final MenuItem aboutItem = new MenuItem();
/**
* 调试
*/
@ -64,9 +55,7 @@ public class TopMenuBar extends MenuBar {
*/
private final MenuItem runItem = new MenuItem();
private final MenuItem developerItem = new MenuItem();
/**
* 打开
*/
@ -87,7 +76,6 @@ public class TopMenuBar extends MenuBar {
* 重命名
*/
private final MenuItem renameItem = new MenuItem();
/**
* 查看
*/
@ -112,11 +100,14 @@ public class TopMenuBar extends MenuBar {
* 英文选项
*/
private final RadioMenuItem englishItem = new RadioMenuItem();
/**
* 插件管理菜单项
*/
private final MenuItem pluginManagerItem = new MenuItem();
/**
* 标签页布局组件封装
*/
CenterTabPaneManager centerTabPane = CenterTabPaneManager.getInstance();
private TopMenuBar() {
}

View File

@ -63,9 +63,9 @@ public class FileTopMenu extends AbstractBaseMenu {
// 文件菜单
registerMenuItem(topMenuBar.getNewItem(), NEW, "newItem", new NewFile());
registerMenuItem(topMenuBar.getOpenItem(), OPEN, "openItem", new OpenFile());
registerMenuItem(topMenuBar.getSaveItem(), SAVE, "saveItem", new SaveFile());
registerMenuItem(topMenuBar.getSaveAsItem(), SAVE_AS, "saveAsItem", new SaveAsFile());
registerMenuItem(topMenuBar.getRenameItem(), RENAME, "renameItem", new RenameFile());
registerMenuItem(topMenuBar.getSaveItem(), SAVE, SAVE.toLowerCase(), new SaveFile());
registerMenuItem(topMenuBar.getSaveAsItem(), SAVE_AS, SAVE_AS.toLowerCase(), new SaveAsFile());
registerMenuItem(topMenuBar.getRenameItem(), RENAME, RENAME.toLowerCase(), new RenameFile());
// 打开文件夹按钮
registerMenuItem(topMenuBar.getOpenDirItem(), OPEN_DIRECTORY, "openDirItem", new OpenDirectory());
}

View File

@ -28,6 +28,25 @@ public class RunTopMenu extends AbstractBaseMenu {
private static final BuildPanel BUILD_PANEL = BuildPanel.getInstance();
private static final RunTopMenu INSTANCE = new RunTopMenu();
private final Map<String, MenuItem> runMenuItems = new HashMap<>();
EventHandler<ActionEvent> codeRun = event -> {
// 获取TextCodeArea的文本内容
CenterTab centerTab = CenterTabPaneManager.getInstance().getSelected();
String code = centerTab.getTextCodeArea().getText();
String fileName = centerTab.getText();
// 将C代码写入临时文件
try (PrintWriter writer = new PrintWriter(new FileWriter(fileName))) {
writer.write(code);
} catch (IOException ex) {
LogUtil.getLogger(this.getClass()).info("正在写入:{}", code);
}
// 编译C代码
compileAndRunCode(fileName);
};
public static RunTopMenu getInstance() {
return INSTANCE;
@ -63,26 +82,6 @@ public class RunTopMenu extends AbstractBaseMenu {
return runMenuItems;
}
EventHandler<ActionEvent> codeRun = event -> {
// 获取TextCodeArea的文本内容
CenterTab centerTab = CenterTabPaneManager.getInstance().getSelected();
String code = centerTab.getTextCodeArea().getText();
String fileName = centerTab.getText();
// 将C代码写入临时文件
try (PrintWriter writer = new PrintWriter(new FileWriter(fileName))) {
writer.write(code);
} catch (IOException ex) {
LogUtil.getLogger(this.getClass()).info("正在写入:{}", code);
}
// 编译C代码
compileAndRunCode(fileName);
};
/**
* 编译和运行C代码的方法
*/

View File

@ -19,6 +19,7 @@
-fx-border-width: 0 1 0 0;
-fx-border-color: -color-border-default;
}
/*左侧边栏*/
.tool-horizontal-box {
-fx-border-width: 0 1 0 0;

View File

@ -39,9 +39,7 @@ CLOSE_LEFT_TABS=关闭左侧标签页
CLOSE_RIGHT_TABS=关闭右侧标签页
CLOSE_OTHER_TABS=关闭其他标签页
FIXED_TAB=固定标签页
UNFIXED_TAB=取消固定
READ_ONLY=只读
UNREAD_ONLY=取消只读
OPEN_ON=打开于

View File

@ -28,3 +28,16 @@ ROW=Row
FILE=File
MANAGER_PLUGIN=Manager Plugin
ENCODE=Encoding
COPY=Copy
FILE_NAME=File Name
FILE_PATH=File Path
FOLDER_PATH=Folder Path
EXPLORER=Explorer
CLOSE=Close
CLOSE_ALL_TABS=Close All Tabs
CLOSE_LEFT_TABS=Close Left Tabs
CLOSE_RIGHT_TABS=Close Right Tabs
CLOSE_OTHER_TABS=Close Other Tabs
FIXED_TAB=Fixed Tab
READ_ONLY=Read Only
OPEN_ON=Open On

View File

@ -28,3 +28,16 @@ ROW=行数
FILE=文件
MANAGER_PLUGIN=插件管理
ENCODE=编码
COPY=复制
FILE_NAME=文件名
FILE_PATH=文件路径
FOLDER_PATH=所在文件夹
EXPLORER=资源管理器
CLOSE=关闭
CLOSE_ALL_TABS=关闭所有标签页
CLOSE_LEFT_TABS=关闭左侧标签页
CLOSE_RIGHT_TABS=关闭右侧标签页
CLOSE_OTHER_TABS=关闭其他标签页
FIXED_TAB=固定标签页
READ_ONLY=只读
OPEN_ON=打开于