Package eu.hansolo.enzo.lcd.skin

Source Code of eu.hansolo.enzo.lcd.skin.LcdClockSkin

/*
* Copyright (c) 2013 by Gerrit Grunwald
*
* 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 eu.hansolo.enzo.lcd.skin;

import eu.hansolo.enzo.lcd.Alarm;
import eu.hansolo.enzo.lcd.LcdClock;
import javafx.collections.ListChangeListener;
import javafx.geometry.VPos;
import javafx.scene.Group;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.InnerShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;

import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.Random;


/**
* Created by
* User: hansolo
* Date: 19.08.13
* Time: 08:14
*/
public class LcdClockSkin extends SkinBase<LcdClock> implements Skin<LcdClock> {
    private static final double      PREFERRED_WIDTH    = 76;
    private static final double      PREFERRED_HEIGHT   = 40;
    private static final double      MINIMUM_WIDTH      = 5;
    private static final double      MINIMUM_HEIGHT     = 5;
    private static final double      MAXIMUM_WIDTH      = 1024;
    private static final double      MAXIMUM_HEIGHT     = 1024;
    private static final Color       DARK_NOISE_COLOR   = Color.rgb(100, 100, 100, 0.10);
    private static final Color       BRIGHT_NOISE_COLOR = Color.rgb(200, 200, 200, 0.05);
    private static final DropShadow  FOREGROUND_SHADOW  = new DropShadow();   
    private static       double      aspectRatio        = PREFERRED_HEIGHT / PREFERRED_WIDTH;
    private static       Text        oneTimeSegment     = new Text("8");
    private static       Text        oneSecondSegment   = new Text("8");
    private double                   width;
    private double                   height;
    private Pane                     pane;
    private Region                   main;
    private ImageView                crystalOverlay;
    private Image                    crystalImage;
    private Rectangle                crystalClip;
    private InnerShadow              mainInnerShadow0;
    private InnerShadow              mainInnerShadow1;
    private Region                   alarm;
    private Text                     timeText;
    private Text                     backgroundTimeText;
    private Text                     secondText;
    private Text                     backgroundSecondText;
    private Text                     title;
    private Text                     dateText;
    private Text                     dayOfWeekText;
    private DateTimeFormatter        dateFormat;
    private double                   valueOffsetRight;
    private double                   digitalFontSizeFactor;
    private Font                     timeFont;
    private Font                     secondFont;
    private Font                     titleFont;
    private Font                     smallFont;
    private StringBuilder            backgroundTextBuilder;
    private Group                    shadowGroup;


    // ******************** Constructors **************************************
    public LcdClockSkin(final LcdClock CONTROL) {
        super(CONTROL);
        aspectRatio = PREFERRED_HEIGHT / PREFERRED_WIDTH;
        valueOffsetRight = 0.0;
        digitalFontSizeFactor = 1.0;
        backgroundTextBuilder = new StringBuilder();
        FOREGROUND_SHADOW.setOffsetX(0);
        FOREGROUND_SHADOW.setOffsetY(1);
        FOREGROUND_SHADOW.setColor(Color.rgb(0, 0, 0, 0.5));
        FOREGROUND_SHADOW.setBlurType(BlurType.TWO_PASS_BOX);
        FOREGROUND_SHADOW.setRadius(2);
        adjustDateFormat();
        init();
        initGraphics();
        registerListeners();
    }


    // ******************** Initialization ************************************
    private void init() {
        if (Double.compare(getSkinnable().getPrefWidth(), 0.0) <= 0 || Double.compare(getSkinnable().getPrefHeight(),
                                                                                      0.0) <= 0 ||
            Double.compare(getSkinnable().getWidth(), 0.0) <= 0 || Double.compare(getSkinnable().getHeight(),
                                                                                  0.0) <= 0) {
            if (getSkinnable().getPrefWidth() > 0 && getSkinnable().getPrefHeight() > 0) {
                getSkinnable().setPrefSize(getSkinnable().getPrefWidth(), getSkinnable().getPrefHeight());
            } else {
                getSkinnable().setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT);
            }
        }

