From d75c3bbf96852129a07996c07cdf0219a27a30df Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 26 Jan 2019 12:53:49 +0800 Subject: [PATCH 01/31] Refactor TwoLineListItem --- .../java/org/jackhuang/hmcl/ui/MainPage.java | 3 - .../org/jackhuang/hmcl/ui/SettingsView.java | 2 +- .../hmcl/ui/account/AddAccountPane.java | 1 + .../hmcl/ui/construct/FontComboBox.java | 14 +-- .../hmcl/ui/construct/TwoLineListItem.java | 96 +------------------ .../hmcl/ui/versions/VersionSettingsPage.java | 7 +- HMCL/src/main/resources/assets/css/root.css | 57 ++++------- .../resources/assets/lang/I18N.properties | 2 +- .../resources/assets/lang/I18N_zh.properties | 2 +- .../assets/lang/I18N_zh_CN.properties | 2 +- 10 files changed, 38 insertions(+), 148 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java index 378e0db7c..6b6d65a54 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -87,11 +87,8 @@ public final class MainPage extends StackPane implements DecoratorPage { lblIcon.setGraphic(SVG.update(Theme.whiteFillBinding(), 20, 20)); TwoLineListItem prompt = new TwoLineListItem(); - prompt.setTitleFill(Color.WHITE); - prompt.setSubtitleFill(Color.WHITE); prompt.setSubtitle(i18n("update.bubble.subtitle")); prompt.setPickOnBounds(false); - prompt.setStyle("-jfx-title-font-weight: BOLD;"); prompt.titleProperty().bind(latestVersionProperty()); hBox.getChildren().setAll(lblIcon, prompt); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java index 566880966..07638486c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsView.java @@ -359,7 +359,7 @@ public abstract class SettingsView extends StackPane { HBox hBox = new HBox(); hBox.setSpacing(3); - cboFont = new FontComboBox(12, false); + cboFont = new FontComboBox(12); txtFontSize = new JFXTextField(); FXUtils.setLimitWidth(txtFontSize, 50); hBox.getChildren().setAll(cboFont, txtFontSize); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 0e117dc90..c35783ed6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui.account; import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.*; + import javafx.beans.binding.Bindings; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.fxml.FXML; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java index 81f2130de..abb1d10f3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FontComboBox.java @@ -24,27 +24,27 @@ import static javafx.collections.FXCollections.singletonObservableList; import org.jackhuang.hmcl.util.javafx.MultiStepBinding; import com.jfoenix.controls.JFXComboBox; +import com.jfoenix.controls.JFXListCell; import javafx.beans.NamedArg; import javafx.beans.binding.Bindings; -import javafx.scene.control.ListCell; import javafx.scene.text.Font; public class FontComboBox extends JFXComboBox { private boolean loaded = false; - public FontComboBox(@NamedArg(value = "fontSize", defaultValue = "12.0") double fontSize, - @NamedArg(value = "enableStyle", defaultValue = "false") boolean enableStyle) { + public FontComboBox(@NamedArg(value = "fontSize", defaultValue = "12.0") double fontSize) { styleProperty().bind(Bindings.concat("-fx-font-family: \"", valueProperty(), "\"")); - setCellFactory(listView -> new ListCell() { + setCellFactory(listView -> new JFXListCell() { @Override - protected void updateItem(String item, boolean empty) { + public void updateItem(String item, boolean empty) { super.updateItem(item, empty); - if (item != null) { + if (!empty) { setText(item); - setFont(new Font(item, fontSize)); + setGraphic(null); + setStyle("-fx-font-family: \"" + item + "\""); } } }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TwoLineListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TwoLineListItem.java index 48d9f9b12..158576d92 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TwoLineListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TwoLineListItem.java @@ -19,32 +19,15 @@ package org.jackhuang.hmcl.ui.construct; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import javafx.css.CssMetaData; -import javafx.css.SimpleStyleableObjectProperty; -import javafx.css.Styleable; -import javafx.css.StyleableObjectProperty; -import javafx.css.StyleablePropertyFactory; import javafx.scene.control.Label; -import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; -import javafx.scene.paint.Color; -import javafx.scene.paint.Paint; -import javafx.scene.text.Font; -import java.util.List; - -public class TwoLineListItem extends StackPane { +public class TwoLineListItem extends VBox { private static final String DEFAULT_STYLE_CLASS = "two-line-list-item"; private final StringProperty title = new SimpleStringProperty(this, "title"); private final StringProperty subtitle = new SimpleStringProperty(this, "subtitle"); - private final StyleableObjectProperty titleFont = new SimpleStyleableObjectProperty<>(StyleableProperties.TITLE_FONT, this, "title-font", Font.font(15)); - private final StyleableObjectProperty subtitleFont = new SimpleStyleableObjectProperty<>(StyleableProperties.SUBTITLE_FONT, this, "subtitle-font", Font.getDefault()); - - private final StyleableObjectProperty titleFill = new SimpleStyleableObjectProperty<>(StyleableProperties.TITLE_FILL, this, "title-fill", Color.BLACK); - private final StyleableObjectProperty subtitleFill = new SimpleStyleableObjectProperty<>(StyleableProperties.SUBTITLE_FILL, this, "subtitle-fill", Color.GRAY); - public TwoLineListItem(String titleString, String subtitleString) { this(); @@ -55,19 +38,14 @@ public class TwoLineListItem extends StackPane { public TwoLineListItem() { setMouseTransparent(true); Label lblTitle = new Label(); - lblTitle.textFillProperty().bind(titleFill); - lblTitle.fontProperty().bind(titleFont); + lblTitle.getStyleClass().add("title"); lblTitle.textProperty().bind(title); Label lblSubtitle = new Label(); - lblSubtitle.textFillProperty().bind(subtitleFill); - lblSubtitle.fontProperty().bind(subtitleFont); + lblSubtitle.getStyleClass().add("subtitle"); lblSubtitle.textProperty().bind(subtitle); - VBox vbox = new VBox(); - vbox.getChildren().setAll(lblTitle, lblSubtitle); - getChildren().setAll(vbox); - + getChildren().setAll(lblTitle, lblSubtitle); getStyleClass().add(DEFAULT_STYLE_CLASS); } @@ -95,74 +73,8 @@ public class TwoLineListItem extends StackPane { this.subtitle.set(subtitle); } - public Font getTitleFont() { - return titleFont.get(); - } - - public StyleableObjectProperty titleFontProperty() { - return titleFont; - } - - public void setTitleFont(Font titleFont) { - this.titleFont.set(titleFont); - } - - public Font getSubtitleFont() { - return subtitleFont.get(); - } - - public StyleableObjectProperty subtitleFontProperty() { - return subtitleFont; - } - - public void setSubtitleFont(Font subtitleFont) { - this.subtitleFont.set(subtitleFont); - } - - public Paint getTitleFill() { - return titleFill.get(); - } - - public StyleableObjectProperty titleFillProperty() { - return titleFill; - } - - public void setTitleFill(Paint titleFill) { - this.titleFill.set(titleFill); - } - - public Paint getSubtitleFill() { - return subtitleFill.get(); - } - - public StyleableObjectProperty subtitleFillProperty() { - return subtitleFill; - } - - public void setSubtitleFill(Paint subtitleFill) { - this.subtitleFill.set(subtitleFill); - } - @Override public String toString() { return getTitle(); } - - @Override - public List> getCssMetaData() { - return getClassCssMetaData(); - } - - public static List> getClassCssMetaData() { - return StyleableProperties.FACTORY.getCssMetaData(); - } - - private static class StyleableProperties { - private static final StyleablePropertyFactory FACTORY = new StyleablePropertyFactory<>(StackPane.getClassCssMetaData()); - - private static final CssMetaData TITLE_FONT = FACTORY.createFontCssMetaData("-jfx-title-font", s -> s.titleFont, Font.font(15)); - private static final CssMetaData SUBTITLE_FONT = FACTORY.createFontCssMetaData("-jfx-subtitle-font", s -> s.subtitleFont); - private static final CssMetaData TITLE_FILL = FACTORY.createPaintCssMetaData("-jfx-title-fill", s -> s.titleFill); - private static final CssMetaData SUBTITLE_FILL = FACTORY.createPaintCssMetaData("-jfx-subtitle-fill", s -> s.subtitleFill, Color.GREY); - } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index a16ca63d4..b9b7f365d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -35,6 +35,7 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.FileChooser; import org.jackhuang.hmcl.setting.EnumGameDirectory; +import org.jackhuang.hmcl.setting.LauncherVisibility; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Profiles; import org.jackhuang.hmcl.setting.VersionSetting; @@ -60,6 +61,7 @@ import java.util.List; import java.util.logging.Level; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.ui.FXUtils.stringConverter; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class VersionSettingsPage extends StackPane implements DecoratorPage { @@ -85,7 +87,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag @FXML private ComponentList advancedSettingsPane; @FXML private ComponentList componentList; @FXML private ComponentList iconPickerItemWrapper; - @FXML private JFXComboBox cboLauncherVisibility; + @FXML private JFXComboBox cboLauncherVisibility; @FXML private JFXCheckBox chkFullscreen; @FXML private Label lblPhysicalMemory; @FXML private JFXToggleButton chkNoJVMArgs; @@ -100,6 +102,9 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag public VersionSettingsPage() { FXUtils.loadFXML(this, "/assets/fxml/version/version-settings.fxml"); + + cboLauncherVisibility.getItems().setAll(LauncherVisibility.values()); + cboLauncherVisibility.setConverter(stringConverter(e -> i18n("settings.advanced.launcher_visibility." + e.name().toLowerCase()))); } @FXML diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index aef827b80..1e5b15ad2 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -104,20 +104,24 @@ -fx-padding: 4 0 4 0; } +.two-line-list-item > .title { + -fx-text-fill: black; + -fx-font-size: 15px; +} + +.two-line-list-item > .subtitle { + -fx-text-fill: gray; +} + .bubble { -fx-background-color: gray; -fx-background-radius: 2px; + -fx-text-fill: white; } -.bubble .two-line-list-item { - -jfx-title-fill: white; - -jfx-subtitle-fill: white; -} - -.two-line-list-item { - -jfx-title-font-size: 15px; - -jfx-title-fill: black; - -jfx-subtitle-fill: gray; +.bubble .two-line-list-item > .title, +.bubble .two-line-list-item > .subtitle { + -fx-text-fill: white; } .window-title-bar .separator { @@ -678,20 +682,12 @@ * * *******************************************************************************/ -.jfx-list-cell:odd, -.jfx-list-cell:even, -.list-cell:odd, -.list-cell:even { +.jfx-list-cell, .list-cell { -fx-background-color: WHITE; } -.list-cell:selected, .jfx-list-cell:selected { - -fx-background-insets: 0.0; - -fx-text-fill: BLACK; -} - -.jfx-list-cell:filled:hover, -.jfx-list-cell:selected .label { +.list-cell:selected, .jfx-list-cell:selected, +.list-cell:hover, .jfx-list-cell:hover { -fx-text-fill: black; } @@ -1109,31 +1105,10 @@ -fx-fill: #D34336; } -.combo-box-popup .list-view .jfx-list-cell .label, -.combo-box-popup .list-view .jfx-list-cell:filled:hover .label { - -fx-text-fill: BLACK; -} - -.combo-box-popup .list-view .jfx-list-cell .custom-jfx-list-view-icon, -.combo-box-popup .list-view .jfx-list-cell:filled:hover .custom-jfx-list-view-icon, -.combo-box-popup .list-view .jfx-list-cell:selected .custom-jfx-list-view-icon { - -fx-fill: -fx-base-color; -} - -.combo-box-popup .list-view .jfx-list-cell:odd:selected > .jfx-rippler > StackPane, -.combo-box-popup .list-view .jfx-list-cell:even:selected > .jfx-rippler > StackPane { - -fx-background-color: rgba(0.0, 0.0, 255.0, 0.2); -} - .combo-box-popup .list-view .jfx-list-cell { -fx-background-insets: 0.0; } -.combo-box-popup .list-view .jfx-list-cell:odd, -.combo-box-popup .list-view .jfx-list-cell:even { - -fx-background-color: WHITE; -} - .combo-box-popup .list-view .jfx-list-cell .jfx-rippler { -jfx-rippler-fill: -fx-base-color; } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 62997be15..5c2d448fe 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -307,7 +307,7 @@ settings.advanced.java_permanent_generation_space=PermGen Space/MB settings.advanced.jvm_args=Java VM Arguments settings.advanced.launcher_visibility.close=Close the launcher when the game launched. settings.advanced.launcher_visibility.hide=Hide the launcher when the game launched. -settings.advanced.launcher_visibility.hide_reopen=Hide the launcher and re-open when game closes. +settings.advanced.launcher_visibility.hide_and_reopen=Hide the launcher and re-open when game closes. settings.advanced.launcher_visibility.keep=Keep the launcher visible. settings.advanced.launcher_visible=Launcher Visibility settings.advanced.minecraft_arguments=Minecraft Arguments diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 48feef601..e448ffbb7 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -306,7 +306,7 @@ settings.advanced.java_permanent_generation_space=記憶體永久儲存區域( settings.advanced.jvm_args=Java 虛擬機參數(不必填寫) settings.advanced.launcher_visibility.close=遊戲啟動後結束啟動器 settings.advanced.launcher_visibility.hide=遊戲啟動後隱藏啟動器 -settings.advanced.launcher_visibility.hide_reopen=隱藏啟動器並在遊戲結束後重新開啟 +settings.advanced.launcher_visibility.hide_and_reopen=隱藏啟動器並在遊戲結束後重新開啟 settings.advanced.launcher_visibility.keep=不隱藏啟動器 settings.advanced.launcher_visible=啟動器可見性 settings.advanced.minecraft_arguments=Minecraft 額外參數(不必填寫) diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index c4ce1b21c..5c72e9066 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -306,7 +306,7 @@ settings.advanced.java_permanent_generation_space=内存永久保存区域(不 settings.advanced.jvm_args=Java 虚拟机参数(不必填写) settings.advanced.launcher_visibility.close=游戏启动后结束启动器 settings.advanced.launcher_visibility.hide=游戏启动后隐藏启动器 -settings.advanced.launcher_visibility.hide_reopen=隐藏启动器并在游戏结束后重新打开 +settings.advanced.launcher_visibility.hide_and_reopen=隐藏启动器并在游戏结束后重新打开 settings.advanced.launcher_visibility.keep=保持启动器可见 settings.advanced.launcher_visible=启动器可见性 settings.advanced.minecraft_arguments=Minecraft 额外参数(不必填写) From 77c86ed3bcf9e78f9fc1c892516d540937805bd3 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 26 Jan 2019 13:17:45 +0800 Subject: [PATCH 02/31] Add tooltip for authlib-injector accounts --- .../hmcl/ui/account/AccountListItemSkin.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index 2ff6b2ace..bc900d2d3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -22,17 +22,21 @@ import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.effects.JFXDepthManager; import javafx.geometry.Pos; +import javafx.scene.control.Label; import javafx.scene.control.SkinBase; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; + import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; -import org.jackhuang.hmcl.ui.construct.TwoLineListItem; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; + public class AccountListItemSkin extends SkinBase { public AccountListItemSkin(AccountListItem skinnable) { @@ -58,8 +62,19 @@ public class AccountListItemSkin extends SkinBase { FXUtils.limitSize(imageView, 32, 32); imageView.imageProperty().bind(skinnable.imageProperty()); - TwoLineListItem item = new TwoLineListItem(); + Label title = new Label(); + title.getStyleClass().add("title"); + title.textProperty().bind(skinnable.titleProperty()); + Label subtitle = new Label(); + subtitle.getStyleClass().add("subtitle"); + subtitle.textProperty().bind(skinnable.subtitleProperty()); + if (skinnable.getAccount() instanceof AuthlibInjectorAccount) { + FXUtils.installTooltip(subtitle, ((AuthlibInjectorAccount) skinnable.getAccount()).getServer().toString()); + } + VBox item = new VBox(title, subtitle); + item.getStyleClass().add("two-line-list-item"); BorderPane.setAlignment(item, Pos.CENTER); + center.getChildren().setAll(imageView, item); root.setCenter(center); @@ -83,8 +98,6 @@ public class AccountListItemSkin extends SkinBase { root.setStyle("-fx-background-color: white; -fx-padding: 8 8 8 0;"); JFXDepthManager.setDepth(root, 1); - item.titleProperty().bind(skinnable.titleProperty()); - item.subtitleProperty().bind(skinnable.subtitleProperty()); getChildren().setAll(root); } From 6c1de5d4855ad003fbd2659bd142cb2c35b4c758 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 26 Jan 2019 13:33:59 +0800 Subject: [PATCH 03/31] Improve tooltip UX --- .../main/java/org/jackhuang/hmcl/ui/FXUtils.java | 16 ++++++++++++++-- .../java/org/jackhuang/hmcl/ui/SettingsPage.java | 2 +- .../hmcl/ui/account/AccountListItemSkin.java | 13 ++++++++++--- .../jackhuang/hmcl/ui/construct/FileItem.java | 2 +- .../hmcl/ui/construct/IconedMenuItem.java | 2 +- .../hmcl/ui/construct/ImagePickerItem.java | 2 +- .../hmcl/ui/versions/DatapackListItem.java | 2 +- .../hmcl/ui/versions/GameListItemSkin.java | 2 +- .../org/jackhuang/hmcl/ui/versions/ModItem.java | 2 +- .../jackhuang/hmcl/ui/versions/VersionPage.java | 10 +++++----- 10 files changed, 36 insertions(+), 17 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index dd108dfcd..614ee0295 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -234,8 +234,20 @@ public final class FXUtils { } } - public static void installTooltip(Node node, String tooltip) { - installTooltip(node, 0, 5000, 0, new Tooltip(tooltip)); + public static void installFastTooltip(Node node, Tooltip tooltip) { + installTooltip(node, 50, 5000, 0, tooltip); + } + + public static void installFastTooltip(Node node, String tooltip) { + installFastTooltip(node, new Tooltip(tooltip)); + } + + public static void installSlowTooltip(Node node, Tooltip tooltip) { + installTooltip(node, 500, 5000, 0, tooltip); + } + + public static void installSlowTooltip(Node node, String tooltip) { + installSlowTooltip(node, new Tooltip(tooltip)); } public static void installTooltip(Node node, double openDelay, double visibleDelay, double closeDelay, Tooltip tooltip) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java index 079ae3266..75bf402b5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java @@ -129,7 +129,7 @@ public final class SettingsPage extends SettingsView implements DecoratorPage { config().commonDirectoryProperty(), config().commonDirTypeProperty())); // ==== Update ==== - FXUtils.installTooltip(btnUpdate, i18n("update.tooltip")); + FXUtils.installFastTooltip(btnUpdate, i18n("update.tooltip")); updateListener = any -> { btnUpdate.setVisible(UpdateChecker.isOutdated()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java index bc900d2d3..0eca64e0e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListItemSkin.java @@ -21,9 +21,12 @@ import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXRadioButton; import com.jfoenix.effects.JFXDepthManager; + +import javafx.beans.binding.Bindings; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.SkinBase; +import javafx.scene.control.Tooltip; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; @@ -36,6 +39,7 @@ import org.jackhuang.hmcl.ui.SVG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; +import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; public class AccountListItemSkin extends SkinBase { @@ -69,7 +73,10 @@ public class AccountListItemSkin extends SkinBase { subtitle.getStyleClass().add("subtitle"); subtitle.textProperty().bind(skinnable.subtitleProperty()); if (skinnable.getAccount() instanceof AuthlibInjectorAccount) { - FXUtils.installTooltip(subtitle, ((AuthlibInjectorAccount) skinnable.getAccount()).getServer().toString()); + Tooltip tooltip = new Tooltip(); + AuthlibInjectorServer server = ((AuthlibInjectorAccount) skinnable.getAccount()).getServer(); + tooltip.textProperty().bind(Bindings.createStringBinding(server::toString, server)); + FXUtils.installSlowTooltip(subtitle, tooltip); } VBox item = new VBox(title, subtitle); item.getStyleClass().add("two-line-list-item"); @@ -84,7 +91,7 @@ public class AccountListItemSkin extends SkinBase { btnRefresh.setOnMouseClicked(e -> skinnable.refresh()); btnRefresh.getStyleClass().add("toggle-icon4"); btnRefresh.setGraphic(SVG.refresh(Theme.blackFillBinding(), -1, -1)); - JFXUtilities.runInFX(() -> FXUtils.installTooltip(btnRefresh, i18n("button.refresh"))); + JFXUtilities.runInFX(() -> FXUtils.installFastTooltip(btnRefresh, i18n("button.refresh"))); right.getChildren().add(btnRefresh); JFXButton btnRemove = new JFXButton(); @@ -92,7 +99,7 @@ public class AccountListItemSkin extends SkinBase { btnRemove.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnRemove, Pos.CENTER); btnRemove.setGraphic(SVG.delete(Theme.blackFillBinding(), -1, -1)); - JFXUtilities.runInFX(() -> FXUtils.installTooltip(btnRemove, i18n("button.delete"))); + JFXUtilities.runInFX(() -> FXUtils.installFastTooltip(btnRemove, i18n("button.delete"))); right.getChildren().add(btnRemove); root.setRight(right); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java index 56af42ac8..7cbd5ac61 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java @@ -61,7 +61,7 @@ public class FileItem extends BorderPane { right.setGraphic(SVG.pencil(Theme.blackFillBinding(), 15, 15)); right.getStyleClass().add("toggle-icon4"); right.setOnMouseClicked(e -> onExplore()); - FXUtils.installTooltip(right, i18n("button.edit")); + FXUtils.installFastTooltip(right, i18n("button.edit")); setRight(right); Tooltip tip = new Tooltip(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedMenuItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedMenuItem.java index a008af282..49d915229 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedMenuItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/IconedMenuItem.java @@ -30,7 +30,7 @@ public class IconedMenuItem extends IconedItem { } public IconedMenuItem addTooltip(String tooltip) { - FXUtils.installTooltip(this, tooltip); + FXUtils.installFastTooltip(this, tooltip); return this; } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java index 6c8b3afef..1a4bd7620 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ImagePickerItem.java @@ -63,7 +63,7 @@ public final class ImagePickerItem extends BorderPane { deleteButton.onMouseClickedProperty().bind(onDeleteButtonClicked); deleteButton.getStyleClass().add("toggle-icon4"); - FXUtils.installTooltip(selectButton, i18n("button.edit")); + FXUtils.installFastTooltip(selectButton, i18n("button.edit")); HBox hBox = new HBox(); hBox.getChildren().setAll(imageView, selectButton, deleteButton); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DatapackListItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DatapackListItem.java index a7a8d04d7..7c8501b53 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DatapackListItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DatapackListItem.java @@ -44,7 +44,7 @@ public class DatapackListItem extends BorderPane { setCenter(modItem); JFXButton btnRemove = new JFXButton(); - FXUtils.installTooltip(btnRemove, i18n("datapack.remove")); + FXUtils.installFastTooltip(btnRemove, i18n("datapack.remove")); btnRemove.setOnMouseClicked(e -> deleteCallback.accept(this)); btnRemove.getStyleClass().add("toggle-icon4"); BorderPane.setAlignment(btnRemove, Pos.CENTER); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java index 8b5013f30..a6de9f3f8 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListItemSkin.java @@ -73,7 +73,7 @@ public class GameListItemSkin extends SkinBase { btnUpgrade.setOnMouseClicked(e -> skinnable.update()); btnUpgrade.getStyleClass().add("toggle-icon4"); btnUpgrade.setGraphic(SVG.update(Theme.blackFillBinding(), -1, -1)); - JFXUtilities.runInFX(() -> FXUtils.installTooltip(btnUpgrade, i18n("version.update"))); + JFXUtilities.runInFX(() -> FXUtils.installFastTooltip(btnUpgrade, i18n("version.update"))); right.getChildren().add(btnUpgrade); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java index f9af3a7be..0a6eb2251 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModItem.java @@ -47,7 +47,7 @@ public final class ModItem extends BorderPane { JFXButton btnRemove = new JFXButton(); JFXUtilities.runInFX(() -> { - FXUtils.installTooltip(btnRemove, i18n("mods.remove")); + FXUtils.installFastTooltip(btnRemove, i18n("mods.remove")); }); btnRemove.setOnMouseClicked(e -> deleteCallback.accept(this)); btnRemove.getStyleClass().add("toggle-icon4"); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java index bc933e727..9b089ec8e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionPage.java @@ -99,13 +99,13 @@ public final class VersionPage extends StackPane implements DecoratorPage { new IconedMenuItem(null, i18n("version.manage.clean"), FXUtils.withJFXPopupClosing(() -> Versions.cleanVersion(profile, version), managementPopup)).addTooltip(i18n("version.manage.clean.tooltip")) ); - FXUtils.installTooltip(btnDelete, i18n("version.manage.remove")); - FXUtils.installTooltip(btnBrowseMenu, i18n("settings.game.exploration")); - FXUtils.installTooltip(btnManagementMenu, i18n("settings.game.management")); - FXUtils.installTooltip(btnExport, i18n("modpack.export")); + FXUtils.installFastTooltip(btnDelete, i18n("version.manage.remove")); + FXUtils.installFastTooltip(btnBrowseMenu, i18n("settings.game.exploration")); + FXUtils.installFastTooltip(btnManagementMenu, i18n("settings.game.management")); + FXUtils.installFastTooltip(btnExport, i18n("modpack.export")); btnTestGame.setGraphic(SVG.launch(Theme.whiteFillBinding(), 20, 20)); - FXUtils.installTooltip(btnTestGame, i18n("version.launch.test")); + FXUtils.installFastTooltip(btnTestGame, i18n("version.launch.test")); setEventHandler(Navigator.NavigationEvent.NAVIGATED, this::onNavigated); } From 8d774e267f7f63d9b61a6c216b510b47fc176ed2 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 26 Jan 2019 15:18:56 +0800 Subject: [PATCH 04/31] Show register link in login dialog https://github.com/yushijinhun/authlib-injector/issues/25 --- .../hmcl/ui/account/AddAccountPane.java | 36 +++++++++++++++++-- .../resources/assets/fxml/account-add.fxml | 1 + .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + .../AuthlibInjectorServer.java | 18 ++++++++++ 6 files changed, 56 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index c35783ed6..9dd6b67eb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -21,7 +21,10 @@ import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.*; import javafx.beans.binding.Bindings; +import javafx.beans.property.ListProperty; import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.SimpleListProperty; +import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.geometry.Pos; import javafx.scene.control.Hyperlink; @@ -45,11 +48,15 @@ import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.*; import org.jackhuang.hmcl.util.Logging; +import org.jackhuang.hmcl.util.javafx.MultiStepBinding; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; +import static java.util.Collections.unmodifiableList; import static java.util.Objects.requireNonNull; import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.ui.FXUtils.*; @@ -64,12 +71,13 @@ public class AddAccountPane extends StackPane { @FXML private JFXComboBox> cboType; @FXML private JFXComboBox cboServers; @FXML private Label lblInjectorServer; - @FXML private Hyperlink linkManageInjectorServers; - @FXML private JFXDialogLayout layout; @FXML private JFXButton btnAccept; @FXML private JFXButton btnAddServer; @FXML private JFXButton btnManageServer; @FXML private SpinnerPane acceptPane; + @FXML private HBox linksContainer; + + private ListProperty links = new SimpleListProperty<>();; public AddAccountPane() { FXUtils.loadFXML(this, "/assets/fxml/account-add.fxml"); @@ -118,6 +126,30 @@ public class AddAccountPane extends StackPane { txtUsername.textProperty(), txtPassword.textProperty(), txtPassword.visibleProperty(), cboServers.getSelectionModel().selectedItemProperty(), cboServers.visibleProperty())); + + // authlib-injector links + links.bind(MultiStepBinding.of(cboServers.getSelectionModel().selectedItemProperty()) + .map(AddAccountPane::createHyperlinks) + .map(FXCollections::observableList)); + Bindings.bindContent(linksContainer.getChildren(), links); + linksContainer.visibleProperty().bind(cboServers.visibleProperty()); + } + + private static final String[] ALLOWED_LINKS = { "register" }; + + public static List createHyperlinks(AuthlibInjectorServer server) { + Map links = server.getLinks(); + List result = new ArrayList<>(); + for (String key : ALLOWED_LINKS) { + String value = links.get(key); + if (value != null) { + Hyperlink link = new Hyperlink(i18n("account.injector.link." + key)); + FXUtils.installSlowTooltip(link, value); + link.setOnAction(e -> FXUtils.openLink(value)); + result.add(link); + } + } + return unmodifiableList(result); } /** diff --git a/HMCL/src/main/resources/assets/fxml/account-add.fxml b/HMCL/src/main/resources/assets/fxml/account-add.fxml index 857a4c846..ccc5290b3 100644 --- a/HMCL/src/main/resources/assets/fxml/account-add.fxml +++ b/HMCL/src/main/resources/assets/fxml/account-add.fxml @@ -32,6 +32,7 @@ + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 5c2d448fe..6caad45cf 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -49,6 +49,7 @@ account.injector.empty=Empty (Click the plus button right to add) account.injector.manage=Manage authentication servers account.injector.manage.title=Authentication servers account.injector.http=Warning: This server is using HTTP, which will cause your password be transmitted in clear text. +account.injector.link.register=Register account.injector.server=Auth Server account.injector.server_url=Server URL account.injector.server_name=Server Name diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index e448ffbb7..070e6a3ca 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -48,6 +48,7 @@ account.injector.empty=無(點擊右側加號添加) account.injector.manage=管理認證伺服器 account.injector.manage.title=認證伺服器 account.injector.http=警告:此伺服器使用不安全的 HTTP 協議,您的密碼在登入時會被明文傳輸。 +account.injector.link.register=註冊 account.injector.server=認證伺服器 account.injector.server_url=伺服器位址 account.injector.server_name=伺服器名稱 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 5c72e9066..864169851 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -48,6 +48,7 @@ account.injector.empty=无(点击右侧加号添加) account.injector.manage=管理认证服务器 account.injector.manage.title=认证服务器 account.injector.http=警告:此服务器使用不安全的 HTTP 协议,您的密码在登录时会被明文传输。 +account.injector.link.register=注册 account.injector.server=认证服务器 account.injector.server_url=服务器地址 account.injector.server_name=服务器名称 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java index 8c48639eb..e3d9aff9b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.auth.authlibinjector; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Collections.emptyMap; import static org.jackhuang.hmcl.util.Lang.tryCast; import static org.jackhuang.hmcl.util.Logging.LOG; import static org.jackhuang.hmcl.util.io.IOUtils.readFullyAsByteArray; @@ -29,6 +30,8 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Optional; import java.util.logging.Level; @@ -137,6 +140,7 @@ public class AuthlibInjectorServer implements Observable { @Nullable private transient String name; + private transient Map links = emptyMap(); private transient boolean metadataRefreshed; private transient ObservableHelper helper = new ObservableHelper(this); @@ -162,6 +166,10 @@ public class AuthlibInjectorServer implements Observable { .orElse(url); } + public Map getLinks() { + return links; + } + public String fetchMetadataResponse() throws IOException { if (metadataResponse == null || !metadataRefreshed) { refreshMetadata(); @@ -201,6 +209,16 @@ public class AuthlibInjectorServer implements Observable { this.name = metaObject.flatMap(meta -> tryCast(meta.get("serverName"), JsonPrimitive.class).map(JsonPrimitive::getAsString)) .orElse(null); + this.links = metaObject.flatMap(meta -> tryCast(meta.get("links"), JsonObject.class)) + .map(linksObject -> { + Map converted = new LinkedHashMap<>(); + linksObject.entrySet().forEach( + entry -> tryCast(entry.getValue(), JsonPrimitive.class).ifPresent(element -> { + converted.put(entry.getKey(), element.getAsString()); + })); + return converted; + }) + .orElse(emptyMap()); } } From 0c25f31493fe3d2be2ebcb8e93275d17c4ec6db2 Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Sat, 26 Jan 2019 22:50:51 +0800 Subject: [PATCH 05/31] fix npe --- .../java/org/jackhuang/hmcl/ui/account/AddAccountPane.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java index 9dd6b67eb..a346b08dc 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AddAccountPane.java @@ -56,6 +56,7 @@ import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; +import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableList; import static java.util.Objects.requireNonNull; import static org.jackhuang.hmcl.setting.ConfigHolder.config; @@ -138,6 +139,10 @@ public class AddAccountPane extends StackPane { private static final String[] ALLOWED_LINKS = { "register" }; public static List createHyperlinks(AuthlibInjectorServer server) { + if (server == null) { + return emptyList(); + } + Map links = server.getLinks(); List result = new ArrayList<>(); for (String key : ALLOWED_LINKS) { From f20c11a4e2d60b9902b9be9eaeb99f2570d04856 Mon Sep 17 00:00:00 2001 From: Feng Chang Date: Mon, 4 Feb 2019 02:18:24 +0800 Subject: [PATCH 06/31] Ensure sequential execution of configuration writer threads (#516) * Ensure sequential execution of configuration writer threads Signed-off-by: Chang Feng * Change method to add synchronized to action Signed-off-by: Chang Feng --- .../java/org/jackhuang/hmcl/util/InvocationDispatcher.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/InvocationDispatcher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/InvocationDispatcher.java index d67020aad..274e05edb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/InvocationDispatcher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/InvocationDispatcher.java @@ -33,7 +33,9 @@ public class InvocationDispatcher implements Consumer { public static InvocationDispatcher runOn(Consumer executor, Consumer action) { return new InvocationDispatcher<>(arg -> executor.accept(() -> { - action.accept(arg.get()); + synchronized (action) { + action.accept(arg.get()); + } })); } From 93f943d40c6ee36f0bb2f74b919c22589dce016c Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Mon, 4 Feb 2019 17:06:20 +0800 Subject: [PATCH 07/31] Fix crash in version settings introduced in d75c3bbf96852129a07996c07cdf0219a27a30df --- .../assets/fxml/version/version-settings.fxml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml index f07f6cf7c..a66289999 100644 --- a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml +++ b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml @@ -60,16 +60,7 @@