Package eu.hansolo.enzo.vumeter.skin

Source Code of eu.hansolo.enzo.vumeter.skin.VuMeterSkin

package eu.hansolo.enzo.vumeter.skin;

import eu.hansolo.enzo.common.Section;
import eu.hansolo.enzo.vumeter.VuMeter;
import javafx.animation.AnimationTimer;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.WeakEventHandler;
import javafx.geometry.Orientation;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;


/**
* User: hansolo
* Date: 04.11.13
* Time: 10:30
*/
public class VuMeterSkin extends SkinBase<VuMeter> implements Skin<VuMeter> {
    private static final double    PREFERRED_WIDTH  = 24;
    private static final double    PREFERRED_HEIGHT = 24;
    private static final double    MINIMUM_WIDTH    = 16;
    private static final double    MINIMUM_HEIGHT   = 16;
    private static final double    MAXIMUM_WIDTH    = 1024;
    private static final double    MAXIMUM_HEIGHT   = 1024;
    public static final long       PEAK_TIMEOUT     = 1_500_000_000l;
    private static boolean         active;
    private double                 size;   
    private ObservableList<Region> leds;
    private HBox                   hBox;
    private VBox                   vBox;
    private DoubleProperty         stepSize;
    private int                    peakLedIndex;
    private long                   lastTimerCall;   
    private AnimationTimer         timer;


