diff --git a/src/main/java/org/jcnc/jnotepad/LunchApp.java b/src/main/java/org/jcnc/jnotepad/LunchApp.java index 4d02858..9619d61 100644 --- a/src/main/java/org/jcnc/jnotepad/LunchApp.java +++ b/src/main/java/org/jcnc/jnotepad/LunchApp.java @@ -68,7 +68,6 @@ public class LunchApp extends Application { viewManager.initScreen(scene); // 初始化菜单项和标签栏 - view.initItem(); view.initTabPane(); view.initShortcutKey(); diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java index 8e79a01..a076b7e 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/NewFile.java @@ -5,6 +5,8 @@ import javafx.event.EventHandler; import javafx.scene.control.Tab; import org.jcnc.jnotepad.controller.manager.Controller; 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; @@ -37,14 +39,10 @@ public class NewFile implements EventHandler { // 增加autoSave监听器绑定 controller.autoSave(textArea); ViewManager viewManager = ViewManager.getInstance(); - // 创建一个新的Tab页 - Tab tab = new Tab("新建文本 " + viewManager.selfIncreaseAndGetTabIndex()); - tab.setContent(textArea); // 将Tab页添加到TabPane中 - viewManager.getTabPane().getTabs().add(tab); - - // 将新建的Tab页设置为选中状态 - viewManager.getTabPane().getSelectionModel().select(tab); + JNotepadTabPane.getInstance().addNewTab(new JNotepadTab("新建文本 " + + viewManager.selfIncreaseAndGetTabIndex(), + textArea)); // 更新状态标签 controller.updateStatusLabel(textArea); diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java index ddb64b8..4b80318 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java @@ -6,6 +6,7 @@ import javafx.event.EventHandler; import javafx.stage.FileChooser; import org.jcnc.jnotepad.controller.manager.Controller; import org.jcnc.jnotepad.ui.LineNumberTextArea; +import org.jcnc.jnotepad.ui.tab.JNotepadTabPane; import org.jcnc.jnotepad.view.manager.ViewManager; import java.io.File; @@ -41,7 +42,7 @@ public class OpenFile implements EventHandler { // 调用控制器的getText方法,读取文件内容 controller.getText(file); // 更新编码标签 - controller.upDateEncodingLabel(((LineNumberTextArea) viewManager.getTabPane().getSelectionModel().getSelectedItem().getContent()).getMainTextArea().getText()); + controller.upDateEncodingLabel(((LineNumberTextArea) JNotepadTabPane.getInstance().getSelected().getContent()).getMainTextArea().getText()); return null; } }; diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/SaveAsFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/SaveAsFile.java index c5afe8d..d7fbbda 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/SaveAsFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/SaveAsFile.java @@ -5,6 +5,7 @@ import javafx.event.EventHandler; import javafx.scene.control.Tab; import javafx.stage.FileChooser; import org.jcnc.jnotepad.ui.LineNumberTextArea; +import org.jcnc.jnotepad.ui.tab.JNotepadTabPane; import org.jcnc.jnotepad.view.manager.ViewManager; import java.io.BufferedWriter; @@ -31,8 +32,7 @@ public class SaveAsFile implements EventHandler { */ @Override public void handle(ActionEvent event) { - ViewManager viewManager = ViewManager.getInstance(); - Tab selectedTab = viewManager.getTabPane().getSelectionModel().getSelectedItem(); + Tab selectedTab = JNotepadTabPane.getInstance().getSelected(); if (selectedTab != null) { FileChooser fileChooser = new FileChooser(); fileChooser.setInitialFileName(selectedTab.getText()); diff --git a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java index 1f622df..334db75 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java +++ b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java @@ -12,6 +12,8 @@ import org.jcnc.jnotepad.controller.event.handler.OpenFile; import org.jcnc.jnotepad.controller.event.handler.SaveAsFile; import org.jcnc.jnotepad.tool.EncodingDetector; 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 java.io.*; @@ -101,7 +103,7 @@ public class Controller implements ControllerInterface { @Override public void autoSave(LineNumberTextArea textArea) { textArea.getMainTextArea().textProperty().addListener((observable, oldValue, newValue) -> { - Tab tab = ViewManager.getInstance().getTabPane().getSelectionModel().getSelectedItem(); + Tab tab = JNotepadTabPane.getInstance().getSelected(); if (tab != null) { File file = (File) tab.getUserData(); if (file != null) { @@ -174,11 +176,9 @@ public class Controller implements ControllerInterface { Platform.runLater(() -> { textArea.getMainTextArea().setText(text); - Tab tab = createNewTab(file.getName(), textArea); + JNotepadTab tab = createNewTab(file.getName(), textArea); tab.setUserData(file); - viewManager.getTabPane().getTabs().add(tab); -// ViewManager.tabPane.sets - viewManager.getTabPane().getSelectionModel().select(tab); + JNotepadTabPane.getInstance().addNewTab(tab); updateStatusLabel(textArea); autoSave(textArea); @@ -237,7 +237,7 @@ public class Controller implements ControllerInterface { @Override public void initTabPane() { Controller controller = new Controller(); - ViewManager.getInstance().getTabPane().getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { + JNotepadTabPane.getInstance().getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) -> { LineNumberTextArea textArea; if (newTab != null) { // 获取新选定的标签页并关联的文本区域 @@ -267,10 +267,8 @@ public class Controller implements ControllerInterface { @Override public void updateUiWithNewTextArea(LineNumberTextArea textArea) { ViewManager viewManager = ViewManager.getInstance(); - Tab tab = new Tab("新建文件 " + viewManager.selfIncreaseAndGetTabIndex()); - tab.setContent(textArea); - viewManager.getTabPane().getTabs().add(tab); - viewManager.getTabPane().getSelectionModel().select(tab); + String tabTitle = "新建文件 " + viewManager.selfIncreaseAndGetTabIndex(); + JNotepadTabPane.getInstance().addNewTab(new JNotepadTab(tabTitle, textArea)); updateStatusLabel(textArea); } @@ -311,11 +309,8 @@ public class Controller implements ControllerInterface { * @param textArea 文本区域 * @return 新的标签页 */ - private Tab createNewTab(String tabName, LineNumberTextArea textArea) { - Tab tab = new Tab(tabName); - tab.setContent(textArea); - tab.setUserData(null); - return tab; + private JNotepadTab createNewTab(String tabName, LineNumberTextArea textArea) { + return new JNotepadTab(tabName, textArea); } /** diff --git a/src/main/java/org/jcnc/jnotepad/controller/manager/ShortcutKey.java b/src/main/java/org/jcnc/jnotepad/controller/manager/ShortcutKey.java index 1cd4d74..12f3aa0 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/manager/ShortcutKey.java +++ b/src/main/java/org/jcnc/jnotepad/controller/manager/ShortcutKey.java @@ -6,7 +6,7 @@ import com.google.gson.reflect.TypeToken; import javafx.scene.control.MenuItem; import javafx.scene.input.KeyCombination; 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.util.Map; @@ -54,7 +54,7 @@ public class ShortcutKey implements ShortcutKeyInterface { }.getType()); for (Map.Entry stringObjectEntry : shortcutKeyConfig.entrySet()) { // 保证json的key必须和变量名一致 - MenuItem menuItem = ViewManager.getInstance().getItemMap().get(stringObjectEntry.getKey()); + MenuItem menuItem = JNotepadMenuBar.getMenuBar().getItemMap().get(stringObjectEntry.getKey()); String shortKeyValue = stringObjectEntry.getValue(); if ("".equals(shortKeyValue) || Objects.isNull(menuItem)) { continue; diff --git a/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java b/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java new file mode 100644 index 0000000..a1c0d5b --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java @@ -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 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 getItemMap() { + return itemMap; + } + + /** + * 根据当前选中tab,更新菜单选项 + */ + public void updateMenuStatusBySelectedTab() { + JNotepadTab selectedTab = JNotepadTabPane.getInstance().getSelected(); + lineFeedItem.selectedProperty().setValue(selectedTab.isAutoLine()); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/ui/tab/JNotepadTab.java b/src/main/java/org/jcnc/jnotepad/ui/tab/JNotepadTab.java new file mode 100644 index 0000000..7a59a97 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/ui/tab/JNotepadTab.java @@ -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; + } +} diff --git a/src/main/java/org/jcnc/jnotepad/ui/tab/JNotepadTabPane.java b/src/main/java/org/jcnc/jnotepad/ui/tab/JNotepadTabPane.java new file mode 100644 index 0000000..970aca9 --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/ui/tab/JNotepadTabPane.java @@ -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(); + } +} diff --git a/src/main/java/org/jcnc/jnotepad/view/init/View.java b/src/main/java/org/jcnc/jnotepad/view/init/View.java index 258b0b2..d0c75e0 100644 --- a/src/main/java/org/jcnc/jnotepad/view/init/View.java +++ b/src/main/java/org/jcnc/jnotepad/view/init/View.java @@ -15,20 +15,6 @@ import java.util.Map; * @author 许轲 */ public class View { - // todo 这个东西干嘛的,都没用过 - private static Map itmeMap = new HashMap<>(); - - public void initItem() { - ViewManager viewManager = ViewManager.getInstance(); - // 初始化菜单项的事件处理器 - EventHandler newFileEventHandler = Controller.getInstance().getNewFileEventHandler(new LineNumberTextArea()); - viewManager.getNewItem().setOnAction(newFileEventHandler); - EventHandler openFileEventHandler = Controller.getInstance().getOpenFileEventHandler(); - viewManager.getOpenItem().setOnAction(openFileEventHandler); - EventHandler saveAsFileEventHandler = Controller.getInstance().getSaveAsFileEventHandler(); - viewManager.getSaveAsItem().setOnAction(saveAsFileEventHandler); - viewManager.getLineFeedItem().setOnAction(Controller.getInstance().getLineFeedEventHandler(new LineNumberTextArea())); - } public void initTabPane() { Controller.getInstance().initTabPane(); diff --git a/src/main/java/org/jcnc/jnotepad/view/manager/ViewManager.java b/src/main/java/org/jcnc/jnotepad/view/manager/ViewManager.java index bac2c4c..d3e1134 100644 --- a/src/main/java/org/jcnc/jnotepad/view/manager/ViewManager.java +++ b/src/main/java/org/jcnc/jnotepad/view/manager/ViewManager.java @@ -2,12 +2,11 @@ package org.jcnc.jnotepad.view.manager; import javafx.geometry.Insets; import javafx.scene.Scene; -import javafx.scene.control.*; +import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; - -import java.util.HashMap; -import java.util.Map; +import org.jcnc.jnotepad.ui.menu.JNotepadMenuBar; +import org.jcnc.jnotepad.ui.tab.JNotepadTabPane; /** @@ -26,62 +25,16 @@ public class ViewManager { 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 TabPane tabPane; // 标签页栏 - // 状态栏 private Label statusLabel; private static ViewManager instance = null; - private Map itemMap = new HashMap<>(); + public Label getEnCodingLabel() { @@ -103,62 +56,15 @@ public class ViewManager { 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() { return root; } - public TabPane getTabPane() { - return tabPane; - } - public Label getStatusLabel() { return statusLabel; } - public Map getItemMap() { - return itemMap; - } - /** * 获取ViewManager的实例。如果实例不存在,则创建一个新实例。 @@ -198,52 +104,13 @@ public class ViewManager { * @param scene 与视图相关联的JavaFX场景。 */ 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.setTop(menuBar); + root.setTop(JNotepadMenuBar.getMenuBar()); // 创建标签页和文本编辑区域 - tabPane = new TabPane(); - root.setCenter(tabPane); + root.setCenter(JNotepadTabPane.getInstance()); // 创建状态栏 statusLabel = new Label("行数:1 \t列数:1 \t字数:0 ");