All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.ykiselev.gfx.sprite.font.builder.FontSettingTab Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017 Yuriy Kiselev ([email protected])
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.ykiselev.gfx.sprite.font.builder;

import com.typesafe.config.Config;
import com.typesafe.config.ConfigValueFactory;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.Tab;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.util.converter.IntegerStringConverter;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Yuriy Kiselev ([email protected]).
 */
public final class FontSettingTab implements BuilderTab {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private static final double COMBO_BOX_WIDTH = 200.0;

    private final Tab tab = new Tab();

    private final ComboBox fontWeightComboBox = new ComboBox<>();

    private final ComboBox fontPostureComboBox = new ComboBox<>();

    private final ComboBox fontSizeComboBox = new ComboBox<>();

    private final Text example = new Text();

    private final TextField exampleText = new TextField();

    private final ListView fontListView = new ListView<>();

    public Tab tab() {
        return tab;
    }

    public FontSettingTab(double leftPaneWidth) {
        tab.setText("Font Settings");
        tab.setClosable(false);

        final AnchorPane pane = new AnchorPane();
        tab.setContent(pane);

        final VBox leftBox = new VBox(4.0);
        leftBox.setPadding(new Insets(4.0));

        leftBox.setPrefWidth(leftPaneWidth);
        pane.getChildren().add(leftBox);

        AnchorPane.setTopAnchor(leftBox, 2.0);
        AnchorPane.setLeftAnchor(leftBox, 2.0);
        AnchorPane.setBottomAnchor(leftBox, 2.0);

        final TextField fontFilter = new TextField();
        fontFilter.textProperty().addListener((a, b, c) -> onFontFilterChanged(b, c));
        fontFilter.setPromptText("Start typing font family to filter list");

        fontListView.setEditable(false);
        fontListView.setFixedCellSize(Region.USE_COMPUTED_SIZE);
        fontListView.setCellFactory((listView) -> new FontListCell());
        fontListView.setItems(FXCollections.observableList(Font.getFamilies()));
        fontListView.getSelectionModel().selectedItemProperty().addListener((a, b, c) -> onNewFontSelected());

        VBox.setVgrow(fontListView, Priority.ALWAYS);

        leftBox.getChildren().addAll(fontFilter, fontListView);

        final VBox rightBox = new VBox(4.0);
        rightBox.setPadding(new Insets(4.0));
        pane.getChildren().add(rightBox);

        AnchorPane.setTopAnchor(rightBox, 2.0);
        AnchorPane.setLeftAnchor(rightBox, leftPaneWidth + 2.0);
        AnchorPane.setBottomAnchor(rightBox, 2.0);
        AnchorPane.setRightAnchor(rightBox, 2.0);

        final Label fontWeightLabel = new Label("Font weight:");
        fontWeightLabel.setLabelFor(fontWeightComboBox);
        fontWeightComboBox.setItems(FXCollections.observableArrayList(FontWeight.values()));
        fontWeightComboBox.getSelectionModel().select(FontWeight.NORMAL);
        fontWeightComboBox.setPrefWidth(COMBO_BOX_WIDTH);
        fontWeightComboBox.getSelectionModel().selectedItemProperty().addListener((a, b, c) -> onNewFontSelected());

        final Label fontPostureLabel = new Label("Font posture:");
        fontPostureLabel.setLabelFor(fontPostureComboBox);
        fontPostureComboBox.setItems(FXCollections.observableArrayList(FontPosture.values()));
        fontPostureComboBox.getSelectionModel().select(FontPosture.REGULAR);
        fontPostureComboBox.setPrefWidth(COMBO_BOX_WIDTH);
        fontPostureComboBox.getSelectionModel().selectedItemProperty().addListener((a, b, c) -> onNewFontSelected());

        final Label fontSizeLabel = new Label("Font size:");
        fontSizeLabel.setLabelFor(fontSizeComboBox);
        fontSizeComboBox.setEditable(true);
        fontSizeComboBox.setItems(FXCollections.observableArrayList(8, 10, 11, 12, 14, 16, 18, 20, 22, 24, 36, 48));
        fontSizeComboBox.getSelectionModel().select(Integer.valueOf(10));
        fontSizeComboBox.setPrefWidth(COMBO_BOX_WIDTH);
        fontSizeComboBox.getSelectionModel().selectedItemProperty().addListener((a, b, c) -> onNewFontSelected());
        fontSizeComboBox.setConverter(new IntegerStringConverter());

        exampleText.setPromptText("Leave empty to use font family as example text");
        exampleText.textProperty().addListener((a, b, c) -> onNewFontSelected());

        example.setText("Example text");
        example.setFocusTraversable(false);

        rightBox.getChildren().addAll(
                fontWeightLabel,
                fontWeightComboBox,
                fontPostureLabel,
                fontPostureComboBox,
                fontSizeLabel,
                fontSizeComboBox,
                exampleText,
                example
        );
        fontListView.getSelectionModel().selectFirst();
    }

