diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/LauncherSettings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/LauncherSettings.java index a92fdf5fce5..eaf94c434bd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/LauncherSettings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/LauncherSettings.java @@ -476,6 +476,15 @@ public StringProperty launcherFontFamilyProperty() { return launcherFontFamily; } + /// The launcher chrome font size. + @SerializedName("launcherFontSize") + private final DoubleProperty launcherFontSize = new SimpleDoubleProperty(FontManager.DEFAULT_FONT_SIZE); + + /// Returns the launcher chrome font size property. + public DoubleProperty launcherFontSizeProperty() { + return launcherFontSize; + } + // General UI /// Whether UI animations are disabled. diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/StyleSheets.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/StyleSheets.java index 9c9175329a2..3c754375426 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/StyleSheets.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/StyleSheets.java @@ -39,6 +39,7 @@ import java.util.Base64; import java.util.Locale; +import static org.jackhuang.hmcl.setting.SettingsManager.settings; import static org.jackhuang.hmcl.util.logging.Logger.LOG; /** @@ -61,6 +62,7 @@ public final class StyleSheets { stylesheets = FXCollections.observableList(Arrays.asList(array)); FontManager.fontProperty().addListener(o -> stylesheets.set(FONT_STYLE_SHEET_INDEX, getFontStyleSheet())); + settings().launcherFontSizeProperty().addListener(o -> stylesheets.set(FONT_STYLE_SHEET_INDEX, getFontStyleSheet())); Themes.colorSchemeProperty().addListener(o -> { stylesheets.set(THEME_STYLE_SHEET_INDEX, getThemeStyleSheet()); stylesheets.set(BRIGHTNESS_SHEET_INDEX, getBrightnessStyleSheet()); @@ -90,48 +92,65 @@ private static String getFontStyleSheet() { final String defaultCss = "/assets/css/font.css"; final FontManager.FontReference font = FontManager.getFont(); - if (font == null || "System".equals(font.family())) - return defaultCss; + final boolean hasCustomFont = font != null && !"System".equals(font.family()); + final double fontSize = settings().launcherFontSizeProperty().get(); - String fontFamily = font.family(); - String style = font.style(); - String weight = null; - String posture = null; - - if (style != null) { - style = style.toLowerCase(Locale.ROOT); - - if (style.contains("thin")) - weight = "100"; - else if (style.contains("extralight") || style.contains("extra light") || style.contains("ultralight") | style.contains("ultra light")) - weight = "200"; - else if (style.contains("medium")) - weight = "500"; - else if (style.contains("semibold") || style.contains("semi bold") || style.contains("demibold") || style.contains("demi bold")) - weight = "600"; - else if (style.contains("extrabold") || style.contains("extra bold") || style.contains("ultrabold") || style.contains("ultra bold")) - weight = "800"; - else if (style.contains("black") || style.contains("heavy")) - weight = "900"; - else if (style.contains("light")) - weight = "lighter"; - else if (style.contains("bold")) - weight = "bold"; - - posture = style.contains("italic") || style.contains("oblique") ? "italic" : null; - } + if (!hasCustomFont && fontSize == FontManager.DEFAULT_FONT_SIZE) + return defaultCss; StringBuilder builder = new StringBuilder(); builder.append(".root {"); - builder.append("-fx-font-family:\"").append(fontFamily).append("\";"); - if (weight != null) - builder.append("-fx-font-weight:").append(weight).append(";"); + if (hasCustomFont) { + String fontFamily = font.family(); + String style = font.style(); + String weight = null; + String posture = null; + + if (style != null) { + style = style.toLowerCase(Locale.ROOT); + + if (style.contains("thin")) + weight = "100"; + else if (style.contains("extralight") || style.contains("extra light") || style.contains("ultralight") | style.contains("ultra light")) + weight = "200"; + else if (style.contains("medium")) + weight = "500"; + else if (style.contains("semibold") || style.contains("semi bold") || style.contains("demibold") || style.contains("demi bold")) + weight = "600"; + else if (style.contains("extrabold") || style.contains("extra bold") || style.contains("ultrabold") || style.contains("ultra bold")) + weight = "800"; + else if (style.contains("black") || style.contains("heavy")) + weight = "900"; + else if (style.contains("light")) + weight = "lighter"; + else if (style.contains("bold")) + weight = "bold"; + + posture = style.contains("italic") || style.contains("oblique") ? "italic" : null; + } + + builder.append("-fx-font-family:\"").append(fontFamily).append("\";"); + + if (weight != null) + builder.append("-fx-font-weight:").append(weight).append(";"); - if (posture != null) - builder.append("-fx-font-style:").append(posture).append(";"); + if (posture != null) + builder.append("-fx-font-style:").append(posture).append(";"); + } - builder.append('}'); + if (fontSize != FontManager.DEFAULT_FONT_SIZE) { + builder.append("-fx-font-size:").append(fontSize).append("px;"); + builder.append('}'); + // Override Modena UA which sets explicit font-size on common controls, + // blocking inheritance from .root. The ".root " prefix gives higher + // specificity than Modena's plain ".label" etc., and author sheets + // have higher priority than user-agent sheets. + builder.append(".root .label,.root .button,.root .check-box,.root .radio-button,.root .hyperlink{") + .append("-fx-font-size:").append(fontSize).append("px;}"); + } else { + builder.append('}'); + } return toStyleSheetUri(builder.toString(), defaultCss); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java index 7be7564d975..dc846968aeb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java @@ -1197,24 +1197,39 @@ protected Node createRightNode() { { HBox hBox = new HBox(); - hBox.setSpacing(8); + hBox.setSpacing(3); FontComboBox cboFont = new FontComboBox(); cboFont.setValue(settings().launcherFontFamilyProperty().get()); FXUtils.onChange(cboFont.valueProperty(), FontManager::setFontFamily); + JFXTextField txtFontSize = new JFXTextField(); + FXUtils.setLimitWidth(txtFontSize, 50); + FXUtils.bind(txtFontSize, settings().launcherFontSizeProperty(), SafeStringConverter.fromFiniteDouble() + .restrict(it -> it > 0) + .fallbackTo(FontManager.DEFAULT_FONT_SIZE) + .asPredicate(Validator.addTo(txtFontSize))); + JFXButton clearButton = FXUtils.newToggleButton4(SVG.RESTORE); clearButton.setOnAction(e -> cboFont.setValue(null)); FXUtils.installFastTooltip(clearButton, i18n("button.reset")); - hBox.getChildren().setAll(cboFont, clearButton); + hBox.getChildren().setAll(cboFont, txtFontSize, clearButton); borderPane.setRight(hBox); } } - vbox.getChildren().add(new Label("Hello Minecraft! Launcher")); + Label lblFontDisplay = new Label("Hello Minecraft! Launcher"); + lblFontDisplay.fontProperty().bind(Bindings.createObjectBinding( + () -> Font.font( + Lang.requireNonNullElse(settings().launcherFontFamilyProperty().get(), + Font.getDefault().getFamily()), + settings().launcherFontSizeProperty().get()), + settings().launcherFontFamilyProperty(), settings().launcherFontSizeProperty())); + + vbox.getChildren().add(lblFontDisplay); fontPane.getContent().add(vbox); } diff --git a/docs/schemas/launcher-settings/1.0.0.json b/docs/schemas/launcher-settings/1.0.0.json index bd8b769826b..45d4e78d957 100644 --- a/docs/schemas/launcher-settings/1.0.0.json +++ b/docs/schemas/launcher-settings/1.0.0.json @@ -138,6 +138,9 @@ "launcherFontFamily": { "type": "string" }, + "launcherFontSize": { + "type": "number" + }, "windowTransparent": { "type": "boolean" },