Implement changing font family at runtime
This commit is contained in:
parent
cd16046340
commit
c2e03d2193
@ -55,10 +55,7 @@ public class Launcher extends Application {
|
||||
tm.setTheme(tm.getAvailableThemes().get(0));
|
||||
if (IS_DEV_MODE) { startCssFX(scene); }
|
||||
|
||||
scene.getStylesheets().addAll(
|
||||
Resources.resolve("assets/fonts/index.css"),
|
||||
Resources.resolve("assets/styles/index.css")
|
||||
);
|
||||
scene.getStylesheets().addAll(Resources.resolve("assets/styles/index.css"));
|
||||
|
||||
stage.setScene(scene);
|
||||
stage.setTitle(System.getProperty("app.name"));
|
||||
|
@ -5,13 +5,16 @@ import atlantafx.sampler.page.AbstractPage;
|
||||
import atlantafx.sampler.page.SampleBlock;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Spinner;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
@ -23,6 +26,8 @@ import static atlantafx.base.theme.Styles.*;
|
||||
|
||||
public class TypographyPage extends AbstractPage {
|
||||
|
||||
private static final double CONTROL_WIDTH = 200;
|
||||
|
||||
public static final String NAME = "Typography";
|
||||
|
||||
@Override
|
||||
@ -36,18 +41,20 @@ public class TypographyPage extends AbstractPage {
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
Spinner<Integer> fontSizeSpinner = fontSizeSpinner();
|
||||
fontSizeSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
|
||||
fontSizeSpinner.setPrefWidth(200);
|
||||
var controlsGrid = new GridPane();
|
||||
controlsGrid.setVgap(10);
|
||||
controlsGrid.setHgap(20);
|
||||
|
||||
var fontSizeBox = new HBox(20, new Label("Font size"), fontSizeSpinner);
|
||||
fontSizeBox.setAlignment(Pos.CENTER_LEFT);
|
||||
controlsGrid.add(new Label("Font family"), 0, 0);
|
||||
controlsGrid.add(fontFamilyChooser(), 1, 0);
|
||||
controlsGrid.add(new Label("Font size"), 0, 1);
|
||||
controlsGrid.add(fontSizeSpinner(), 1, 1);
|
||||
|
||||
var fontSizeSample = fontSizeSample();
|
||||
fontSizeSampleContent = (GridPane) fontSizeSample.getContent();
|
||||
|
||||
userContent.getChildren().setAll(
|
||||
fontSizeBox,
|
||||
controlsGrid,
|
||||
fontSizeSample.getRoot(),
|
||||
fontWeightSample().getRoot(),
|
||||
fontStyleSample().getRoot(),
|
||||
@ -57,19 +64,42 @@ public class TypographyPage extends AbstractPage {
|
||||
);
|
||||
}
|
||||
|
||||
private ComboBox<String> fontFamilyChooser() {
|
||||
final var tm = ThemeManager.getInstance();
|
||||
|
||||
ComboBox<String> comboBox = new ComboBox<>();
|
||||
comboBox.getItems().add(tm.getFontFamily());
|
||||
comboBox.getItems().addAll(FXCollections.observableArrayList(Font.getFamilies()));
|
||||
comboBox.setPrefWidth(CONTROL_WIDTH);
|
||||
comboBox.getSelectionModel().select(tm.getFontFamily());
|
||||
|
||||
comboBox.valueProperty().addListener((obs, old, val) -> {
|
||||
if (val != null) {
|
||||
tm.setFontFamily(val);
|
||||
tm.reloadCustomCSS();
|
||||
updateFontInfo(Duration.ofMillis(1000));
|
||||
}
|
||||
});
|
||||
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private Spinner<Integer> fontSizeSpinner() {
|
||||
var spinner = new Spinner<Integer>(10, 24, 14);
|
||||
final var tm = ThemeManager.getInstance();
|
||||
|
||||
var spinner = new Spinner<Integer>(10, 24, tm.getFontSize());
|
||||
spinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
|
||||
spinner.setPrefWidth(CONTROL_WIDTH);
|
||||
|
||||
// Instead of this we should obtain font size from a rendered node.
|
||||
// But since it's not trivial (thanks to JavaFX doesn't expose relevant API)
|
||||
// we just keep current font size inside ThemeManager singleton.
|
||||
// It works fine if ThemeManager default font size value matches
|
||||
// default theme font size value.
|
||||
spinner.getValueFactory().setValue(ThemeManager.getInstance().getFontSize());
|
||||
spinner.getValueFactory().setValue(tm.getFontSize());
|
||||
|
||||
spinner.valueProperty().addListener((obs, old, val) -> {
|
||||
if (val != null && getScene() != null) {
|
||||
var tm = ThemeManager.getInstance();
|
||||
if (val != null) {
|
||||
tm.setFontSize(val);
|
||||
tm.reloadCustomCSS();
|
||||
updateFontInfo(Duration.ofMillis(1000));
|
||||
|
@ -19,6 +19,7 @@ public final class ThemeManager {
|
||||
|
||||
private static final String DUMMY_STYLESHEET = Resources.getResource("assets/styles/empty.css").toString();
|
||||
private static final PseudoClass USER_CUSTOM = PseudoClass.getPseudoClass("user-custom");
|
||||
private static final String DEFAULT_FONT_FAMILY_NAME = "Application Default";
|
||||
|
||||
// KEY | VALUE
|
||||
// -fx-property | value;
|
||||
@ -26,9 +27,10 @@ public final class ThemeManager {
|
||||
// .foo | -fx-property: value;
|
||||
private final Map<String, String> customCSSRules = new LinkedHashMap<>();
|
||||
|
||||
private Theme currentTheme = null;
|
||||
private int currentFontSize = 14;
|
||||
private Scene scene;
|
||||
private Theme currentTheme = null;
|
||||
private String fontFamily = DEFAULT_FONT_FAMILY_NAME;
|
||||
private int fontSize = 14;
|
||||
|
||||
public Scene getScene() {
|
||||
return scene;
|
||||
@ -66,10 +68,7 @@ public final class ThemeManager {
|
||||
|
||||
public List<Theme> getAvailableThemes() {
|
||||
var themes = new ArrayList<Theme>();
|
||||
var appStylesheets = new URI[] {
|
||||
URI.create(Resources.resolve("assets/fonts/index.css")),
|
||||
URI.create(Resources.resolve("assets/styles/index.css"))
|
||||
};
|
||||
var appStylesheets = new URI[] { URI.create(Resources.resolve("assets/styles/index.css")) };
|
||||
|
||||
if (Launcher.IS_DEV_MODE) {
|
||||
themes.add(new ExternalTheme("Primer Light", DUMMY_STYLESHEET, merge(
|
||||
@ -95,14 +94,23 @@ public final class ThemeManager {
|
||||
return themes;
|
||||
}
|
||||
|
||||
public String getFontFamily() {
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
public void setFontFamily(String fontFamily) {
|
||||
setCustomDeclaration("-fx-font-family", "\"" + fontFamily + "\"");
|
||||
this.fontFamily = fontFamily;
|
||||
}
|
||||
|
||||
public int getFontSize() {
|
||||
return currentFontSize;
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
public void setFontSize(int fontSize) {
|
||||
setCustomDeclaration("-fx-font-size", fontSize + "px");
|
||||
setCustomRule(".ikonli-font-icon", String.format("-fx-icon-size: %dpx;", fontSize + 2));
|
||||
currentFontSize = fontSize;
|
||||
this.fontSize = fontSize;
|
||||
}
|
||||
|
||||
private void setCustomDeclaration(String property, String value) {
|
||||
@ -139,8 +147,6 @@ public final class ThemeManager {
|
||||
css.append("}\n");
|
||||
});
|
||||
|
||||
System.out.println(css);
|
||||
|
||||
scene.getStylesheets().removeIf(uri -> uri.startsWith("data:text/css"));
|
||||
scene.getStylesheets().add(
|
||||
"data:text/css;base64," + Base64.getEncoder().encodeToString(css.toString().getBytes(UTF_8))
|
||||
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Note that each font-family have to be unique. That's because unlike web browsers
|
||||
* OpenJFX CSS parser doesn't support `font-weight` and `font-style` attributes
|
||||
* in the `@font-face` at-rule. It just silently ignores them. So, the font variant
|
||||
* can only be expressed via font name. OpenJFX always uses font transformation,
|
||||
* even when corresponding font variant provided explicitly.
|
||||
*
|
||||
* See, CSS Reference guide:
|
||||
* https://openjfx.io/javadoc/17/javafx.graphics/javafx/scene/doc-files/cssref.html
|
||||
* > Although the parser will parse the syntax, all @font‑face descriptors
|
||||
* > are ignored except for the src descriptor. The src descriptor is expected
|
||||
* > to be a <url>. The format hint is ignored.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter UI Regular";
|
||||
src: url('Inter/InterUI-Regular.otf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter UI Medium";
|
||||
src: url('Inter/InterUI-Medium.otf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter UI Bold";
|
||||
src: url('Inter/InterUI-Bold.otf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter UI Italic";
|
||||
src: url('Inter/InterUI-Italic.otf');
|
||||
}
|
@ -1,7 +1,12 @@
|
||||
/** SPDX-License-Identifier: MIT */
|
||||
|
||||
@font-face {
|
||||
font-family: "Application Default";
|
||||
src: url('../fonts/Inter-Regular.otf');
|
||||
}
|
||||
|
||||
.root {
|
||||
-fx-font-family: "Inter";
|
||||
-fx-font-family: "Application Default";
|
||||
}
|
||||
.root:showcase-mode #sidebar,
|
||||
.root:showcase-mode .page > .header {
|
||||
|
@ -72,7 +72,6 @@
|
||||
|
||||
// default props inherited by all nodes
|
||||
-fx-background-color: -color-bg-default;
|
||||
-fx-font-family: "Inter";
|
||||
-fx-font-size: cfg.$font-default;
|
||||
|
||||
// these are needed for Popup
|
||||
|
Loading…
Reference in New Issue
Block a user