    // ******************** Constructors **************************************
    public VuMeterSkin(final VuMeter CONTROL) {
        super(CONTROL);
        active        = false;
        lastTimerCall = 0l;
        stepSize      = new SimpleDoubleProperty((getSkinnable().getMaxValue() - getSkinnable().getMinValue()) / getSkinnable().getNoOfLeds());
        timer         = new AnimationTimer() {
            @Override public void handle(final long NOW) {
                if (NOW > lastTimerCall + PEAK_TIMEOUT) {
                    leds.get(peakLedIndex).getStyleClass().remove("led-peak");
                    peakLedIndex = Orientation.HORIZONTAL == getSkinnable().getOrientation() ? 0 : leds.size() - 1;
                    timer.stop();
                }
            }
        };
        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 (Orientation.HORIZONTAL == getSkinnable().getOrientation()) {               
                getSkinnable().setPrefSize(getSkinnable().getNoOfLeds() * PREFERRED_WIDTH + (getSkinnable().getNoOfLeds() - 1) * getSkinnable().getLedSpacing(), PREFERRED_HEIGHT);                                                   
            } else {               
                getSkinnable().setPrefSize(PREFERRED_WIDTH, getSkinnable().getNoOfLeds() * PREFERRED_HEIGHT + (getSkinnable().getNoOfLeds() - 1) * getSkinnable().getLedSpacing());               
            }           
        }

        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_WIDTH);
        }
    }

    private void initGraphics() {               
        hBox = new HBox();       
        hBox.getStyleClass().setAll("vu-meter");
        hBox.setSpacing(getSkinnable().getLedSpacing());       
       
        vBox = new VBox();
        vBox.getStyleClass().setAll("vu-meter");
        vBox.setSpacing(getSkinnable().getLedSpacing());       

        leds = FXCollections.observableArrayList();
        for (int i = 0 ; i < getSkinnable().getNoOfLeds() ; i++) {
            Region led = new Region();                   
            led.setOnMouseClicked(new WeakEventHandler<>(event -> active = !active));
            led.setOnMouseEntered(new WeakEventHandler<>(event -> handleMouseEvent(event)));                                   
            if (getSkinnable().getSections().isEmpty()) {
                led.getStyleClass().setAll("led");
            } else {               
                for (Section section : getSkinnable().getSections()) {
                    if (section.contains(i * stepSize.doubleValue())) {
                        led.getStyleClass().setAll("led", section.getStyleClass());
                    }
                }               
            }           
            leds.add(led);
        }
       
        if (Orientation.HORIZONTAL == getSkinnable().getOrientation()) {
            vBox.setManaged(false);           
            vBox.setVisible(false);
            hBox.getChildren().setAll(leds);
            peakLedIndex = 0;
        } else {
            hBox.setManaged(false);
            hBox.setVisible(false);
            FXCollections.reverse(leds);
            vBox.getChildren().setAll(leds);
            peakLedIndex = leds.size() - 1;
        }
                                       
        // Add all nodes
        getChildren().setAll(hBox, vBox);       
    }

    private void registerListeners() {
        getSkinnable().widthProperty().addListener(observable -> handleControlPropertyChanged("RESIZE") );
        getSkinnable().heightProperty().addListener(observable -> handleControlPropertyChanged("RESIZE") );               
        getSkinnable().valueProperty().addListener(observable -> handleControlPropertyChanged("VALUE"));       
        getSkinnable().orientationProperty().addListener((ov, oldOrientation, newOrientation) -> {
            if (Orientation.HORIZONTAL == oldOrientation && Orientation.VERTICAL == newOrientation) {
                FXCollections.reverse(leds);   
            } else if (Orientation.VERTICAL == oldOrientation && Orientation.HORIZONTAL == newOrientation) {
                FXCollections.reverse(leds);
            }
            handleControlPropertyChanged("ORIENTATION");
        });
        getSkinnable().noOfLedsProperty().addListener(observable -> handleControlPropertyChanged("NO_OF_LEDS"));
        getSkinnable().getSections().addListener((ListChangeListener<Section>) change -> handleControlPropertyChanged("SECTIONS"));       
    }


    // ******************** Methods *******************************************
    protected void handleControlPropertyChanged(final String PROPERTY) {
        if ("RESIZE".equals(PROPERTY)) {
            resize();
        } else if ("STYLE".equals(PROPERTY)) {
            resize();           
        } else if ("VALUE".equals(PROPERTY)) {
            int currentLedPeakIndex;
            if (Orientation.HORIZONTAL == getSkinnable().getOrientation()) {               
                // HORIZONTAL
                currentLedPeakIndex = 0;
                for (int i = 0 ; i < leds.size() ; i++) {
                    leds.get(i).getStyleClass().remove("led-on");
                    if (Double.compare(i * stepSize.doubleValue(), getSkinnable().getValue()) <= 0) {
                        leds.get(i).getStyleClass().add("led-on");                   
                        currentLedPeakIndex = i;
                    }
                }
                if (getSkinnable().isPeakValueVisible()) {
                    if (currentLedPeakIndex > peakLedIndex) {
                        timer.stop();
                        leds.get(peakLedIndex).getStyleClass().remove("led-peak");
                        leds.get(currentLedPeakIndex).getStyleClass().add("led-peak");
                        peakLedIndex  = currentLedPeakIndex;
                        lastTimerCall = System.nanoTime();
                        timer.start();
                    }
                }
            } else {   
                // VERTICAL
                currentLedPeakIndex = leds.size() - 1;
                for (int i = 0 ; i < leds.size() ; i++) {
                    if (i != peakLedIndex) leds.get(i).getStyleClass().remove("led-on");
                    if (Double.compare((leds.size() - i - 1) * stepSize.doubleValue(), getSkinnable().getValue()) <= 0) {
                        leds.get(i).getStyleClass().add("led-on");                                               
                    } else {
                        currentLedPeakIndex = i;
                    }
                }               
                if (getSkinnable().isPeakValueVisible()) {
                    if (currentLedPeakIndex < peakLedIndex) {
                        timer.stop();
                        leds.get(peakLedIndex).getStyleClass().remove("led-peak");
                        leds.get(currentLedPeakIndex).getStyleClass().add("led-peak");
                        peakLedIndex  = currentLedPeakIndex;
                        lastTimerCall = System.nanoTime();
                        timer.start();
                    }
                }
            }                       
        } else if ("ORIENTATION".equals(PROPERTY)) {
            hBox.getChildren().clear();
            vBox.getChildren().clear();           
            if (Orientation.HORIZONTAL == getSkinnable().getOrientation()) {
                vBox.setManaged(false);
                vBox.setVisible(false);
                hBox.getChildren().setAll(leds);
            } else {
                hBox.setManaged(false);
                hBox.setVisible(false);               
                vBox.getChildren().setAll(leds);
            }   
        } else if ("NO_OF_LEDS".equals(PROPERTY)) {
            leds.clear();
            hBox.getChildren().clear();
            vBox.getChildren().clear();
            for (int i = 0 ; i < getSkinnable().getNoOfLeds() ; i++) {
                Region led = new Region();
                led.setPrefSize(10, 20);
                if (getSkinnable().getSections().isEmpty()) {
                    led.getStyleClass().setAll("led");
                } else {
                    for (Section section : getSkinnable().getSections()) {
                        if (section.contains(i * stepSize.doubleValue())) {
                            led.getStyleClass().setAll("led", section.getStyleClass());
                        }
                    }
                }
                leds.add(led);
            }

            if (Orientation.HORIZONTAL == getSkinnable().getOrientation()) {               
                hBox.getChildren().setAll(leds);
            } else {  
                vBox.getChildren().setAll(leds);
            }   
        } else if ("SECTIONS".equals(PROPERTY)) {
            for (int i = 0 ; i < getSkinnable().getNoOfLeds() ; i++) {
                Region led = new Region();
                led.setPrefSize(10, 20);
                if (getSkinnable().getSections().isEmpty()) {
                    led.getStyleClass().setAll("led");
                } else {
                    for (Section section : getSkinnable().getSections()) {
                        if (section.contains(i * stepSize.doubleValue())) {
                            led.getStyleClass().setAll("led", section.getStyleClass());
                        }
                    }
                }
                leds.add(led);
            }   
        }
    }
       
    @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 void handleMouseEvent(final MouseEvent EVENT) {       
        if (active && MouseEvent.MOUSE_ENTERED == EVENT.getEventType()) {
            final Region SRC = (Region) EVENT.getSource();           
            if (Orientation.HORIZONTAL == getSkinnable().getOrientation()) {
                for (int i = 0 ; i < leds.size() ; i++) {
                    leds.get(i).getStyleClass().remove("led-on");
                    if (i <= leds.indexOf(SRC)) {
                        leds.get(i).getStyleClass().add("led-on");
                    }               
                }           
            } else {
                for (int i = 0 ; i < leds.size() ; i++) {
                    leds.get(i).getStyleClass().remove("led-on");
                    if (i >= leds.indexOf(SRC)) {
                        leds.get(i).getStyleClass().add("led-on");
                    }
                }
            }
        }
    }
   

    // ******************** Private Methods ***********************************   
    private void resize() {
        size = getSkinnable().getWidth() < getSkinnable().getHeight() ? getSkinnable().getWidth() : getSkinnable().getHeight();                      
        if (size > 0) {                       
            for (Region led : leds) {
                led.setPrefSize(size, size);
            }                                       
        }
    }       
}
TOP

Related Classes of eu.hansolo.enzo.vumeter.skin.VuMeterSkin

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.