    @Override
    public void load(Config state) {
        final Config cfg;
        try {
            cfg = state.getConfig("font");
        } catch (Exception ex) {
            logger.error("Failed to load font section!", ex);
            return;
        }
        try {
            final String fontName = cfg.getString("name");
            if (!StringUtils.isEmpty(fontName)) {
                final int index = fontListView.getItems().indexOf(fontName);
                if (index >= 0) {
                    fontListView.getSelectionModel().select(index);
                    fontListView.scrollTo(index);
                }
            }
        } catch (Exception ex) {
            logger.error("Failed to load font name!", ex);
        }
        try {
            fontWeightComboBox.getSelectionModel().select(
                    FontWeight.valueOf(cfg.getString("weight"))
            );
        } catch (Exception ex) {
            logger.error("Failed to load font weight!", ex);
        }
        try {
            fontPostureComboBox.getSelectionModel().select(
                    FontPosture.valueOf(cfg.getString("posture"))
            );
        } catch (Exception ex) {
            logger.error("Failed to load font posture!", ex);
        }
        try {
            fontSizeComboBox.getSelectionModel().select((Integer) cfg.getInt("size"));
        } catch (Exception ex) {
            logger.error("Failed to load font size!", ex);
        }
    }

    @Override
    public Config save(Config config) {
        try {
            return config.withValue("font.name", ConfigValueFactory.fromAnyRef(fontListView.getSelectionModel().getSelectedItem()))
                    .withValue("font.weight", ConfigValueFactory.fromAnyRef(ObjectUtils.toString(fontWeightComboBox.getSelectionModel().getSelectedItem())))
                    .withValue("font.posture", ConfigValueFactory.fromAnyRef(ObjectUtils.toString(fontPostureComboBox.getSelectionModel().getSelectedItem())))
                    .withValue("font.size", ConfigValueFactory.fromAnyRef(fontSizeComboBox.getSelectionModel().getSelectedItem()));
        } catch (Exception ex) {
            logger.error("Failed to save config!", ex);
        }
        return config;
    }

    private void onFontFilterChanged(String oldValue, String newValue) {
        final String prefix = newValue.toUpperCase();
        final String selectedItem = fontListView.getSelectionModel().getSelectedItem();
        final List items;
        if (StringUtils.isEmpty(newValue)) {
            items = Font.getFamilies();
        } else {
            items = Font.getFamilies()
                    .stream()
                    .filter((s) -> s.toUpperCase().startsWith(prefix))
                    .sorted()
                    .collect(Collectors.toList());
        }
        fontListView.setItems(FXCollections.observableList(items));
        fontListView.getSelectionModel().select(selectedItem);
        if (fontListView.getSelectionModel().getSelectedIndex() == -1) {
            fontListView.getSelectionModel().selectFirst();
        }
    }

    private void onNewFontSelected() {
        if (!StringUtils.isEmpty(exampleText.getText())) {
            example.setText(exampleText.getText());
        } else {
            example.setText(getSelectedFontFamily());
        }
        example.setFont(getSelectedFont());
    }

    public Font getSelectedFont() {
        return Font.font(
                getSelectedFontFamily(),
                getSelectedFontWeight(),
                getSelectedFontPosture(),
                getSelectedFontSize()
        );
    }

    private double getSelectedFontSize() {
        return fontSizeComboBox.getSelectionModel().getSelectedItem();
    }

    private FontPosture getSelectedFontPosture() {
        return fontPostureComboBox.getSelectionModel().getSelectedItem();
    }

    private FontWeight getSelectedFontWeight() {
        return fontWeightComboBox.getSelectionModel().getSelectedItem();
    }

    private String getSelectedFontFamily() {
        return fontListView.getSelectionModel().getSelectedItem();
    }

    private static final class FontListCell extends ListCell {

        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (item != null) {
                final Font font = Font.font(item);
                final Text text = new Text(item);

                text.setFont(font);
                text.setFontSmoothingType(FontSmoothingType.LCD);

                setGraphic(text);
            } else {
                setGraphic(null);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy