!118 ♻️ 重构代码 创建单例组件管理类,将单例组件初始化与单例组件分离

Merge pull request !118 from 格物方能致知/develop
This commit is contained in:
格物方能致知 2023-09-26 13:46:01 +00:00 committed by Gitee
commit 7ce8879e69
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
16 changed files with 374 additions and 263 deletions

View File

@ -17,9 +17,7 @@ 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;
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.*;
import org.jcnc.jnotepad.views.manager.SidebarToolBarManager;
import org.jcnc.jnotepad.views.manager.TopMenuBarManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.util.List; import java.util.List;
@ -65,11 +63,15 @@ public class ApplicationManager {
// 初始化scene // 初始化scene
initScene(); initScene();
// 初始化插件 // 初始化插件
PluginManager.getInstance().initializePlugins(); PluginManager.getInstance().initPlugins();
// 初始化顶部菜单栏 // 初始化顶部菜单栏
TopMenuBarManager.getInstance().initTopMenuBar(); TopMenuBarManager.getInstance().initTopMenuBar();
// 初始化侧边工具栏 // 初始化侧边工具栏
SidebarToolBarManager.getInstance().initSidebarToolBar(); SidebarToolBarManager.getInstance().initSidebarToolBar();
// 初始化下方状态栏
BottomStatusBoxManager.getInstance().initStatusBox();
// 初始标签页布局组件
CenterTabPaneManager.getInstance().initCenterTabPane();
// 初始化ui组件 // 初始化ui组件
initUiComponents(); initUiComponents();
// 初始化primaryStage // 初始化primaryStage
@ -159,6 +161,8 @@ public class ApplicationManager {
// 加载组件 // 加载组件
RootManager rootManager = RootManager.getInstance(scene); RootManager rootManager = RootManager.getInstance(scene);
rootManager.initScreen(scene); rootManager.initScreen(scene);
// 初始化底部根侧边栏垂直布局
RootBottomSideBarVerticalBoxManager.getInstance().initSidebarVerticalBox();
} }
public Pane getRoot() { public Pane getRoot() {
@ -187,6 +191,5 @@ public class ApplicationManager {
public void stopApplication() { public void stopApplication() {
Platform.exit(); Platform.exit();
// application.stop();
} }
} }

View File

@ -7,7 +7,8 @@ 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.ui.module.LineNumberTextArea; import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox; import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager;
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
@ -69,8 +70,8 @@ public class NewFile implements EventHandler<ActionEvent> {
// 设置当前标签页与本地文件无关联 // 设置当前标签页与本地文件无关联
centerTab.setRelevance(false); centerTab.setRelevance(false);
// 将Tab页添加到TabPane中 // 将Tab页添加到TabPane中
CenterTabPane.getInstance().addNewTab(centerTab); CenterTabPaneManager.getInstance().addNewTab(centerTab);
// 更新编码信息 // 更新编码信息
BottomStatusBox.getInstance().updateEncodingLabel(); BottomStatusBoxManager.getInstance().updateEncodingLabel();
} }
} }

View File

