Package eu.hansolo.enzo.heatcontrol.skin

Source Code of eu.hansolo.enzo.heatcontrol.skin.HeatControlSkin

/*
* 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.heatcontrol.skin;

import eu.hansolo.enzo.common.Fonts;
import eu.hansolo.enzo.common.ValueEvent;
import eu.hansolo.enzo.heatcontrol.GradientLookup;
import eu.hansolo.enzo.heatcontrol.HeatControl;
import javafx.animation.FadeTransition;
import javafx.animation.ParallelTransition;
import javafx.animation.PauseTransition;
import javafx.animation.SequentialTransition;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Point2D;
import javafx.geometry.VPos;
import javafx.scene.CacheHint;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.InnerShadow;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TouchEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.text.Text;
import javafx.scene.transform.Rotate;
import javafx.util.Duration;

import java.util.Locale;


/**
* User: hansolo
* Date: 08.11.13
* Time: 16:35
*/
public class HeatControlSkin extends SkinBase<HeatControl> implements Skin<HeatControl> {
    private static final double      PREFERRED_WIDTH  = 200;
    private static final double      PREFERRED_HEIGHT = 200;
    private static final double      MINIMUM_WIDTH    = 50;
    private static final double      MINIMUM_HEIGHT   = 50;
    private static final double      MAXIMUM_WIDTH    = 1024;
    private static final double      MAXIMUM_HEIGHT   = 1024;
    private static boolean           userAction;
    private double                   size;
    private double                   centerX;
    private double                   centerY;
    private Pane                     pane;
    private Circle                   background;
    private Canvas                   ticksCanvas;
    private GraphicsContext          ticks;
    private Region                   targetIndicator;
    private Rotate                   targetIndicatorRotate;
    private boolean                  targetExceeded;
    private Region                   valueIndicator;
    private Rotate                   valueIndicatorRotate;
    private Text                     infoText;
    private Text                     value;
    private String                   newTarget;
    private GradientLookup           gradientLookup;  
    private InnerShadow              innerShadow;
    private double                   angleStep;
    private double                   interactiveAngle;
    private EventHandler<MouseEvent> mouseEventHandler;
    private EventHandler<TouchEvent> touchEventHandler;   