        if (Double.compare(getSkinnable().getMinWidth(), 0.0) <= 0 || Double.compare(getSkinnable().getMinHeight(),
                                                                                     0.0) <= 0) {
            getSkinnable().setMinSize(MINIMUM_WIDTH, MINIMUM_HEIGHT);
        }

        if (Double.compare(getSkinnable().getMaxWidth(), 0.0) <= 0 || Double.compare(getSkinnable().getMaxHeight(), 0.0) <= 0) {
            getSkinnable().setMaxSize(MAXIMUM_WIDTH, MAXIMUM_HEIGHT);
        }
    }

    private void initGraphics() {
        // load the fonts
        Font.loadFont(getClass().getResourceAsStream("/eu/hansolo/enzo/fonts/digital.ttf"), (0.5833333333 * PREFERRED_HEIGHT));         // "Digital-7"
        Font.loadFont(getClass().getResourceAsStream("/eu/hansolo/enzo/fonts/digitalreadout.ttf"), (0.5833333333 * PREFERRED_HEIGHT))// "Digital Readout Upright"
        Font.loadFont(getClass().getResourceAsStream("/eu/hansolo/enzo/fonts/digitalreadoutb.ttf"), (0.5833333333 * PREFERRED_HEIGHT)); // "Digital Readout Thick Upright"
        Font.loadFont(getClass().getResourceAsStream("/eu/hansolo/enzo/fonts/elektra.ttf"), (0.58333333 * PREFERRED_HEIGHT));           // "Elektra"
        Font.loadFont(getClass().getResourceAsStream("/eu/hansolo/enzo/fonts/opensans-semibold.ttf"), (0.58333333 * PREFERRED_HEIGHT)); // "OpenSans"

        main = new Region();
        main.getStyleClass().setAll("main");
        main.setOpacity(getSkinnable().isBackgroundVisible() ? 1 : 0);

        mainInnerShadow0 = new InnerShadow();
        mainInnerShadow0.setOffsetX(0.0);
        mainInnerShadow0.setOffsetY(0.0);
        mainInnerShadow0.setRadius(3.0 / 132.0 * PREFERRED_WIDTH);
        mainInnerShadow0.setColor(Color.web("0xffffff80"));
        mainInnerShadow0.setBlurType(BlurType.TWO_PASS_BOX);

        mainInnerShadow1 = new InnerShadow();
        mainInnerShadow1.setOffsetX(0.0);
        mainInnerShadow1.setOffsetY(1.0);
        mainInnerShadow1.setRadius(2.0 / 132.0 * PREFERRED_WIDTH);
        mainInnerShadow1.setColor(Color.web("0x000000a6"));
        mainInnerShadow1.setBlurType(BlurType.TWO_PASS_BOX);
        mainInnerShadow1.setInput(mainInnerShadow0);

        main.setEffect(getSkinnable().isMainInnerShadowVisible() ? mainInnerShadow1 : null);

        crystalClip = new Rectangle(0, 0, PREFERRED_WIDTH, PREFERRED_HEIGHT);
        crystalClip.setArcWidth(5);
        crystalClip.setArcHeight(5);

        crystalImage = createNoiseImage(PREFERRED_WIDTH, PREFERRED_HEIGHT, DARK_NOISE_COLOR, BRIGHT_NOISE_COLOR, 8);
        crystalOverlay = new ImageView(crystalImage);
        crystalOverlay.setClip(this.crystalClip);
        crystalOverlay.setOpacity(getSkinnable().isCrystalOverlayVisible() ? 1 : 0);

        alarm = new Region();
        alarm.getStyleClass().setAll("alarm");
        alarm.setOpacity(getSkinnable().getAlarms().isEmpty() || allAlarmsInactive() ? 0 : 1);

        backgroundTimeText = new Text("");
        backgroundTimeText.getStyleClass().setAll("fg-trsp");
        backgroundTimeText.setOpacity((LcdClock.LcdFont.LCD == getSkinnable().getTimeFont() || LcdClock.LcdFont.ELEKTRA == getSkinnable().getTimeFont()) ? 1 : 0);

        timeText = new Text("");
        timeText.getStyleClass().setAll("fg");

        backgroundSecondText = new Text("");
        backgroundSecondText.getStyleClass().setAll("fg-trsp");
        backgroundSecondText.setOpacity((LcdClock.LcdFont.LCD == getSkinnable().getTimeFont() || LcdClock.LcdFont.ELEKTRA == getSkinnable().getTimeFont()) ? 1 : 0);

        secondText = new Text("");
        secondText.getStyleClass().setAll("fg");

        title = new Text(getSkinnable().getTitle());
        title.getStyleClass().setAll("fg");

        dateText = new Text(getSkinnable().getTime().getMonthValue() + "/" + getSkinnable().getTime().getDayOfMonth() + "/" + getSkinnable().getTime().getYear());
        dateText.getStyleClass().setAll("fg");

        dayOfWeekText = new Text("");
        dayOfWeekText.getStyleClass().setAll("fg");

        shadowGroup = new Group();
        shadowGroup.setEffect(getSkinnable().isForegroundShadowVisible() ? FOREGROUND_SHADOW : null);
        shadowGroup.getChildren().setAll(alarm,
                                         timeText,
                                         secondText,
                                         title,
                                         dateText,
                                         dayOfWeekText);

        pane = new Pane();
        pane.getChildren().setAll(main,
                                  crystalOverlay,
                                  backgroundTimeText,
                                  backgroundSecondText,
                                  shadowGroup);

        getChildren().setAll(pane);

        resize();
        updateLcd();
    }

    private void registerListeners() {
        getSkinnable().widthProperty().addListener(observable -> handleControlPropertyChanged("RESIZE"));
        getSkinnable().heightProperty().addListener(observable -> handleControlPropertyChanged("RESIZE"));
        getSkinnable().clockProperty().addListener(observable -> handleControlPropertyChanged("UPDATE"));
        getSkinnable().timeProperty().addListener(observable -> handleControlPropertyChanged("UPDATE"));
        getSkinnable().titleProperty().addListener(observable -> handleControlPropertyChanged("UPDATE"));
        getSkinnable().localeProperty().addListener(observable -> handleControlPropertyChanged("UPDATE"));
        getSkinnable().prefWidthProperty().addListener(observable -> handleControlPropertyChanged("PREF_SIZE"));
        getSkinnable().prefHeightProperty().addListener(observable -> handleControlPropertyChanged("PREF_SIZE"));
        getSkinnable().timeFontProperty().addListener(observable -> handleControlPropertyChanged("FONT"));
        getSkinnable().smallFontProperty().addListener(observable -> handleControlPropertyChanged("FONT"));
        getSkinnable().backgroundVisibleProperty().addListener(observable -> handleControlPropertyChanged("BACKGROUND_VISIBLE"));
        getSkinnable().crystalOverlayVisibleProperty().addListener(observable -> handleControlPropertyChanged("CRYSTAL_OVERLAY_VISIBLE"));
        getSkinnable().mainInnerShadowVisibleProperty().addListener(observable -> handleControlPropertyChanged("MAIN_INNER_SHADOW_VISIBLE"));
        getSkinnable().foregroundShadowVisibleProperty().addListener(observable -> handleControlPropertyChanged("FOREGROUND_SHADOW_VISIBLE"));
        getSkinnable().dateFormatProperty().addListener(observable -> handleControlPropertyChanged("DATE_FORMAT"));
        getSkinnable().dateSeparatorProperty().addListener(observable -> handleControlPropertyChanged("DATE_FORMAT"));
       
        getSkinnable().getAlarms().addListener((ListChangeListener<Alarm>) change -> handleControlPropertyChanged("ALARM"));
        getSkinnable().getStyleClass().addListener((ListChangeListener<String>) change -> {
            resize();
            updateLcd();
        });
    }


    // ******************** Methods *******************************************
    protected void handleControlPropertyChanged(final String PROPERTY) {
        if ("UPDATE".equals(PROPERTY)) {
            updateLcd();
        } else if ("RESIZE".equals(PROPERTY)) {
            resize();
            updateLcd();
        } else if ("PREF_SIZE".equals(PROPERTY)) {
            aspectRatio = getSkinnable().getPrefHeight() / getSkinnable().getPrefWidth();
        } else if ("BACKGROUND_VISIBLE".equals(PROPERTY)) {
            main.setOpacity(getSkinnable().isBackgroundVisible() ? 1 : 0);
            crystalOverlay.setOpacity(getSkinnable().isBackgroundVisible() ? 1 : 0);
        } else if ("CRYSTAL_OVERLAY_VISIBLE".equals(PROPERTY)) {
            crystalOverlay.setOpacity(getSkinnable().isCrystalOverlayVisible() ? 1 : 0);
            resize();
        } else if ("MAIN_INNER_SHADOW_VISIBLE".equals(PROPERTY)) {
            main.setEffect(getSkinnable().isMainInnerShadowVisible() ? mainInnerShadow1 : null);
        } else if ("FOREGROUND_SHADOW_VISIBLE".equals(PROPERTY)) {
            shadowGroup.setEffect(getSkinnable().isForegroundShadowVisible() ? FOREGROUND_SHADOW : null);
        } else if ("FONT".equals(PROPERTY)) {
            updateFonts();
        } else if ("ALARM".equals(PROPERTY)) {
            alarm.setOpacity(getSkinnable().getAlarms().isEmpty() || allAlarmsInactive() ? 0 : 1);
        } else if ("DATE_FORMAT".equals(PROPERTY)) {
            adjustDateFormat();
            updateLcd();
        }
    }

    @Override protected double computeMinWidth(final double HEIGHT, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
        return super.computeMinWidth(Math.max(MINIMUM_HEIGHT, HEIGHT - TOP_INSET - BOTTOM_INSET), TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
    }
    @Override protected double computeMinHeight(final double WIDTH, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
        return super.computeMinHeight(Math.max(MINIMUM_WIDTH, WIDTH - LEFT_INSET - RIGHT_INSET), TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
    }

    @Override protected double computeMaxWidth(final double HEIGHT, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
        return super.computeMaxWidth(Math.min(MAXIMUM_HEIGHT, HEIGHT - TOP_INSET - BOTTOM_INSET), TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
    }
    @Override protected double computeMaxHeight(final double WIDTH, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
        return super.computeMaxHeight(Math.min(MAXIMUM_WIDTH, WIDTH - LEFT_INSET - RIGHT_INSET), TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
    }

    @Override protected double computePrefWidth(final double HEIGHT, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
        double prefHeight = PREFERRED_HEIGHT;
        if (HEIGHT != -1) {
            prefHeight = Math.max(0, HEIGHT - TOP_INSET - BOTTOM_INSET);
        }
        return super.computePrefWidth(prefHeight, TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
    }
    @Override protected double computePrefHeight(final double WIDTH, double TOP_INSET, double RIGHT_INSET, double BOTTOM_INSET, double LEFT_INSET) {
        double prefWidth = PREFERRED_WIDTH;
        if (WIDTH != -1) {
            prefWidth = Math.max(0, WIDTH - LEFT_INSET - RIGHT_INSET);
        }
        return super.computePrefHeight(prefWidth, TOP_INSET, RIGHT_INSET, BOTTOM_INSET, LEFT_INSET);
    }


    // ******************** Private Methods ***********************************
    private String ensureTwoDigits(final int NUMBER) {
        if (NUMBER < 10) return "0" + NUMBER;
        return Integer.toString(NUMBER);
    }

    private void adjustDateFormat() {
        switch (getSkinnable().getDateFormat()) {
            case DAY_MONTH_YEAR:
                dateFormat = DateTimeFormatter.ofPattern("dd" + getSkinnable().getDateSeparator().chr + "MM" + getSkinnable().getDateSeparator().chr + "yyyy");
                break;
            case YEAR_MONTH_DAY:
            default:
                dateFormat = DateTimeFormatter.ofPattern("yyyy" + getSkinnable().getDateSeparator().chr + "MM" + getSkinnable().getDateSeparator().chr + "dd");
                break;
        }
    }
   
    private boolean allAlarmsInactive() {
        boolean allAlarmsInactive = true;
        for (Alarm alarm : getSkinnable().getAlarms()) {
            if (alarm.isArmed()) {
                allAlarmsInactive = false;
                break;
            }
        }
        return allAlarmsInactive;
    }

    private Image createNoiseImage(final double WIDTH, final double HEIGHT, final Color DARK_COLOR, final Color BRIGHT_COLOR, final double ALPHA_VARIATION_IN_PERCENT) {
        int width  = WIDTH <= 0 ? (int) PREFERRED_WIDTH : (int) WIDTH;
        int height = HEIGHT <= 0 ? (int) PREFERRED_HEIGHT : (int) HEIGHT;
        double alphaVariationInPercent      = getSkinnable().clamp(0, 100, ALPHA_VARIATION_IN_PERCENT);
        final WritableImage IMAGE           = new WritableImage(width, height);
        final PixelWriter   PIXEL_WRITER    = IMAGE.getPixelWriter();
        final Random        BW_RND          = new Random();
        final Random        ALPHA_RND       = new Random();
        final double        ALPHA_START     = alphaVariationInPercent / 100 / 2;
        final double        ALPHA_VARIATION = alphaVariationInPercent / 100;
        Color  noiseColor;
        double noiseAlpha;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                noiseColor = BW_RND.nextBoolean() == true ? BRIGHT_COLOR : DARK_COLOR;
                noiseAlpha = getSkinnable().clamp(0, 1, ALPHA_START + ALPHA_RND.nextDouble() * ALPHA_VARIATION);
                PIXEL_WRITER.setColor(x, y, Color.color(noiseColor.getRed(), noiseColor.getGreen(), noiseColor.getBlue(), noiseAlpha));
            }
        }
        return IMAGE;
    }

    private void updateFonts() {
        digitalFontSizeFactor = 1.0;
        switch(getSkinnable().getTimeFont()) {
            case LCD:
                digitalFontSizeFactor = 1.05;
                timeFont   = Font.font("Digital-7", (0.7 * height));
                secondFont = Font.font("Digital-7", FontWeight.NORMAL, (0.2 * height));
                break;
            case DIGITAL:
                digitalFontSizeFactor = 0.7;
                timeFont   = Font.font("Digital Readout Upright", (0.7 * height));
                secondFont = Font.font("Digital Readout Upright", FontWeight.NORMAL, (0.2 * height));
                break;
            case DIGITAL_BOLD:
                digitalFontSizeFactor = 0.7;
                timeFont   = Font.font("Digital Readout Thick Upright", (0.7 * height));
                secondFont = Font.font("Digital Readout Thick Upright", FontWeight.NORMAL, (0.2 * height));
                break;
            case ELEKTRA:
                digitalFontSizeFactor = 0.8;
                timeFont   = Font.font("Elektra", (0.7 * height));
                secondFont = Font.font("Elektra", FontWeight.NORMAL, (0.186 * height));
                break;
            case STANDARD:
            default:
                digitalFontSizeFactor = 0.7;
                timeFont   = Font.font("Open Sans", FontWeight.NORMAL, (0.6 * height));
                secondFont = Font.font("Open Sans", FontWeight.NORMAL, (0.2 * height));
                break;
        }
        backgroundTimeText.setFont(timeFont);
        backgroundTimeText.setOpacity((LcdClock.LcdFont.LCD == getSkinnable().getTimeFont() ||
                                       LcdClock.LcdFont.DIGITAL == getSkinnable().getTimeFont() ||
                                       LcdClock.LcdFont.DIGITAL_BOLD == getSkinnable().getTimeFont() ||
                                       LcdClock.LcdFont.ELEKTRA == getSkinnable().getTimeFont()) ? 1 : 0);

        backgroundSecondText.setFont(secondFont);
        backgroundSecondText.setOpacity((LcdClock.LcdFont.LCD == getSkinnable().getTimeFont() ||
                                         LcdClock.LcdFont.DIGITAL == getSkinnable().getTimeFont() ||
                                         LcdClock.LcdFont.DIGITAL_BOLD == getSkinnable().getTimeFont() ||
                                         LcdClock.LcdFont.ELEKTRA == getSkinnable().getTimeFont()) ? 1 : 0);

        timeText.setFont(timeFont);
        titleFont = Font.font(getSkinnable().getTitleFont(), FontWeight.BOLD, (0.15 * height));
        smallFont = Font.font(getSkinnable().getSmallFont(), FontWeight.NORMAL, (0.12 * height));
    }

    private void updateBackgroundText() {
        // Setup the semitransparent background timeText
        backgroundTimeText.setTextOrigin(VPos.BASELINE);
        backgroundTimeText.setTextAlignment(TextAlignment.RIGHT);

        backgroundSecondText.setTextOrigin(VPos.BASELINE);
        backgroundSecondText.setTextAlignment(TextAlignment.RIGHT);

        // Setup the semitransparent background timeText
        // Width of one time segment
        oneTimeSegment.setFont(timeFont);
        if (LcdClock.LcdFont.LCD == getSkinnable().getTimeFont()) {
            oneTimeSegment.setText("8");
        } else if (LcdClock.LcdFont.DIGITAL == getSkinnable().getTimeFont()) {
            oneTimeSegment.setText("_");
        } else if (LcdClock.LcdFont.DIGITAL_BOLD == getSkinnable().getTimeFont()) {
            oneTimeSegment.setText("_");
        } else if (LcdClock.LcdFont.ELEKTRA == getSkinnable().getTimeFont()) {
            oneTimeSegment.setText("_");
        }

        // Width of one time segment
        oneSecondSegment.setFont(secondFont);
        if (LcdClock.LcdFont.LCD == getSkinnable().getTimeFont()) {
            oneSecondSegment.setText("8");
        } else if (LcdClock.LcdFont.DIGITAL == getSkinnable().getTimeFont()) {
            oneSecondSegment.setText("_");
        } else if (LcdClock.LcdFont.DIGITAL_BOLD == getSkinnable().getTimeFont()) {
            oneSecondSegment.setText("_");
        } else if (LcdClock.LcdFont.ELEKTRA == getSkinnable().getTimeFont()) {
            oneSecondSegment.setText("_");
        }

        // Add segments to background timeText
        backgroundTextBuilder.setLength(0);
        backgroundTextBuilder.append(oneTimeSegment.getText());
        backgroundTextBuilder.append(oneTimeSegment.getText());
        backgroundTextBuilder.append(":");
        backgroundTextBuilder.append(oneTimeSegment.getText());
        backgroundTextBuilder.append(oneTimeSegment.getText());

        backgroundTimeText.setText(backgroundTextBuilder.toString());

        backgroundSecondText.setText("88");
    }

    private void updateLcd() {
        timeText.setText(ensureTwoDigits(getSkinnable().getTime().getHour()) + ":" + ensureTwoDigits(getSkinnable().getTime().getMinute()));
        secondText.setText(ensureTwoDigits(getSkinnable().getTime().getSecond()));
        updateBackgroundText();

        // Visualize the lcd semitransparent background timeText
        backgroundTimeText.setX(width - 2 - backgroundTimeText.getLayoutBounds().getWidth() - valueOffsetRight);
        backgroundTimeText.setY(height - (backgroundTimeText.getLayoutBounds().getHeight() * digitalFontSizeFactor) * 0.5);

        timeText.setX((width - 2 - timeText.getLayoutBounds().getWidth()) - valueOffsetRight);

        // Update the title
        title.setText(getSkinnable().getTitle());
        title.setX((width - title.getLayoutBounds().getWidth()) * 0.5);

        // Update the lower center timeText
        dayOfWeekText.setText(getSkinnable().getTime().getDayOfWeek().getDisplayName(TextStyle.FULL_STANDALONE, getSkinnable().getLocale()));
        dayOfWeekText.setX(0.0416666667 * height);

        // Update the lower right timeText       
        dateText.setText(dateFormat.format(getSkinnable().getTime()));       
        dateText.setX(width - dateText.getLayoutBounds().getWidth() - 0.0416666667 * height);
        dateText.setY(main.getLayoutY() + height - 3 - 0.0416666667 * height);
    }

    private void resize() {
        width  = getSkinnable().getWidth();
        height = getSkinnable().getHeight();
        if (getSkinnable().isKeepAspect()) {
            if (aspectRatio * width > height) {
                width = 1 / (aspectRatio / height);
            } else if (1 / (aspectRatio / height) > width) {
                height = aspectRatio * width;
            }
        }

        if (width > 0 && height > 0) {
            main.setPrefSize(width, height);
            mainInnerShadow0.setRadius(3.0 / 132.0 * height);
            mainInnerShadow1.setRadius(2.0 / 132.0 * height);

            if (crystalOverlay.isVisible()) {
                crystalClip.setWidth(width);
                crystalClip.setHeight(height);
                crystalOverlay.setImage(createNoiseImage(width, height, DARK_NOISE_COLOR, BRIGHT_NOISE_COLOR, 8));
                crystalOverlay.setCache(true);
            }

            alarm.setPrefSize(0.15 * height, 0.15 * height);
            alarm.setTranslateX(width - alarm.getPrefWidth() - height * 0.05);
            alarm.setTranslateY(height * 0.42 - alarm.getPrefHeight());

            updateFonts();

            // Setup the lcd unit
            secondText.setFont(secondFont);
            secondText.setTextOrigin(VPos.BASELINE);
            secondText.setTextAlignment(TextAlignment.RIGHT);

            secondText.setX((width - secondText.getLayoutBounds().getWidth()) - height * 0.04);
            secondText.setY(height - (timeText.getLayoutBounds().getHeight() * digitalFontSizeFactor) * 0.5);
            valueOffsetRight = (secondText.getLayoutBounds().getWidth() + height * 0.0833333333); // distance between value and unit

            timeText.setX(width - 2 - timeText.getLayoutBounds().getWidth() - valueOffsetRight);
            timeText.setY(height - (timeText.getLayoutBounds().getHeight() * digitalFontSizeFactor) * 0.5);

            // Visualize the lcd semitransparent background timeText
            updateBackgroundText();

            backgroundTimeText.setX(width - 2 - backgroundTimeText.getLayoutBounds().getWidth() - valueOffsetRight);
            backgroundTimeText.setY(height - (backgroundTimeText.getLayoutBounds().getHeight() * digitalFontSizeFactor) * 0.5);

            backgroundSecondText.setX((width - secondText.getLayoutBounds().getWidth()) - height * 0.04);
            backgroundSecondText.setY(height - (timeText.getLayoutBounds().getHeight() * digitalFontSizeFactor) * 0.5);

            // Setup the font for the lcd title, number system, min measured, max measure and former value
            // Title
            title.setFont(titleFont);
            title.setTextOrigin(VPos.BASELINE);
            title.setTextAlignment(TextAlignment.CENTER);
            title.setText(getSkinnable().getTime().getDayOfWeek().name());
            title.setX((width - title.getLayoutBounds().getWidth()) * 0.5);
            title.setY(main.getLayoutY() + title.getLayoutBounds().getHeight() - 0.04 * height + 2);

            // Date
            dateText.setFont(smallFont);
            dateText.setTextOrigin(VPos.BASELINE);
            dateText.setTextAlignment(TextAlignment.RIGHT);
            dateText.setText(getSkinnable().getTime().getMonthValue() + "/" + getSkinnable().getTime().getDayOfMonth() + "/" + getSkinnable().getTime().getYear());
            dateText.setX(main.getLayoutX() + (width - dateText.getLayoutBounds().getWidth()) * 0.5);
            dateText.setY(main.getLayoutY() + height - 3 - 0.0416666667 * height);

            // Day of week
            dayOfWeekText.setFont(smallFont);
            dayOfWeekText.setTextOrigin(VPos.BASELINE);
            dayOfWeekText.setTextAlignment(TextAlignment.LEFT);
            dayOfWeekText.setX(0.0416666667 * height);
            dayOfWeekText.setY(main.getLayoutY() + height - 3 - 0.0416666667 * height);
        }
    }
}
TOP

Related Classes of eu.hansolo.enzo.lcd.skin.LcdClockSkin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.