refactor: 将菜单\菜单项\Tab提取到单独的类中,作为UI组件

This commit is contained in:
songdragon 2023-08-22 00:09:12 +08:00
parent 09b4f3c64b
commit 65f8a50dd9
11 changed files with 286 additions and 181 deletions

View File

@ -68,7 +68,6 @@ public class LunchApp extends Application {
viewManager.initScreen(scene); viewManager.initScreen(scene);
// 初始化菜单项和标签栏 // 初始化菜单项和标签栏
view.initItem();
view.initTabPane(); view.initTabPane();
view.initShortcutKey(); view.initShortcutKey();

View File

@ -5,6 +5,8 @@ import javafx.event.EventHandler;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.view.manager.ViewManager;
@ -37,14 +39,10 @@ public class NewFile implements EventHandler<ActionEvent> {
// 增加autoSave监听器绑定 // 增加autoSave监听器绑定
controller.autoSave(textArea); controller.autoSave(textArea);
ViewManager viewManager = ViewManager.getInstance(); ViewManager viewManager = ViewManager.getInstance();
// 创建一个新的Tab页
Tab tab = new Tab("新建文本 " + viewManager.selfIncreaseAndGetTabIndex());
tab.setContent(textArea);
// 将Tab页添加到TabPane中 // 将Tab页添加到TabPane中
viewManager.getTabPane().getTabs().add(tab); JNotepadTabPane.getInstance().addNewTab(new JNotepadTab("新建文本 "
+ viewManager.selfIncreaseAndGetTabIndex(),
// 将新建的Tab页设置为选中状态 textArea));
viewManager.getTabPane().getSelectionModel().select(tab);
// 更新状态标签 // 更新状态标签
controller.updateStatusLabel(textArea); controller.updateStatusLabel(textArea);

View File

@ -6,6 +6,7 @@ import javafx.event.EventHandler;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.controller.manager.Controller;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.view.manager.ViewManager;
import java.io.File; import java.io.File;
@ -41,7 +42,7 @@ public class OpenFile implements EventHandler<ActionEvent> {
// 调用控制器的getText方法读取文件内容 // 调用控制器的getText方法读取文件内容
controller.getText(file); controller.getText(file);
// 更新编码标签 // 更新编码标签
controller.upDateEncodingLabel(((LineNumberTextArea) viewManager.getTabPane().getSelectionModel().getSelectedItem().getContent()).getMainTextArea().getText()); controller.upDateEncodingLabel(((LineNumberTextArea) JNotepadTabPane.getInstance().getSelected().getContent()).getMainTextArea().getText());
return null; return null;
} }
}; };

View File

@ -5,6 +5,7 @@ import javafx.event.EventHandler;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.view.manager.ViewManager;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -31,8 +32,7 @@ public class SaveAsFile implements EventHandler<ActionEvent> {
*/ */
@Override @Override
public void handle(ActionEvent event) { public void handle(ActionEvent event) {
ViewManager viewManager = ViewManager.getInstance(); Tab selectedTab = JNotepadTabPane.getInstance().getSelected();
Tab selectedTab = viewManager.getTabPane().getSelectionModel().getSelectedItem();
if (selectedTab != null) { if (selectedTab != null) {
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
fileChooser.setInitialFileName(selectedTab.getText()); fileChooser.setInitialFileName(selectedTab.getText());

View File

@ -12,6 +12,8 @@ import org.jcnc.jnotepad.controller.event.handler.OpenFile;
import org.jcnc.jnotepad.controller.event.handler.SaveAsFile; import org.jcnc.jnotepad.controller.event.handler.SaveAsFile;
import org.jcnc.jnotepad.tool.EncodingDetector; import org.jcnc.jnotepad.tool.EncodingDetector;
import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.view.manager.ViewManager;
import java.io.*; import java.io.*;
@ -101,7 +103,7 @@ public class Controller implements ControllerInterface {
@Override @Override
public void autoSave(LineNumberTextArea textArea) { public void autoSave(LineNumberTextArea textArea) {
textArea.getMainTextArea().textProperty().addListener((observable, oldValue, newValue) -> { textArea.getMainTextArea().textProperty().addListener((observable, oldValue, newValue) -> {
Tab tab = ViewManager.getInstance().getTabPane().getSelectionModel().getSelectedItem(); Tab tab = JNotepadTabPane.getInstance().getSelected();
if (tab != null) { if (tab != null) {
File file = (File) tab.getUserData(); File file = (File) tab.getUserData();
if (file != null) { if (file != null) {
@ -174,11 +176,9 @@ public class Controller implements ControllerInterface {
Platform.runLater(() -> { Platform.runLater(() -> {
textArea.getMainTextArea().setText(text); textArea.getMainTextArea().setText(text);
Tab tab = createNewTab(file.getName(), textArea); JNotepadTab tab = createNewTab(file.getName(), textArea);
tab.setUserData(file); tab.setUserData(file);
viewManager.getTabPane().getTabs().add(tab); JNotepadTabPane.getInstance().addNewTab(tab);
// ViewManager.tabPane.sets
viewManager.getTabPane().getSelectionModel().select(tab);
updateStatusLabel(textArea); updateStatusLabel(textArea);
autoSave(textArea); autoSave(textArea);
@ -237,7 +237,7 @@ public class Controller implements ControllerInterface {
@Override @Override
public void initTabPane() { public void initTabPane() {
Controller controller = new Controller(); Controller controller = new Controller();
ViewManager.getInstance().getTabPane().getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { JNotepadTabPane.getInstance().getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> {
LineNumberTextArea textArea; LineNumberTextArea textArea;
if (newTab != null) { if (newTab != null) {
// 获取新选定的标签页并关联的文本区域 // 获取新选定的标签页并关联的文本区域
@ -267,10 +267,8 @@ public class Controller implements ControllerInterface {
@Override @Override
public void updateUiWithNewTextArea(LineNumberTextArea textArea) { public void updateUiWithNewTextArea(LineNumberTextArea textArea) {
ViewManager viewManager = ViewManager.getInstance(); ViewManager viewManager = ViewManager.getInstance();
Tab tab = new Tab("新建文件 " + viewManager.selfIncreaseAndGetTabIndex()); String tabTitle = "新建文件 " + viewManager.selfIncreaseAndGetTabIndex();
tab.setContent(textArea); JNotepadTabPane.getInstance().addNewTab(new JNotepadTab(tabTitle, textArea));
viewManager.getTabPane().getTabs().add(tab);
viewManager.getTabPane().getSelectionModel().select(tab);
updateStatusLabel(textArea); updateStatusLabel(textArea);
} }
@ -311,11 +309,8 @@ public class Controller implements ControllerInterface {
* @param textArea 文本区域 * @param textArea 文本区域
* @return 新的标签页 * @return 新的标签页
*/ */
private Tab createNewTab(String tabName, LineNumberTextArea textArea) { private JNotepadTab createNewTab(String tabName, LineNumberTextArea textArea) {
Tab tab = new Tab(tabName); return new JNotepadTab(tabName, textArea);
tab.setContent(textArea);
tab.setUserData(null);
return tab;
} }
/** /**

View File

@ -6,7 +6,7 @@ import com.google.gson.reflect.TypeToken;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyCombination;
import org.jcnc.jnotepad.Interface.ShortcutKeyInterface; import org.jcnc.jnotepad.Interface.ShortcutKeyInterface;
import org.jcnc.jnotepad.view.manager.ViewManager; import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
import java.io.*; import java.io.*;
import java.util.Map; import java.util.Map;
@ -54,7 +54,7 @@ public class ShortcutKey implements ShortcutKeyInterface {
}.getType()); }.getType());
for (Map.Entry<String, String> stringObjectEntry : shortcutKeyConfig.entrySet()) { for (Map.Entry<String, String> stringObjectEntry : shortcutKeyConfig.entrySet()) {
// 保证json的key必须和变量名一致 // 保证json的key必须和变量名一致
MenuItem menuItem = ViewManager.getInstance().getItemMap().get(stringObjectEntry.getKey()); MenuItem menuItem = JNotepadMenuBar.getMenuBar().getItemMap().get(stringObjectEntry.getKey());
String shortKeyValue = stringObjectEntry.getValue(); String shortKeyValue = stringObjectEntry.getValue();
if ("".equals(shortKeyValue) || Objects.isNull(menuItem)) { if ("".equals(shortKeyValue) || Objects.isNull(menuItem)) {
continue; continue;

View File

@ -0,0 +1,160 @@
package org.jcnc.jnotepad.ui.menu;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import org.jcnc.jnotepad.controller.event.handler.LineFeed;
import org.jcnc.jnotepad.controller.event.handler.NewFile;
import org.jcnc.jnotepad.controller.event.handler.OpenFile;
import org.jcnc.jnotepad.controller.event.handler.SaveAsFile;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
import org.jcnc.jnotepad.ui.tab.JNotepadTab;
import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import java.util.HashMap;
import java.util.Map;
/**
* 封装菜单栏组件
*
* @author songdragon
*/
public class JNotepadMenuBar extends MenuBar {
private static final JNotepadMenuBar MENU_BAR = new JNotepadMenuBar();
private JNotepadMenuBar() {
init();
}
/**
* 文件菜单
*/
private Menu fileMenu;
/**
* 插件菜单
*/
private Menu setMenu;
/**
* 插件菜单
*/
private Menu pluginMenu;
/// 菜单按钮
/**
* 新建
*/
private MenuItem newItem;
/**
* 打开
*/
private MenuItem openItem;
/**
* 保存
*/
private MenuItem saveAsItem;
/**
* 增加
*/
private MenuItem addItem;
/**
* 查看
*/
private MenuItem countItem;
/**
* 自动换行点击菜单按钮
*/
private CheckMenuItem lineFeedItem;
private final Map<String, MenuItem> itemMap = new HashMap<>();
/**
* 初始化菜单栏
*/
private void init() {
initFileMenu();
initSettingMenu();
initPluginMenu();
// 菜单栏
this.getMenus().addAll(fileMenu, setMenu, pluginMenu);
initEventHandlers();
}
/**
* 初始化文件菜单
*/
private void initFileMenu() {
// 文件菜单
fileMenu = new Menu("文件");
newItem = new MenuItem("新建");
itemMap.put("newItem", newItem);
openItem = new MenuItem("打开");
itemMap.put("openItem", openItem);
saveAsItem = new MenuItem("另存为");
itemMap.put("saveAsItem", saveAsItem);
fileMenu.getItems().addAll(newItem, openItem, saveAsItem);
}
/**
* 初始化设置菜单
*/
private void initSettingMenu() {
// 设置菜单
setMenu = new Menu("设置");
lineFeedItem = new CheckMenuItem("自动换行");
itemMap.put("lineFeedItem", lineFeedItem);
lineFeedItem.selectedProperty().set(true);
setMenu.getItems().addAll(lineFeedItem);
}
/**
* 初始化插件菜单
*/
private void initPluginMenu() {
// 插件菜单
pluginMenu = new Menu("插件");
addItem = new MenuItem("增加插件");
itemMap.put("addItem", addItem);
countItem = new MenuItem("统计字数");
itemMap.put("countItem", countItem);
pluginMenu.getItems().addAll(addItem, countItem);
}
public static JNotepadMenuBar getMenuBar() {
return MENU_BAR;
}
/**
* 初始化事件处理
*/
private void initEventHandlers() {
newItem.setOnAction(new NewFile());
openItem.setOnAction(new OpenFile());
saveAsItem.setOnAction(new SaveAsFile());
lineFeedItem.setOnAction(new LineFeed(new LineNumberTextArea()));
}
public Map<String, MenuItem> getItemMap() {
return itemMap;
}
/**
* 根据当前选中tab更新菜单选项
*/
public void updateMenuStatusBySelectedTab() {
JNotepadTab selectedTab = JNotepadTabPane.getInstance().getSelected();
lineFeedItem.selectedProperty().setValue(selectedTab.isAutoLine());
}
}

View File

@ -0,0 +1,41 @@
package org.jcnc.jnotepad.ui.tab;
import javafx.scene.control.Tab;
import org.jcnc.jnotepad.ui.LineNumberTextArea;
/**
* 封装标签页组件增加属于标签页的属性例如自动换行开关
* 每个Tab关联一个LineNumberTextArea
*
* @author songdragon
*/
public class JNotepadTab extends Tab {
/**
* 默认关闭自动换行
*/
private boolean autoLine = false;
private final LineNumberTextArea lineNumberTextArea;
public JNotepadTab(String tabTitle) {
this(tabTitle, new LineNumberTextArea());
}
public JNotepadTab(String tabTitle, LineNumberTextArea textArea) {
super(tabTitle);
lineNumberTextArea = textArea;
this.setContent(lineNumberTextArea);
}
public boolean isAutoLine() {
return autoLine;
}
public void setAutoLine(boolean autoLine) {
this.autoLine = autoLine;
}
public LineNumberTextArea getLineNumberTextArea() {
return lineNumberTextArea;
}
}

View File

@ -0,0 +1,58 @@
package org.jcnc.jnotepad.ui.tab;
import javafx.scene.control.TabPane;
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
/**
* 标签页布局组件封装
*
* @author songdragon
*/
public class JNotepadTabPane extends TabPane {
private static final JNotepadTabPane TAB_PANE = new JNotepadTabPane();
private JNotepadTabPane() {
initListeners();
}
/**
* 初始化监听器
*/
private void initListeners() {
// tab选中行为监听器用于tab切换后更新与当前tab相关的组件
this.getSelectionModel().selectedItemProperty().addListener(
(ov, from, to) -> {
if (to != null) {
JNotepadMenuBar.getMenuBar().updateMenuStatusBySelectedTab();
}
}
);
}
public static JNotepadTabPane getInstance() {
return TAB_PANE;
}
/**
* 添加新tab并设置为选中状态
*
* @param tab 新标签页
*/
public void addNewTab(JNotepadTab tab) {
if (tab == null) {
return;
}
this.getTabs().add(tab);
this.getSelectionModel().select(tab);
}
/**
* 获取选中的标签页
*
* @return 当前选中的标签页
*/
public JNotepadTab getSelected() {
return (JNotepadTab) this.getSelectionModel().getSelectedItem();
}
}

View File

@ -15,20 +15,6 @@ import java.util.Map;
* @author 许轲 * @author 许轲
*/ */
public class View { public class View {
// todo 这个东西干嘛的都没用过
private static Map<String, Object> itmeMap = new HashMap<>();
public void initItem() {
ViewManager viewManager = ViewManager.getInstance();
// 初始化菜单项的事件处理器
EventHandler<ActionEvent> newFileEventHandler = Controller.getInstance().getNewFileEventHandler(new LineNumberTextArea());
viewManager.getNewItem().setOnAction(newFileEventHandler);
EventHandler<ActionEvent> openFileEventHandler = Controller.getInstance().getOpenFileEventHandler();
viewManager.getOpenItem().setOnAction(openFileEventHandler);
EventHandler<ActionEvent> saveAsFileEventHandler = Controller.getInstance().getSaveAsFileEventHandler();
viewManager.getSaveAsItem().setOnAction(saveAsFileEventHandler);
viewManager.getLineFeedItem().setOnAction(Controller.getInstance().getLineFeedEventHandler(new LineNumberTextArea()));
}
public void initTabPane() { public void initTabPane() {
Controller.getInstance().initTabPane(); Controller.getInstance().initTabPane();

View File

@ -2,12 +2,11 @@ package org.jcnc.jnotepad.view.manager;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.*; import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar;
import java.util.HashMap; import org.jcnc.jnotepad.ui.tab.JNotepadTabPane;
import java.util.Map;
/** /**
@ -26,62 +25,16 @@ public class ViewManager {
private Boolean line = true; private Boolean line = true;
/// 菜单栏组件
/**
* 菜单栏
*/
private MenuBar menuBar;
/**
* 文件菜单
*/
private Menu fileMenu;
/**
* 插件菜单
*/
private Menu setMenu;
/**
* 插件菜单
*/
private Menu pluginMenu;
/// 菜单按钮
/**
* 新建
*/
private MenuItem newItem;
/**
* 打开
*/
private MenuItem openItem;
/**
* 保存
*/
private MenuItem saveAsItem;
/**
* 增加
*/
private MenuItem addItem;
/**
* 查看
*/
private MenuItem countItem;
private CheckMenuItem lineFeedItem; // 自动换行点击菜单按钮
// 主界面布局 // 主界面布局
private BorderPane root; // 主布局 private BorderPane root; // 主布局
// 多个标签页
private TabPane tabPane; // 标签页栏
// 状态栏 // 状态栏
private Label statusLabel; private Label statusLabel;
private static ViewManager instance = null; private static ViewManager instance = null;
private Map<String, MenuItem> itemMap = new HashMap<>();
public Label getEnCodingLabel() { public Label getEnCodingLabel() {
@ -103,62 +56,15 @@ public class ViewManager {
return line; return line;
} }
public MenuBar getMenuBar() {
return menuBar;
}
public Menu getFileMenu() {
return fileMenu;
}
public Menu getSetMenu() {
return setMenu;
}
public Menu getPluginMenu() {
return pluginMenu;
}
public MenuItem getNewItem() {
return newItem;
}
public MenuItem getOpenItem() {
return openItem;
}
public MenuItem getSaveAsItem() {
return saveAsItem;
}
public MenuItem getAddItem() {
return addItem;
}
public MenuItem getCountItem() {
return countItem;
}
public CheckMenuItem getLineFeedItem() {
return lineFeedItem;
}
public BorderPane getRoot() { public BorderPane getRoot() {
return root; return root;
} }
public TabPane getTabPane() {
return tabPane;
}
public Label getStatusLabel() { public Label getStatusLabel() {
return statusLabel; return statusLabel;
} }
public Map<String, MenuItem> getItemMap() {
return itemMap;
}
/** /**
* 获取ViewManager的实例如果实例不存在则创建一个新实例 * 获取ViewManager的实例如果实例不存在则创建一个新实例
@ -198,52 +104,13 @@ public class ViewManager {
* @param scene 与视图相关联的JavaFX场景 * @param scene 与视图相关联的JavaFX场景
*/ */
public void initScreen(Scene scene) { public void initScreen(Scene scene) {
// 创建菜单栏并添加菜单项
menuBar = new MenuBar();
// 文件菜单
fileMenu = new Menu("文件");
newItem = new MenuItem("新建");
itemMap.put("newItem", newItem);
openItem = new MenuItem("打开");
itemMap.put("openItem", openItem);
saveAsItem = new MenuItem("另存为");
itemMap.put("saveAsItem", saveAsItem);
fileMenu.getItems().addAll(newItem, openItem, saveAsItem);
// 设置菜单
setMenu = new Menu("设置");
lineFeedItem = new CheckMenuItem("自动换行");
itemMap.put("lineFeedItem", lineFeedItem);
lineFeedItem.selectedProperty().set(true);
setMenu.getItems().addAll(lineFeedItem);
// 插件菜单
pluginMenu = new Menu("插件");
addItem = new MenuItem("增加插件");
itemMap.put("addItem", addItem);
countItem = new MenuItem("统计字数");
itemMap.put("countItem", countItem);
pluginMenu.getItems().addAll(addItem, countItem);
// 菜单栏
menuBar.getMenus().addAll(fileMenu, setMenu, pluginMenu);
// 创建主界面布局 // 创建主界面布局
root = new BorderPane(); root = new BorderPane();
root.setTop(menuBar); root.setTop(JNotepadMenuBar.getMenuBar());
// 创建标签页和文本编辑区域 // 创建标签页和文本编辑区域
tabPane = new TabPane(); root.setCenter(JNotepadTabPane.getInstance());
root.setCenter(tabPane);
// 创建状态栏 // 创建状态栏
statusLabel = new Label("行数1 \t列数1 \t字数0 "); statusLabel = new Label("行数1 \t列数1 \t字数0 ");