    // ******************** Constructors **************************************
    public HeatControlSkin(HeatControl heatControl) {
        super(heatControl);
        userAction        = false;
        newTarget         = "";
        gradientLookup    = new GradientLookup(new Stop(0.10, Color.web("#3221c9")),                                              
                                               new Stop(0.20, Color.web("#216ec9")),
                                               new Stop(0.30, Color.web("#21bac9")),
                                               new Stop(0.40, Color.web("#30cb22")),
                                               new Stop(0.50, Color.web("#2fcb22")),
                                               new Stop(0.60, Color.web("#f1ec28")),
                                               new Stop(0.70, Color.web("#f1c428")),
                                               new Stop(0.80, Color.web("#f19c28")),
                                               new Stop(0.90, Color.web("#f16f28")),
                                               new Stop(1.00, Color.web("#ec272f")));       
        angleStep         = heatControl.getAngleRange() / (heatControl.getMaxValue() - heatControl.getMinValue());
        mouseEventHandler = mouseEvent -> handleMouseEvent(mouseEvent);
        touchEventHandler = touchEvent -> handleTouchEvent(touchEvent);

        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() {                       
        innerShadow = new InnerShadow(BlurType.TWO_PASS_BOX, Color.rgb(0, 0, 0, 0.65), PREFERRED_HEIGHT * 0.1, 0, 0, 0);
        Color color = gradientLookup.getColorAt(getSkinnable().getValue() / (getSkinnable().getMaxValue() - getSkinnable().getMinValue()));
        background = new Circle(0.5 * PREFERRED_WIDTH, 0.5 * PREFERRED_HEIGHT, 0.5 * PREFERRED_WIDTH);
        background.setFill(new LinearGradient(0, 0, 0, PREFERRED_HEIGHT,
                                              false, CycleMethod.NO_CYCLE,
                                              new Stop(0, color.deriveColor(0, 1, 0.8, 1)),
                                              new Stop(1, color.deriveColor(0, 1, 0.6, 1))));
        background.setEffect(innerShadow);

        ticksCanvas = new Canvas(PREFERRED_WIDTH, PREFERRED_HEIGHT);
        ticksCanvas.setMouseTransparent(true);
        ticks = ticksCanvas.getGraphicsContext2D();

        targetIndicator = new Region();
        targetIndicator.getStyleClass().setAll("target-indicator");
        targetIndicatorRotate = new Rotate(180 - getSkinnable().getStartAngle() - getSkinnable().getMinValue() * angleStep);
        targetIndicator.getTransforms().setAll(targetIndicatorRotate);      
        targetExceeded = false;
        targetIndicator.setVisible(getSkinnable().isTargetEnabled());

        valueIndicator = new Region();
        valueIndicator.getStyleClass().setAll("value-indicator");
        valueIndicatorRotate = new Rotate(180 - getSkinnable().getStartAngle());
        valueIndicatorRotate.setAngle(valueIndicatorRotate.getAngle() + (getSkinnable().getValue() - getSkinnable().getOldValue() - getSkinnable().getMinValue()) * angleStep);
        valueIndicator.getTransforms().setAll(valueIndicatorRotate);

        infoText = new Text(getSkinnable().getInfoText().toUpperCase());
        infoText.setTextOrigin(VPos.CENTER);
        infoText.setFont(Fonts.opensansSemiBold(0.06 * PREFERRED_HEIGHT));
        infoText.setMouseTransparent(true);
        infoText.getStyleClass().setAll("info-text");       

        value = new Text(String.format(Locale.US, "%." + getSkinnable().getDecimals() + "f", getSkinnable().getValue()));
        value.setMouseTransparent(true);
        value.setTextOrigin(VPos.CENTER);
        value.setFont(Fonts.opensansBold(0.32 * PREFERRED_HEIGHT));
        value.setMouseTransparent(true);
        value.getStyleClass().setAll("value");

        // Add all nodes
        pane = new Pane();
        pane.getChildren().setAll(background,                                 
                                  ticksCanvas,
                                  valueIndicator,
                                  targetIndicator,
                                  infoText,
                                  value);
       
        getChildren().setAll(pane);
    }

    private void registerListeners() {
        getSkinnable().widthProperty().addListener(observable -> handleControlPropertyChanged("RESIZE"));
        getSkinnable().heightProperty().addListener(observable -> handleControlPropertyChanged("RESIZE"));
        getSkinnable().infoTextProperty().addListener(observable -> handleControlPropertyChanged("INFO_TEXT"));
        getSkinnable().targetEnabledProperty().addListener(observable -> handleControlPropertyChanged("TARGET_ENABLED"));
        getSkinnable().valueProperty().addListener(observable -> handleControlPropertyChanged("VALUE"));
        getSkinnable().minValueProperty().addListener(observable -> handleControlPropertyChanged("RECALC"));
        getSkinnable().maxValueProperty().addListener(observable -> handleControlPropertyChanged("RECALC"));
        getSkinnable().minMeasuredValueProperty().addListener(observable -> handleControlPropertyChanged("MIN_MEASURED_VALUE"));       
        getSkinnable().maxMeasuredValueProperty().addListener(observable -> handleControlPropertyChanged("MAX_MEASURED_VALUE"));                            
        getSkinnable().thresholdProperty().addListener(observable -> handleControlPropertyChanged("TARGET"));       
        getSkinnable().angleRangeProperty().addListener(observable -> handleControlPropertyChanged("ANGLE_RANGE"));       
       
        valueIndicatorRotate.angleProperty().addListener(observable -> handleControlPropertyChanged("ANGLE"));       

        targetIndicator.setOnMousePressed(mouseEventHandler);
        targetIndicator.setOnMouseDragged(mouseEventHandler);
        targetIndicator.setOnMouseReleased(mouseEventHandler);

        targetIndicator.setOnTouchPressed(touchEventHandler);
        targetIndicator.setOnTouchMoved(touchEventHandler);
        targetIndicator.setOnTouchReleased(touchEventHandler);
    }


    // ******************** Methods *******************************************
    protected void handleControlPropertyChanged(final String PROPERTY) {
        if ("RESIZE".equals(PROPERTY)) {
            resize();
        } else if ("INFO_TEXT".equals(PROPERTY)) {
            infoText.setText(getSkinnable().getInfoText().toUpperCase());
            resize();
        } else if ("VALUE".equals(PROPERTY)) {
            rotateNeedle();     
            adjustBackgroundColor();
        } else if ("RECALC".equals(PROPERTY)) {
            if (getSkinnable().getMinValue() < 0) {
                angleStep = getSkinnable().getAngleRange() / (getSkinnable().getMaxValue() - getSkinnable().getMinValue());
                valueIndicatorRotate.setAngle(180 - getSkinnable().getStartAngle() - (getSkinnable().getMinValue()) * angleStep);
            } else {
                angleStep = getSkinnable().getAngleRange() / (getSkinnable().getMaxValue() + getSkinnable().getMinValue());
                valueIndicatorRotate.setAngle(180 - getSkinnable().getStartAngle() * angleStep);
            }
            resize();
        } else if ("ANGLE".equals(PROPERTY)) {           
            double currentValue = (valueIndicatorRotate.getAngle() + getSkinnable().getStartAngle() - 180) / angleStep + getSkinnable().getMinValue();
            if (!userAction) {
                value.setText(String.format(Locale.US, "%." + getSkinnable().getDecimals() + "f", currentValue));
                value.setTranslateX((size - value.getLayoutBounds().getWidth()) * 0.5);
            }
            // Check targetIndicator
            if (targetExceeded) {
                if (currentValue < getSkinnable().getTarget()) {
                    getSkinnable().fireEvent(new ValueEvent(this, null, ValueEvent.VALUE_UNDERRUN));
                    targetExceeded = false;
                }
            } else {
                if (currentValue > getSkinnable().getTarget()) {
                    getSkinnable().fireEvent(new ValueEvent(this, null, ValueEvent.VALUE_EXCEEDED));
                    targetExceeded = true;
                }
            }                                   
        } else if ("TARGET".equals(PROPERTY)) {
            targetIndicatorRotate.setAngle(getSkinnable().getTarget() * angleStep - 180 - getSkinnable().getStartAngle());
        } else if ("TARGET_ENABLED".equals(PROPERTY)) {
            targetIndicator.setVisible(getSkinnable().isTargetEnabled());
        }
    }

    @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 void handleMouseEvent(final MouseEvent MOUSE_EVENT) {
        final Object    SRC  = MOUSE_EVENT.getSource();
        final EventType TYPE = MOUSE_EVENT.getEventType();
        if (SRC.equals(targetIndicator)) {
            if (MouseEvent.MOUSE_PRESSED == TYPE) {   
                userAction = true;
                value.setText(String.format(Locale.US, "%." + getSkinnable().getDecimals() + "f", getSkinnable().getTarget()));
                resizeText();               
            } else if (MouseEvent.MOUSE_DRAGGED == TYPE) {
                touchRotate(MOUSE_EVENT.getSceneX() - getSkinnable().getLayoutX(), MOUSE_EVENT.getSceneY() - getSkinnable().getLayoutY(), targetIndicatorRotate);               
            } else if (MouseEvent.MOUSE_RELEASED == TYPE) {               
                getSkinnable().setTarget(Double.parseDouble(newTarget));
                fadeBack();
            }
        }
    }

    private void handleTouchEvent(final TouchEvent TOUCH_EVENT) {
        final Object    SRC  = TOUCH_EVENT.getSource();
        final EventType TYPE = TOUCH_EVENT.getEventType();
        if (SRC.equals(targetIndicator)) {
            if (TouchEvent.TOUCH_PRESSED == TYPE) {
                value.setText(String.format(Locale.US, "%." + getSkinnable().getDecimals() + "f", getSkinnable().getTarget()));
                resizeText();
            } else if (TouchEvent.TOUCH_MOVED == TYPE) {
                touchRotate(TOUCH_EVENT.getTouchPoint().getSceneX() - getSkinnable().getLayoutX(), TOUCH_EVENT.getTouchPoint().getSceneY() - getSkinnable().getLayoutY(),
                            targetIndicatorRotate);
            } else if (TouchEvent.TOUCH_RELEASED == TYPE) {
                getSkinnable().setTarget(Double.parseDouble(value.getText()));
                fadeBack();
            }
        }
    }

    private double getTheta(double x, double y) {
        double deltaX = x - centerX;
        double deltaY = y - centerY;
        double radius = Math.sqrt((deltaX * deltaX) + (deltaY * deltaY));
        double nx     = deltaX / radius;
        double ny     = deltaY / radius;
        double theta  = Math.atan2(ny, nx);
        return Double.compare(theta, 0.0) >= 0 ? Math.toDegrees(theta) : Math.toDegrees((theta)) + 360.0;
    }

    private void touchRotate(final double X, final double Y, final Rotate ROTATE) {
        double theta     = getTheta(X, Y);
        interactiveAngle = (theta + 90) % 360;
        double newValue  = Double.compare(interactiveAngle, 180) <= 0 ?
                           (interactiveAngle + 180.0 + getSkinnable().getStartAngle() - 360) / angleStep + getSkinnable().getMinValue():
                           (interactiveAngle - 180.0 + getSkinnable().getStartAngle() - 360) / angleStep + getSkinnable().getMinValue();
        if (Double.compare(newValue, getSkinnable().getMinValue()) >= 0 && Double.compare(newValue, getSkinnable().getMaxValue()) <= 0) {
            ROTATE.setAngle(interactiveAngle);
            value.setText(String.format(Locale.US, "%." + getSkinnable().getDecimals() + "f", newValue));
            newTarget = value.getText();
            resizeText();
        }

    }

    private void fadeBack() {
        FadeTransition fadeInfoTextOut = new FadeTransition(Duration.millis(425), infoText);
        fadeInfoTextOut.setFromValue(1.0);
        fadeInfoTextOut.setToValue(0.0);
       
        FadeTransition fadeValueOut = new FadeTransition(Duration.millis(425), value);
        fadeValueOut.setFromValue(1.0);
        fadeValueOut.setToValue(0.0);

        PauseTransition pause = new PauseTransition(Duration.millis(50));

        FadeTransition fadeInfoTextIn = new FadeTransition(Duration.millis(425), infoText);
        fadeInfoTextIn.setFromValue(0.0);
        fadeInfoTextIn.setToValue(1.0);
       
        FadeTransition fadeValueIn = new FadeTransition(Duration.millis(425), value);
        fadeValueIn.setFromValue(0.0);
        fadeValueIn.setToValue(1.0);               
       
        ParallelTransition parallelIn = new ParallelTransition(fadeInfoTextIn, fadeValueIn);

        ParallelTransition parallelOut = new ParallelTransition(fadeInfoTextOut, fadeValueOut);
        parallelOut.setOnFinished(event -> {
            double currentValue = (valueIndicatorRotate.getAngle() + getSkinnable().getStartAngle() - 180) / angleStep + getSkinnable().getMinValue();
            value.setText(String.format(Locale.US, "%." + getSkinnable().getDecimals() + "f", currentValue));
            value.setTranslateX((size - value.getLayoutBounds().getWidth()) * 0.5);
            if (getSkinnable().getTarget() < getSkinnable().getValue()) {
                getSkinnable().setInfoText("COOLING");
            } else if (getSkinnable().getTarget() > getSkinnable().getValue()) {
                getSkinnable().setInfoText("HEATING");
            }
           
            resizeText();
            drawTickMarks(ticks);
            userAction = false;
        });

        SequentialTransition sequence = new SequentialTransition(parallelOut, pause, parallelIn);
        sequence.play();
    }

    private void rotateNeedle() {
        double range       = (getSkinnable().getMaxValue() - getSkinnable().getMinValue());
        double angleRange  = getSkinnable().getAngleRange();
        angleStep          = angleRange / range;
        double targetAngle = valueIndicatorRotate.getAngle() + (getSkinnable().getValue() - getSkinnable().getOldValue()) * angleStep;
       
        valueIndicatorRotate.setAngle(targetAngle);
        drawTickMarks(ticks);
    }
  
    private void adjustBackgroundColor() {
        Color color = gradientLookup.getColorAt(getSkinnable().getValue() / (getSkinnable().getMaxValue() - getSkinnable().getMinValue()));
        background.setFill(new LinearGradient(0, 0, 0, size,
                                              false, CycleMethod.NO_CYCLE,
                                              new Stop(0, color.deriveColor(0, 1, 0.8, 1)),
                                              new Stop(1, color.deriveColor(0, 1, 0.6, 1))));                       
    }
   
    private void drawTickMarks(final GraphicsContext CTX) {       
        CTX.clearRect(0, 0, size, size);
        double  sinValue;       
        double  cosValue;
        double  startAngle     = getSkinnable().getStartAngle();               
        Point2D center         = new Point2D(size * 0.5, size * 0.5);
        double  stdLineWidth   = size * 0.003;
        double  rangeLineWidth = size * 0.007;
        for (double angle = 0, counter = getSkinnable().getMinValue() ; Double.compare(counter, getSkinnable().getMaxValue()) <= 0 ; angle -= angleStep / 3, counter+= 0.33333) {
            sinValue = Math.sin(Math.toRadians(angle + startAngle));
            cosValue = Math.cos(Math.toRadians(angle + startAngle));

            Point2D innerPoint = new Point2D(center.getX() + size * 0.368 * sinValue, center.getY() + size * 0.368 * cosValue);           
            Point2D outerPoint = new Point2D(center.getX() + size * 0.457 * sinValue, center.getY() + size * 0.457 * cosValue);           

            CTX.setStroke(getSkinnable().getTickMarkFill());                       
            if (getSkinnable().isTargetEnabled() &&
                counter > getSkinnable().getValue() && counter < getSkinnable().getTarget() ||
                counter > getSkinnable().getTarget() && counter < getSkinnable().getValue()) {
                CTX.setLineWidth(rangeLineWidth);
            } else {
                CTX.setLineWidth(stdLineWidth);   
            }
            CTX.setLineCap(StrokeLineCap.ROUND);
            CTX.strokeLine(innerPoint.getX(), innerPoint.getY(), outerPoint.getX(), outerPoint.getY());                           
        }
    }
   
    private void resizeText() {       
        infoText.setFont(Fonts.opensansLight(size * 0.07));
        infoText.setTranslateX((size - infoText.getLayoutBounds().getWidth()) * 0.5);
        infoText.setTranslateY(size * 0.34);

        value.setFont(Fonts.opensansBold(size * 0.32));
        value.setTranslateX((size - value.getLayoutBounds().getWidth()) * 0.5);
        value.setTranslateY(size * 0.5);
    }

    private void resize() {
        size = getSkinnable().getWidth() < getSkinnable().getHeight() ? getSkinnable().getWidth() : getSkinnable().getHeight();
        centerX = size * 0.5;
        centerY = size * 0.5;
       
        innerShadow.setRadius(size * 0.1);
       
        background.setCenterX(centerX);
        background.setCenterY(centerY);
        background.setRadius(size * 0.5);

        ticksCanvas.setWidth(size);
        ticksCanvas.setHeight(size);
        ticks.clearRect(0, 0, size, size);       
        drawTickMarks(ticks);
        ticksCanvas.setCache(true);
        ticksCanvas.setCacheHint(CacheHint.QUALITY);

        valueIndicator.setPrefSize(size * 0.025, size * 0.096);
        valueIndicator.relocate((size - valueIndicator.getPrefWidth()) * 0.5, size * 0.039);
        valueIndicatorRotate.setPivotX(valueIndicator.getPrefWidth() * 0.5);
        valueIndicatorRotate.setPivotY(size * 0.461);
       
        targetIndicator.setPrefSize(0.025 * size, 0.13 * size);
        targetIndicator.relocate((size - targetIndicator.getPrefWidth()) * 0.5, size * 0.039);
        targetIndicatorRotate.setPivotX(targetIndicator.getPrefWidth() * 0.5);
        targetIndicatorRotate.setPivotY(size * 0.461);
        targetIndicatorRotate.setAngle(getSkinnable().getTarget() * angleStep - 180 - getSkinnable().getStartAngle() - getSkinnable().getMinValue() * angleStep);

        infoText.setText(getSkinnable().getInfoText().toUpperCase());
        value.setText(String.format(Locale.US, "%." + getSkinnable().getDecimals() + "f", (valueIndicatorRotate.getAngle() + getSkinnable().getStartAngle() - 180) / angleStep));
               
        resizeText();
    }
}
TOP

Related Classes of eu.hansolo.enzo.heatcontrol.skin.HeatControlSkin

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.