diff --git a/mystyle-java-fx-tools.ini b/mystyle-java-fx-tools.ini new file mode 100644 index 0000000..40f1200 --- /dev/null +++ b/mystyle-java-fx-tools.ini @@ -0,0 +1,23 @@ +# +# TimiFXExamples 配置文件,不建议手动修改,可能会导致程序异常或崩溃 +# + +[Main] + +# 语言 +Lang=zh_CN + +# 窗体宽度,静默配置,双精度浮点型,取值范围 [1, 系统最大限制],默认 1300 +Width=1300 + +# 窗体高度,静默配置,双精度浮点型,取值范围 [1, 系统最大限制],默认 850 +Height=850 + +# 编辑器主题 +AceJsThem=kr_theme + + +[Interpolator] + +# 动画插值器持续时间 +Duration=1000 \ No newline at end of file diff --git a/src/main/java/com/zhangmeng/tools/controller/EditorListImplController.java b/src/main/java/com/zhangmeng/tools/controller/EditorListImplController.java index cdef5dd..375efd7 100644 --- a/src/main/java/com/zhangmeng/tools/controller/EditorListImplController.java +++ b/src/main/java/com/zhangmeng/tools/controller/EditorListImplController.java @@ -1,5 +1,7 @@ package com.zhangmeng.tools.controller; +import com.sun.javafx.PlatformUtil; +import com.zhangmeng.tools.components.RecursiveFileList; import com.zhangmeng.tools.dto.FileTreeView; import com.zhangmeng.tools.editors.ace.AceEditor; import com.zhangmeng.tools.editors.ace.AceMode; @@ -12,6 +14,7 @@ import com.zhangmeng.tools.utils.ImagePath; import com.zhangmeng.tools.utils.ResourcesUtils; import eu.mihosoft.monacofx.Editor; import eu.mihosoft.monacofx.MonacoFX; +import javafx.application.Platform; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; @@ -19,27 +22,29 @@ import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; +import javafx.event.Event; +import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.geometry.Pos; +import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; -import javafx.scene.input.MouseButton; -import javafx.scene.input.MouseEvent; +import javafx.scene.input.*; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.HBox; import javafx.scene.paint.Paint; import javafx.scene.text.Font; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; +import javafx.stage.DirectoryChooser; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.util.Callback; import lombok.extern.slf4j.Slf4j; +import net.imyeyu.timifx.service.RunAsync; import org.apache.commons.io.FilenameUtils; import org.fxmisc.flowless.VirtualizedScrollPane; import org.fxmisc.richtext.CodeArea; @@ -53,25 +58,29 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import static net.imyeyu.timifx.TimiFX.BORDER_EXLEFT; @Slf4j public class EditorListImplController { + @FXML + public MenuItem open_file; + + @FXML + public MenuItem open_dir; + + @FXML + public MenuItem save; + public enum Type { - JAVA, - HTML, - GO, - JS, - CSS, - SQL, - XML, - YML, - MARKDOWN + JAVA, HTML, GO, JS, CSS, SQL, XML, YML, MARKDOWN } + private TabPane tabPane = null; private SimpleDoubleProperty width = new SimpleDoubleProperty(0.0); private SimpleDoubleProperty height = new SimpleDoubleProperty(0.0); private AnchorPane root; @@ -82,7 +91,7 @@ public class EditorListImplController { private AnchorPane timiFx; private SimpleObjectProperty choose_file = new SimpleObjectProperty<>(null); - + private final ObservableList filePaths_list = FXCollections.observableArrayList(); public static final String color_cell = "#f4f4f4"; @FXML @@ -91,6 +100,8 @@ public class EditorListImplController { @FXML private SplitPane splitPane; + private static final Map map = new HashMap<>(); + @FXML public void date_query_menu_item() { load_small_tools(5); @@ -354,8 +365,61 @@ public class EditorListImplController { return listCell; } }); + tabPane = new TabPane(); + //添加菜单 + addMenu(); + File file = null; + FileTreeView fileTreeView = new FileTreeView(file); + fileTreeView.setBorder(BORDER_EXLEFT); + fileTreeView.setFixedCellSize(40); + splitPane.getItems().clear(); + splitPane.getItems().add(0, fileTreeView); + splitPane.getItems().add(1, tabPane); + splitPane.setDividerPosition(0, 0.20); + splitPane.setDividerPosition(1, 0.80); + } - acJsEditor(false); + public void addMenu() { + + // 设置快捷键 + save.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCodeCombination.CONTROL_DOWN)); + save.setOnAction(event -> writer_file()); + + open_file.setAccelerator(new KeyCodeCombination(KeyCode.F, KeyCodeCombination.CONTROL_DOWN)); + open_file.setOnAction(event -> open_file()); + + open_dir.setAccelerator(new KeyCodeCombination(KeyCode.D, KeyCodeCombination.CONTROL_DOWN)); + open_dir.setOnAction(event -> open_file_dir()); + + + } + + public void open_file() { + Stage stage = new Stage(); + FileChooser dc = new FileChooser(); + dc.setTitle("文件选择"); + dc.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("文件类型", "*.java", "*.go", "*.txt", "*.json", "*.sql")); + File file = dc.showOpenDialog(stage); + if (file != null) { + refresh(file, 0); + } + } + + public void open_file_dir() { + + Stage stage = new Stage(); + DirectoryChooser dc = new DirectoryChooser(); + dc.setTitle("文件夹选择"); + File file = dc.showDialog(stage); + if (file != null) { + if (file.isDirectory()) { + refresh(file, 1); + } + } + } + + public void refresh(File file, int type) { + file_checked(file, type); } private void acJsEditor(boolean flag) { @@ -439,7 +503,7 @@ public class EditorListImplController { AlertUtils.alert_warning("tab " + choose_file.get().getName() + "保存成功!"); } - public void file_checked(File file) { + public void file_checked(File file, int open_type) { String extension = FilenameUtils.getExtension(file.getName()); boolean flag = true; @@ -492,63 +556,139 @@ public class EditorListImplController { if (extension.equals("yml")) { type = Type.YML; } + + if (extension.equals("md")) { + type = Type.MARKDOWN; + } + if (type == null) { type = Type.JAVA; } - if (type == null) { - type = Type.MARKDOWN; - } - open_file(file, type); + + open_file(file, type, open_type); } else { AlertUtils.alert_warning("该文件不支持!"); } } - public void open_file(File file, Type type) { + public void open_file(File file, Type type, int open_type) { - String file_content = null; - try { - file_content = Files.readString(choose_file.get().toPath(), StandardCharsets.UTF_8); - } catch (IOException e) { - try { - file_content = Files.readString(choose_file.get().toPath(), Charset.forName("GBK")); - } catch (IOException ex) { - ex.printStackTrace(); - } + //打开文件 + //打开文件夹 + choose_file.setValue(file); + + if (open_type == 1) { + common_method(); } - int index = listView.getSelectionModel().getSelectedIndex(); - - switch (index) { - case 0 -> { - - switch (type){ - case JAVA -> acJsEditor.setAceMode(AceMode.JAVA); - case HTML -> acJsEditor.setAceMode(AceMode.HTML); - case XML -> acJsEditor.setAceMode(AceMode.XML); - case SQL -> acJsEditor.setAceMode(AceMode.SQL); - case MARKDOWN -> acJsEditor.setAceMode(AceMode.MARKDOWN); - } - - acJsEditor.setAceText(file_content); + Path path = file.toPath(); + if (filePaths_list.contains(path)) {//size -1 ,szie -2 + //切换到一打开的tab + Tab tab = map.get(path); + if (!tabPane.getTabs().contains(tab)) { + tabPane.getTabs().add(tab); + } + tabPane.getSelectionModel().select(tab); + } else { + if (choose_file.get().isFile()) { + + //异步加载 + RunAsync.runback(() -> { + + String file_content = null; + try { + file_content = Files.readString(choose_file.get().toPath(), StandardCharsets.UTF_8); + } catch (IOException e) { + try { + file_content = Files.readString(choose_file.get().toPath(), Charset.forName("GBK")); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + return file_content; + }, file_content -> { + + Tab tab = new Tab(file.getName()); + + ContextMenu contextMenu = new ContextMenu(); + MenuItem close = new MenuItem("close"); + MenuItem close_other_tabs = new MenuItem("close other tabs"); + MenuItem close_all = new MenuItem("close all"); + close_all.setOnAction(event -> { + tabPane.getTabs().clear(); + }); + close_other_tabs.setOnAction(event -> { + ObservableList tabs = tabPane.getTabs(); + ObservableList list = FXCollections.observableArrayList(tabs); + //关闭其他 + for (Tab tabPaneTab : list) { + if (tabPaneTab != tabPane.getSelectionModel().getSelectedItem()) { + tabs.remove(tabPaneTab); + } + } + }); + close.setOnAction(event -> { + //关闭当前窗口 + Tab selectedItem = tabPane.getSelectionModel().getSelectedItem(); + tabPane.getTabs().remove(selectedItem); + }); + contextMenu.getItems().add(close); + contextMenu.getItems().add(close_other_tabs); + contextMenu.getItems().add(close_all); + + + tab.setContextMenu(contextMenu); + tab.setOnCloseRequest(new EventHandler() { + @Override + public void handle(Event event) { + // log.info("tabtab.setOnCloseRequest:--->" + tab.getText()); + tabPane.getTabs().remove(tab); + } + }); + AceMode mode = null; + switch (type) { + case JAVA -> mode = AceMode.JAVA; + case HTML -> mode = AceMode.HTML; + case XML -> mode = AceMode.XML; + case SQL -> mode = AceMode.SQL; + case MARKDOWN -> mode = AceMode.MARKDOWN; + } + //新建编辑器 + AceEditor editor = new AceEditor(choose_file.getValue(),mode,null); + WebView view = editor.getWebView(); + AnchorPane.setTopAnchor(view, 0.0); + AnchorPane.setBottomAnchor(view, 0.0); + AnchorPane.setLeftAnchor(view, 0.0); + AnchorPane.setRightAnchor(view, 0.0); + + tab.setContent(editor); + tabPane.getTabs().add(tab); + tabPane.getSelectionModel().select(tab); + + filePaths_list.add(path); + map.put(path, tab); + }); } - case 1 -> monacoEdit.setText(file_content); - case 2 -> codemirror.setText(file_content); } } + /** + * File file = new File("D:\\generate"); + */ private void common_method() { //splitPane.getItems().remove(1); + File file = choose_file.get(); + //添加菜单 splitPane.getItems().clear(); - //添加文件选择 - File file = new File("D:\\generate"); + //添加文件选择 FileTreeView fileTreeView = new FileTreeView(file); fileTreeView.setBorder(BORDER_EXLEFT); + fileTreeView.setFixedCellSize(40); //fileTreeView.addItemFilter(file -> file.isDirectory() || file.getName().endsWith(".txt")); splitPane.getItems().add(0, fileTreeView); - splitPane.getItems().add(1, root); + splitPane.getItems().add(1, tabPane); splitPane.setDividerPosition(0, 0.2); splitPane.setDividerPosition(1, 0.8); @@ -571,34 +711,36 @@ public class EditorListImplController { if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) { // 双击左键的操作 log.info("open file:" + choose_file.get().getName()); - file_checked(choose_file.get()); + if (choose_file.getValue() != null) { + file_checked(choose_file.get(), 0); + } } }); - root.widthProperty().addListener((observable, oldValue, newValue) -> { - if (newValue != null) { - double width = splitPane.getWidth(); - EditorListImplController.this.width.set(width); - log.info("home:--->width:{}", width); - } - }); - root.heightProperty().addListener((observable, oldValue, newValue) -> { - if (newValue != null) { - double height = splitPane.getHeight(); - EditorListImplController.this.height.set(height); - log.info("home:--->height:{}", height); - } - }); - - this.width.addListener((observable, oldValue, newValue) -> { - EditorListImplController.this.root.setPrefWidth(newValue.doubleValue() - listView.getWidth()); - log.info("root:=====================>width:" + (newValue.doubleValue() - listView.getWidth())); - }); - - this.height.addListener((observable, oldValue, newValue) -> { - EditorListImplController.this.root.setPrefHeight(newValue.doubleValue() - listView.getHeight()); - log.info("root:=====================>:height" + (newValue.doubleValue() - listView.getWidth())); - }); +// root.widthProperty().addListener((observable, oldValue, newValue) -> { +// if (newValue != null) { +// double width = splitPane.getWidth(); +// EditorListImplController.this.width.set(width); +// log.info("home:--->width:{}", width); +// } +// }); +// root.heightProperty().addListener((observable, oldValue, newValue) -> { +// if (newValue != null) { +// double height = splitPane.getHeight(); +// EditorListImplController.this.height.set(height); +// log.info("home:--->height:{}", height); +// } +// }); +// +// this.width.addListener((observable, oldValue, newValue) -> { +// EditorListImplController.this.root.setPrefWidth(newValue.doubleValue() - listView.getWidth()); +// log.info("root:=====================>width:" + (newValue.doubleValue() - listView.getWidth())); +// }); +// +// this.height.addListener((observable, oldValue, newValue) -> { +// EditorListImplController.this.root.setPrefHeight(newValue.doubleValue() - listView.getHeight()); +// log.info("root:=====================>:height" + (newValue.doubleValue() - listView.getWidth())); +// }); } @FXML diff --git a/src/main/java/com/zhangmeng/tools/dto/FileTreeView.java b/src/main/java/com/zhangmeng/tools/dto/FileTreeView.java index bf5b562..2f12741 100644 --- a/src/main/java/com/zhangmeng/tools/dto/FileTreeView.java +++ b/src/main/java/com/zhangmeng/tools/dto/FileTreeView.java @@ -105,10 +105,10 @@ public class FileTreeView extends XTreeView implements TimiFX { this.refreshItem((TreeItem)this.getSelectionModel().getSelectedItem()); }); - List roots = new ArrayList<>(); - roots.add(root); - + if (root != null){ + roots.add(root); + } menuDestroy.disableProperty().bind(Bindings.createBooleanBinding(() -> { ObservableList> items = this.getSelectionModel().getSelectedItems(); diff --git a/src/main/java/com/zhangmeng/tools/editors/ace/AceEditor.java b/src/main/java/com/zhangmeng/tools/editors/ace/AceEditor.java index d11ff30..20af63d 100644 --- a/src/main/java/com/zhangmeng/tools/editors/ace/AceEditor.java +++ b/src/main/java/com/zhangmeng/tools/editors/ace/AceEditor.java @@ -80,6 +80,27 @@ public class AceEditor extends AnchorPane { initialize(); } + public AceEditor(File file,AceMode mode,AceTheme theme) { + String file_content = null; + try { + file_content = Files.readString(file.toPath(), StandardCharsets.UTF_8); + } catch (IOException e) { + try { + file_content = Files.readString(file.toPath(), Charset.forName("GBK")); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + this.file = file; + if (theme != null){ + this.theme.setValue(theme); + } + + this.mode = mode; + setText(file_content); + initialize(); + } + public AceEditor(String text) { setText(text); initialize(); diff --git a/src/main/resources/fxml/editor-list-impl.fxml b/src/main/resources/fxml/editor-list-impl.fxml index 16d3498..be1f21b 100644 --- a/src/main/resources/fxml/editor-list-impl.fxml +++ b/src/main/resources/fxml/editor-list-impl.fxml @@ -7,129 +7,140 @@ - + - + - - - + + + - + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + + - + - - - - + + + + - + - - - + + + - + - - - - - - - - - + + + + + + + + + - + - + - + - - - - + + + + - + - - - - + + + + - + - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mystyle-java-fx-tools.ini b/src/main/resources/mystyle-java-fx-tools.ini index 37a9511..40f1200 100644 --- a/src/main/resources/mystyle-java-fx-tools.ini +++ b/src/main/resources/mystyle-java-fx-tools.ini @@ -13,6 +13,10 @@ Width=1300 # 窗体高度,静默配置,双精度浮点型,取值范围 [1, 系统最大限制],默认 850 Height=850 +# 编辑器主题 +AceJsThem=kr_theme + + [Interpolator] # 动画插值器持续时间