@ -14,6 +14,7 @@ import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
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;
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;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
@ -126,7 +127,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
// 设置当前标签页关联本地文件 // 设置当前标签页关联本地文件
tab.setRelevance(true); tab.setRelevance(true);
tab.setUserData(file); tab.setUserData(file);
CenterTabPane.getInstance().addNewTab(tab); CenterTabPaneManager.getInstance().addNewTab(tab);
}); });
} catch (IOException ignored) { } catch (IOException ignored) {
LogUtil.getLogger(this.getClass()).info("已忽视IO异常!"); LogUtil.getLogger(this.getClass()).info("已忽视IO异常!");

View File

@ -11,6 +11,7 @@ import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory;
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.jcnc.jnotepad.util.UiUtil; import org.jcnc.jnotepad.util.UiUtil;
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -31,7 +32,7 @@ public class RenameFile implements EventHandler<ActionEvent> {
@Override @Override
public void handle(ActionEvent actionEvent) { public void handle(ActionEvent actionEvent) {
// 获取当前标签页 // 获取当前标签页
CenterTab centerTab = CenterTabPane.getInstance().getSelected(); CenterTab centerTab = CenterTabPaneManager.getInstance().getSelected();
if (centerTab == null || centerTab.getText().isEmpty()) { if (centerTab == null || centerTab.getText().isEmpty()) {
return; return;
} }

View File

@ -10,9 +10,9 @@ import org.jcnc.jnotepad.controller.i18n.LocalizationController;
import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory; import org.jcnc.jnotepad.ui.dialog.factory.impl.BasicFileChooserFactory;
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.TopMenuBarManager; import org.jcnc.jnotepad.views.manager.TopMenuBarManager;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.io.File; import java.io.File;
@ -40,7 +40,7 @@ public class SaveFile implements EventHandler<ActionEvent> {
@Override @Override
public void handle(ActionEvent actionEvent) { public void handle(ActionEvent actionEvent) {
// 获取当前tab页 // 获取当前tab页
CenterTab selectedTab = CenterTabPane.getInstance().getSelected(); CenterTab selectedTab = CenterTabPaneManager.getInstance().getSelected();
if (selectedTab == null) { if (selectedTab == null) {
return; return;
} }
@ -72,7 +72,7 @@ public class SaveFile implements EventHandler<ActionEvent> {
* @see LogUtil * @see LogUtil
*/ */
protected void saveTab(Class<?> currentClass) { protected void saveTab(Class<?> currentClass) {
CenterTab selectedTab = CenterTabPane.getInstance().getSelected(); CenterTab selectedTab = CenterTabPaneManager.getInstance().getSelected();
if (selectedTab == null) { if (selectedTab == null) {
return; return;
} }

View File

@ -113,7 +113,7 @@ public class PluginManager {
/** /**
* 初始化所有启用的插件 * 初始化所有启用的插件
*/ */
public void initializePlugins() { public void initPlugins() {
for (PluginDescriptor pluginDescriptor : pluginDescriptors) { for (PluginDescriptor pluginDescriptor : pluginDescriptors) {
if (pluginDescriptor.isEnabled()) { if (pluginDescriptor.isEnabled()) {
pluginDescriptor.getPlugin().initialize(); pluginDescriptor.getPlugin().initialize();

View File

@ -4,9 +4,9 @@ import javafx.geometry.Insets;
import org.fxmisc.richtext.LineNumberFactory; import org.fxmisc.richtext.LineNumberFactory;
import org.fxmisc.richtext.StyleClassedTextArea; import org.fxmisc.richtext.StyleClassedTextArea;
import org.jcnc.jnotepad.util.LogUtil; import org.jcnc.jnotepad.util.LogUtil;
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox; import org.jcnc.jnotepad.views.manager.BottomStatusBoxManager;
import org.jcnc.jnotepad.views.manager.CenterTabPaneManager;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab; import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -51,7 +51,7 @@ public class LineNumberTextArea extends StyleClassedTextArea {
private void initListeners() { private void initListeners() {
// 监听主要文本区域的文本变化 // 监听主要文本区域的文本变化
this.textProperty().addListener((observable, oldValue, newValue) -> { this.textProperty().addListener((observable, oldValue, newValue) -> {
BottomStatusBox.getInstance().updateWordCountStatusLabel(); BottomStatusBoxManager.getInstance().updateWordCountStatusLabel();
save(); save();
}); });
} }
@ -61,7 +61,7 @@ public class LineNumberTextArea extends StyleClassedTextArea {
*/ */
public void save() { public void save() {
// 获取当前选定的中央标签页CenterTab对象 // 获取当前选定的中央标签页CenterTab对象
CenterTab tab = CenterTabPane.getInstance().getSelected(); CenterTab tab = CenterTabPaneManager.getInstance().getSelected();
// 如果没有选定标签页返回不执行保存操作 // 如果没有选定标签页返回不执行保存操作
if (tab == null) { if (tab == null) {

View File

@ -0,0 +1,198 @@
package org.jcnc.jnotepad.views.manager;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import java.nio.charset.Charset;
/**
* 状态栏组件管理类
*
* @author gewuyou
*/
public class BottomStatusBoxManager {
private static final BottomStatusBoxManager INSTANCE = new BottomStatusBoxManager();
private static final BottomStatusBox BOTTOM_STATUS_BOX = BottomStatusBox.getInstance();
private static final String STATUS_LABEL_FORMAT = "%s : %d \t%s: %d \t%s: %d \t";
private String style = "-fx-background-color: rgba(43,43,43,0.12);";
public static BottomStatusBoxManager getInstance() {
return INSTANCE;
}
/**
* 初始化状态栏
*/
public void initStatusBox() {
BOTTOM_STATUS_BOX.setStyle(style);
BOTTOM_STATUS_BOX.getChildren().clear();
registerBottomStatusBox();
updateEncodingLabel();
updateWhenTabSelected();
BOTTOM_STATUS_BOX.getProperties().put("borderpane-margin", new Insets(5, 10, 5, 10));
BOTTOM_STATUS_BOX.setAlignment(Pos.BASELINE_RIGHT);
UiResourceBundle.getInstance().addListener((observable, oldValue, newValue) -> updateWhenTabSelected());
/*
第一个参数 10 表示上边距
第二个参数 10 表示右边距
第三个参数 10 表示下边距
第四个参数 10 表示左边距
*/
HBox.setMargin(BOTTOM_STATUS_BOX.getStatusLabel(), new Insets(5, 10, 5, 10));
}
/**
* 注册下方状态栏
*/
public void registerBottomStatusBox() {
Label statusLabel = BOTTOM_STATUS_BOX.getStatusLabel();
registerChildrenByLabel(statusLabel);
statusLabel.setText(getStatusBarFormattedText(0, 0, 1));
registerChildrenByLabel(BOTTOM_STATUS_BOX.getEncodingLabel());
}
/**
* 设置状态栏样式
*
* @param style 样式字符串
*/
public void setBottomStatusBoxStyle(String style) {
this.style = style;
}
/**
* 注册状态栏标签组件
*
* @param label 标签组件
*/
public void registerChildrenByLabel(Label label) {
BOTTOM_STATUS_BOX.getChildren().add(label);
}
public void updateEncodingLabel() {
updateEncodingLabel(null);
}
/**
* 更新编码展示
*
* @param encoding 文件编码
*/
public void updateEncodingLabel(String encoding) {
if (encoding == null) {
encoding = Charset.defaultCharset().name();
}
BOTTOM_STATUS_BOX.getEncodingLabel().setText(getEncodingFormattedText(encoding) + "\t");
}
/**
* 更新字数统计
*/
public void updateWordCountStatusLabel() {
CenterTabPaneManager instance = CenterTabPaneManager.getInstance();
if (instance.getSelected() == null) {
return;
}
LineNumberTextArea textArea = instance.getSelected().getLineNumberTextArea();
int caretPosition = textArea.getCaretPosition();
int row = getRow(caretPosition, textArea.getText());
int column = getColumn(caretPosition, textArea.getText());
int length = textArea.getLength();
BOTTOM_STATUS_BOX.getStatusLabel().setText(getStatusBarFormattedText(row, column, length));
}
/**
* Tab选中时更新状态栏
* <br>1. 状态栏更新当前选中tab的数字统计
* <br>2. 状态栏更新当前选中tab的字符编码
*/
public void updateWhenTabSelected() {
CenterTabPaneManager instance = CenterTabPaneManager.getInstance();
if (instance.getSelected() != null) {
updateWordCountStatusLabel();
CenterTab centerTab = instance.getSelected();
if (centerTab != null) {
updateEncodingLabel(centerTab.getCharset().name());
// 添加光标位置变化监听器
LineNumberTextArea textArea = centerTab.getLineNumberTextArea();
textArea.caretPositionProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> updateRowColumnLabel(textArea.getCaretPosition(), textArea.getText()));
}
}
}
/**
* 更新行列信息
*
* @param caretPosition 光标位置
* @param text 文本内容
*/
public void updateRowColumnLabel(int caretPosition, String text) {
int row = getRow(caretPosition, text);
int column = getColumn(caretPosition, text);
BOTTOM_STATUS_BOX.getStatusLabel().setText(getStatusBarFormattedText(row, column, text.length()));
}
/**
* 获取光标所在行号
*
* @param caretPosition 光标位置
* @param text 文本内容
* @return 光标所在行号
*/
public int getRow(int caretPosition, String text) {
caretPosition = Math.min(caretPosition, text.length());
String substring = text.substring(0, caretPosition);
int count = 0;
for (char c : substring.toCharArray()) {
if (c == '\n') {
count++;
}
}
return count + 1;
}
/**
* 获取光标所在列号
*
* @param caretPosition 光标位置
* @param text 文本内容
* @return 光标所在列号
*/
public int getColumn(int caretPosition, String text) {
return caretPosition - text.lastIndexOf("\n", caretPosition - 1);
}
public String getStatusBarFormattedText(int row, int column, int wordCount) {
String rowText = UiResourceBundle.getContent(TextConstants.ROW);
String columnText = UiResourceBundle.getContent(TextConstants.COLUMN);
String wordCountText = UiResourceBundle.getContent(TextConstants.WORD_COUNT);
return String.format(STATUS_LABEL_FORMAT,
rowText,
row,
columnText,
column,
wordCountText,
wordCount
);
}
public String getEncodingFormattedText(String encoding) {
String encodingLabelFormat = "%s : %s";
return String.format(encodingLabelFormat, UiResourceBundle.getContent(TextConstants.ENCODE), encoding);
}
}

View File

@ -0,0 +1,91 @@
package org.jcnc.jnotepad.views.manager;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar;
/**
* 中心标签页窗格管理类
*
* @author gewuyou
*/
public class CenterTabPaneManager {
private static final CenterTabPaneManager INSTANCE = new CenterTabPaneManager();
private final CenterTabPane centerTabPane = CenterTabPane.getInstance();
private final BottomStatusBoxManager bottomStatusBoxManager = BottomStatusBoxManager.getInstance();
private CenterTabPaneManager() {
}
public static CenterTabPaneManager getInstance() {
return INSTANCE;
}
/**
* 初始化标签页布局组件
*/
public void initCenterTabPane() {
initListeners();
}
/**
* 初始化监听器
*/
private void initListeners() {
// tab选中行为监听器用于tab切换后更新与当前tab相关的组件
centerTabPane.getSelectionModel().selectedItemProperty().addListener(
(ov, from, to) -> {
if (to != null) {
// 更新菜单栏中与tab相关设置
TopMenuBar.getInstance().updateMenuStatusBySelectedTab();
}
// 更新状态标签
bottomStatusBoxManager.updateWhenTabSelected();
}
);
}
/**
* 添加新tab并设置为选中状态
*
* @param tab 新标签页
*/
public void addNewTab(CenterTab tab) {
if (tab == null) {
return;
}
// 将标签页加入标签页列表
centerTabPane.getTabs().add(tab);
// 设置索引
centerTabPane.getSelectionModel().select(tab);
// 将标签页设置为选中状态
fireTabSelected();
}
/**
* 获取选中的标签页
*
* @return 当前选中的标签页
*/
public CenterTab getSelected() {
return (CenterTab) centerTabPane.getSelectionModel().getSelectedItem();
}
/**
* tab选中行为
* 应用当前菜单上选中的自动换行设置
*/
public void fireTabSelected() {
CenterTab selectedTab = getSelected();
if (selectedTab == null) {
return;
}
selectedTab.setAutoLine(AppConfigController.getInstance().getAutoLineConfig());
bottomStatusBoxManager.updateWhenTabSelected();
}
}

View File

@ -0,0 +1,41 @@
package org.jcnc.jnotepad.views.manager;
import javafx.scene.layout.VBox;
import org.jcnc.jnotepad.views.root.bottom.RootBottomSideBarVerticalBox;
import org.jcnc.jnotepad.views.root.bottom.function.FunctionBox;
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox;
/**
* 底部根侧边栏垂直布局管理类
*
* @author gewuyou
*/
public class RootBottomSideBarVerticalBoxManager {
private static final RootBottomSideBarVerticalBoxManager INSTANCE = new RootBottomSideBarVerticalBoxManager();
private final RootBottomSideBarVerticalBox rootBottomSideBarVerticalBox = RootBottomSideBarVerticalBox.getInstance();
private RootBottomSideBarVerticalBoxManager() {
}
public static RootBottomSideBarVerticalBoxManager getInstance() {
return INSTANCE;
}
/**
* 初始化底部根侧边栏垂直布局
*/
public void initSidebarVerticalBox() {
FunctionBox functionBox = FunctionBox.getInstance();
VBox vbox = rootBottomSideBarVerticalBox.getVbox();
if (!FunctionBox.getMenuBar().getMenus().isEmpty()) {
functionBox.getChildren().add(FunctionBox.getMenuBar());
vbox.getChildren().addAll(functionBox);
}
vbox.getChildren().addAll(BottomStatusBox.getInstance());
rootBottomSideBarVerticalBox.getChildren().addAll(vbox);
}
}

View File

@ -5,8 +5,6 @@ import javafx.scene.layout.BorderPane;
import org.jcnc.jnotepad.exception.AppException; import org.jcnc.jnotepad.exception.AppException;
import org.jcnc.jnotepad.views.root.RootBorderPane; import org.jcnc.jnotepad.views.root.RootBorderPane;
import static org.jcnc.jnotepad.views.root.bottom.RootBottomSideBarVerticalBox.initSidebarVerticalBox;
/** /**
* 根布局管理器类用于管理记事本应用程序的根布局组件 * 根布局管理器类用于管理记事本应用程序的根布局组件
* *
@ -72,6 +70,6 @@ public class RootManager {
root.setCenter(RootBorderPane.getInstance()); root.setCenter(RootBorderPane.getInstance());
scene.setRoot(root); scene.setRoot(root);
initSidebarVerticalBox();
} }
} }

View File

@ -17,7 +17,6 @@ import org.jcnc.jnotepad.model.entity.ShortcutKey;
import org.jcnc.jnotepad.ui.pluginstage.PluginManagementPane; import org.jcnc.jnotepad.ui.pluginstage.PluginManagementPane;
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.root.center.main.center.tab.CenterTabPane;
import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar; import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -97,7 +96,7 @@ public class TopMenuBarManager {
// 1. 更新全局配置 // 1. 更新全局配置
AppConfigController.getInstance().setAutoLineConfig(after); AppConfigController.getInstance().setAutoLineConfig(after);
// 2. 对当前tab生效配置 // 2. 对当前tab生效配置
CenterTabPane.getInstance().fireTabSelected(); CenterTabPaneManager.getInstance().fireTabSelected();
}); });
topMenuBar.getLineFeedItem().selectedProperty().set(true); topMenuBar.getLineFeedItem().selectedProperty().set(true);

View File

@ -2,8 +2,6 @@ package org.jcnc.jnotepad.views.root.bottom;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import org.jcnc.jnotepad.ui.module.AbstractVerticalBox; import org.jcnc.jnotepad.ui.module.AbstractVerticalBox;
import org.jcnc.jnotepad.views.root.bottom.function.FunctionBox;
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox;
/** /**
* 底部根侧边栏垂直布局 * 底部根侧边栏垂直布局
@ -17,7 +15,7 @@ public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
/** /**
* VBox实例 * VBox实例
*/ */
private static final VBox V_BOX_INSTANCE = new VBox(); private final VBox vBox = new VBox();
/** /**
* 获取 RootBottomSideBarVerticalBox 的唯一实例 * 获取 RootBottomSideBarVerticalBox 的唯一实例
@ -37,21 +35,10 @@ public class RootBottomSideBarVerticalBox extends AbstractVerticalBox {
* *
* @return VBox * @return VBox
*/ */
public static VBox getVboxInstance() { public VBox getVbox() {
return V_BOX_INSTANCE; return vBox;
} }
private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox(); private static final RootBottomSideBarVerticalBox INSTANCE = new RootBottomSideBarVerticalBox();
public static void initSidebarVerticalBox() {
FunctionBox functionBox = FunctionBox.getInstance();
if (!FunctionBox.getMenuBar().getMenus().isEmpty()) {
functionBox.getChildren().add(FunctionBox.getMenuBar());
V_BOX_INSTANCE.getChildren().addAll(functionBox);
}
V_BOX_INSTANCE.getChildren().addAll(BottomStatusBox.getInstance());
INSTANCE.getChildren().addAll(V_BOX_INSTANCE);
}
} }

View File

@ -1,18 +1,7 @@
package org.jcnc.jnotepad.views.root.bottom.status; package org.jcnc.jnotepad.views.root.bottom.status;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import org.jcnc.jnotepad.app.i18n.UiResourceBundle;
import org.jcnc.jnotepad.common.constants.TextConstants;
import org.jcnc.jnotepad.ui.module.AbstractHorizontalBox; import org.jcnc.jnotepad.ui.module.AbstractHorizontalBox;
import org.jcnc.jnotepad.ui.module.LineNumberTextArea;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTab;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
import java.nio.charset.Charset;
/** /**
* 状态栏组件封装 * 状态栏组件封装
@ -23,171 +12,31 @@ import java.nio.charset.Charset;
*/ */
public class BottomStatusBox extends AbstractHorizontalBox { public class BottomStatusBox extends AbstractHorizontalBox {
private static final BottomStatusBox STATUS_BOX = new BottomStatusBox(); private static final BottomStatusBox INSTANCE = new BottomStatusBox();
private static final String STATUS_LABEL_FORMAT = "%s : %d \t%s: %d \t%s: %d \t";
/** /**
* 字数统计及光标 * 字数统计及光标
*/ */
private Label statusLabel; private final Label statusLabel = new Label();
/** /**
* 显示文本编码 * 显示文本编码
*/ */
private Label encodingLabel; private final Label encodingLabel = new Label();
private BottomStatusBox() { private BottomStatusBox() {
initStatusBox();
} }
public static BottomStatusBox getInstance() { public static BottomStatusBox getInstance() {
return STATUS_BOX; return INSTANCE;
}
/**
* 初始化状态栏组件
*/
public void initStatusBox() {
this.setStyle("-fx-background-color: rgba(43,43,43,0.12);");
this.getChildren().clear();
// 创建状态栏
statusLabel = new Label();
statusLabel.setText(getStatusBarFormattedText(0, 0, 1));
// 创建新的标签以显示编码信息
encodingLabel = new Label();
updateEncodingLabel();
updateWhenTabSelected();
this.getChildren().add(statusLabel);
this.getChildren().add(encodingLabel);
this.getProperties().put("borderpane-margin", new Insets(5, 10, 5, 10));
this.setAlignment(Pos.BASELINE_RIGHT);
UiResourceBundle.getInstance().addListener((observable, oldValue, newValue) -> updateWhenTabSelected());
/*
第一个参数 10 表示上边距
第二个参数 10 表示右边距
第三个参数 10 表示下边距
第四个参数 10 表示左边距
*/
setMargin(statusLabel, new Insets(5, 10, 5, 10));
}
public void updateEncodingLabel() {
updateEncodingLabel(null);
}
/**
* 更新编码展示
*
* @param encoding 文件编码
*/
public void updateEncodingLabel(String encoding) {
if (encoding == null) {
encoding = Charset.defaultCharset().name();
}
this.encodingLabel.setText(getEncodingFormattedText(encoding) + "\t");
}
/**
* 更新字数统计
*/
public void updateWordCountStatusLabel() {
CenterTabPane instance = CenterTabPane.getInstance();
if (instance.getSelected() == null) {
return;
}
LineNumberTextArea textArea = instance.getSelected().getLineNumberTextArea();
int caretPosition = textArea.getCaretPosition();
int row = getRow(caretPosition, textArea.getText());
int column = getColumn(caretPosition, textArea.getText());
int length = textArea.getLength();
this.statusLabel.setText(getStatusBarFormattedText(row, column, length));
}
/**
* Tab选中时更新状态栏
* <br>1. 状态栏更新当前选中tab的数字统计
* <br>2. 状态栏更新当前选中tab的字符编码
*/
public void updateWhenTabSelected() {
CenterTabPane instance = CenterTabPane.getInstance();
if (instance.getSelected() != null) {
updateWordCountStatusLabel();
CenterTab centerTab = instance.getSelected();
if (centerTab != null) {
updateEncodingLabel(centerTab.getCharset().name());
// 添加光标位置变化监听器
LineNumberTextArea textArea = centerTab.getLineNumberTextArea();
textArea.caretPositionProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
updateRowColumnLabel(textArea.getCaretPosition(), textArea.getText());
}
});
}
}
}
/**
* 更新行列信息
*
* @param caretPosition 光标位置
* @param text 文本内容
*/
private void updateRowColumnLabel(int caretPosition, String text) {
int row = getRow(caretPosition, text);
int column = getColumn(caretPosition, text);
statusLabel.setText(getStatusBarFormattedText(row, column, text.length()));
} }
/** public Label getStatusLabel() {
* 获取光标所在行号 return statusLabel;
*
* @param caretPosition 光标位置
* @param text 文本内容
* @return 光标所在行号
*/
public int getRow(int caretPosition, String text) {
caretPosition = Math.min(caretPosition, text.length());
String substring = text.substring(0, caretPosition);
int count = 0;
for (char c : substring.toCharArray()) {
if (c == '\n') {
count++;
}
}
return count + 1;
} }
/** public Label getEncodingLabel() {
* 获取光标所在列号 return encodingLabel;
*
* @param caretPosition 光标位置
* @param text 文本内容
* @return 光标所在列号
*/
public int getColumn(int caretPosition, String text) {
return caretPosition - text.lastIndexOf("\n", caretPosition - 1);
}
protected String getStatusBarFormattedText(int row, int column, int wordCount) {
String rowText = UiResourceBundle.getContent(TextConstants.ROW);
String columnText = UiResourceBundle.getContent(TextConstants.COLUMN);
String wordCountText = UiResourceBundle.getContent(TextConstants.WORD_COUNT);
return String.format(STATUS_LABEL_FORMAT,
rowText,
row,
columnText,
column,
wordCountText,
wordCount
);
}
protected String getEncodingFormattedText(String encoding) {
String encodingLabelFormat = "%s : %s";
return String.format(encodingLabelFormat, UiResourceBundle.getContent(TextConstants.ENCODE), encoding);
} }
} }

View File

@ -1,9 +1,6 @@
package org.jcnc.jnotepad.views.root.center.main.center.tab; package org.jcnc.jnotepad.views.root.center.main.center.tab;
import javafx.scene.control.TabPane; import javafx.scene.control.TabPane;
import org.jcnc.jnotepad.controller.config.AppConfigController;
import org.jcnc.jnotepad.views.root.bottom.status.BottomStatusBox;
import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar;
/** /**
* 标签页布局组件封装 * 标签页布局组件封装
@ -12,69 +9,14 @@ import org.jcnc.jnotepad.views.root.top.menu.TopMenuBar;
*/ */
public class CenterTabPane extends TabPane { public class CenterTabPane extends TabPane {
private static final CenterTabPane TAB_PANE = new CenterTabPane(); private static final CenterTabPane INSTANCE = new CenterTabPane();
private CenterTabPane() { private CenterTabPane() {
initListeners();
} }
public static CenterTabPane getInstance() { public static CenterTabPane getInstance() {
return TAB_PANE; return INSTANCE;
} }
/**
* 初始化监听器
*/
private void initListeners() {
// tab选中行为监听器用于tab切换后更新与当前tab相关的组件
this.getSelectionModel().selectedItemProperty().addListener(
(ov, from, to) -> {
if (to != null) {
// 更新菜单栏中与tab相关设置
TopMenuBar.getInstance().updateMenuStatusBySelectedTab();
}
// 更新状态标签
BottomStatusBox.getInstance().updateWhenTabSelected();
}
);
}
/**
* 添加新tab并设置为选中状态
*
* @param tab 新标签页
*/
public void addNewTab(CenterTab tab) {
if (tab == null) {
return;
}
// 将标签页加入标签页列表
this.getTabs().add(tab);
// 设置索引
this.getSelectionModel().select(tab);
// 将标签页设置为选中状态
fireTabSelected();
}
/**
* 获取选中的标签页
*
* @return 当前选中的标签页
*/
public CenterTab getSelected() {
return (CenterTab) this.getSelectionModel().getSelectedItem();
}
/**
* tab选中行为
* 应用当前菜单上选中的自动换行设置
*/
public void fireTabSelected() {
CenterTab selectedTab = getSelected();
if (selectedTab == null) {
return;
}
selectedTab.setAutoLine(AppConfigController.getInstance().getAutoLineConfig());
BottomStatusBox.getInstance().updateWhenTabSelected();
}
} }

View File

@ -1,8 +1,8 @@
package org.jcnc.jnotepad.views.root.top.menu; package org.jcnc.jnotepad.views.root.top.menu;
import javafx.scene.control.*; import javafx.scene.control.*;
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;
import org.jcnc.jnotepad.views.root.center.main.center.tab.CenterTabPane;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -22,7 +22,7 @@ public class TopMenuBar extends MenuBar {
/** /**
* 标签页布局组件封装 * 标签页布局组件封装
*/ */
CenterTabPane centerTabPane = CenterTabPane.getInstance(); CenterTabPaneManager centerTabPane = CenterTabPaneManager.getInstance();
/** /**
* 文件菜单 * 文件菜单
*/ */