From 008fe17035a0857cd4fc867b8243c432213fa101 Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Fri, 7 Jul 2023 14:57:16 +0800 Subject: [PATCH] Support2128 log window copy able (#2359) * Support copy action in LogWindow * Use a pseudo class state to manage render whether the line is selected --- .../java/org/jackhuang/hmcl/ui/LogWindow.java | 45 +++++++++++++++++++ HMCL/src/main/resources/assets/css/root.css | 4 ++ 2 files changed, 49 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java index 42acfd20b..523b46dd4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java @@ -33,6 +33,7 @@ import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.*; +import javafx.scene.input.KeyCode; import javafx.scene.layout.*; import javafx.stage.Stage; import org.jackhuang.hmcl.game.LauncherHelper; @@ -144,6 +145,7 @@ public final class LogWindow extends Stage { private static class Log { private final String log; private final Log4jLevel level; + private boolean selected = false; public Log(String log, Log4jLevel level) { this.log = log; @@ -236,6 +238,9 @@ public final class LogWindow extends Stage { private static final PseudoClass INFO = PseudoClass.getPseudoClass("info"); private static final PseudoClass DEBUG = PseudoClass.getPseudoClass("debug"); private static final PseudoClass TRACE = PseudoClass.getPseudoClass("trace"); + private static final PseudoClass SELECTED = PseudoClass.getPseudoClass("selected"); + + private final Set> selected = new HashSet<>(); private static ToggleButton createToggleButton(String backgroundColor, StringProperty buttonText, BooleanProperty showLevel) { ToggleButton button = new ToggleButton(); @@ -306,6 +311,27 @@ public final class LogWindow extends Stage { setPadding(new Insets(2)); setWrapText(true); setGraphic(null); + + setOnMouseClicked(event -> { + if (!event.isControlDown()) { + for (ListCell logListCell: selected) { + if (logListCell != this) { + logListCell.pseudoClassStateChanged(SELECTED, false); + if (logListCell.getItem() != null) { + logListCell.getItem().selected = false; + } + } + } + + selected.clear(); + } + + selected.add(this); + pseudoClassStateChanged(SELECTED, true); + if (getItem() != null) { + getItem().selected = true; + } + }); } @Override @@ -324,6 +350,8 @@ public final class LogWindow extends Stage { pseudoClassStateChanged(INFO, !empty && item.level == Log4jLevel.INFO); pseudoClassStateChanged(DEBUG, !empty && item.level == Log4jLevel.DEBUG); pseudoClassStateChanged(TRACE, !empty && item.level == Log4jLevel.TRACE); + pseudoClassStateChanged(SELECTED, !empty && item.selected); + if (empty) { setText(null); } else { @@ -332,6 +360,23 @@ public final class LogWindow extends Stage { } }); + listView.setOnKeyPressed(event -> { + if (event.isControlDown() && event.getCode() == KeyCode.C) { + StringBuilder stringBuilder = new StringBuilder(); + + for (Log item : listView.getItems()) { + if (item != null && item.selected) { + if (item.log != null) { + stringBuilder.append(item.log); + } + stringBuilder.append('\n'); + } + } + + FXUtils.copyText(stringBuilder.toString()); + } + }); + VBox.setVgrow(listView, Priority.ALWAYS); vbox.getChildren().add(listView); } diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index a9b62f03b..aea759d2a 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -1146,6 +1146,10 @@ -fx-background-color: #EEE9E0; } +.log-window-list-cell:selected { + -fx-background-color: #C4C4C4; +} + /******************************************************************************* * * * JFX Spinner *