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

eu.hansolo.tilesfx.chart.ChartData Maven / Gradle / Ivy

There is a newer version: 21.0.9
Show newest version
/*
 * SPDX-License-Identifier: Apache-2.0
 *
 * Copyright 2016-2021 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
 *
 *     https://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.tilesfx.chart;

import eu.hansolo.tilesfx.Tile;
import eu.hansolo.tilesfx.events.ChartDataEvent;
import eu.hansolo.tilesfx.events.ChartDataEvent.EventType;
import eu.hansolo.tilesfx.events.ChartDataEventListener;
import eu.hansolo.toolboxfx.GradientLookup;
import eu.hansolo.toolboxfx.geom.Location;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.DoublePropertyBase;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ObjectPropertyBase;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.util.Duration;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;

import static eu.hansolo.tilesfx.tools.Helper.clamp;


/**
 * Created by hansolo on 17.02.17.
 */
public class ChartData implements Comparable {
    protected final ChartDataEvent                     UPDATE_EVENT   = new ChartDataEvent(EventType.UPDATE, ChartData.this);
    protected final ChartDataEvent                     FINISHED_EVENT = new ChartDataEvent(EventType.FINISHED, ChartData.this);
    protected       Image                              image;
    protected       String                             name;
    protected       double                             value;
    protected       double                             oldValue;
    protected       Color                              fillColor;
    protected       Color                              strokeColor;
    protected       Color                              textColor;
    protected       Instant                            oldTimestamp;
    protected       Instant                            timestamp;
    protected       java.time.Duration                 oldDuration;
    protected       java.time.Duration                 duration;
    protected       Location                           location;
    protected       boolean                            animated;
    protected       long                               animationDuration;
    protected       List       listenerList   = new CopyOnWriteArrayList<>();
    protected       DoubleProperty                     currentValue;
    protected       ObjectProperty currentDuration;
    protected       ObjectProperty            currentTimestamp;
    protected       Timeline                           timeline;
    protected       String                             formatString;
    protected       double                             minValue;
    protected       double                             maxValue;
    protected       GradientLookup                     gradientLookup;
    protected       boolean                            useChartDataColors;


    // ******************** Constructors **************************************
    public ChartData() {
        this(null, "", 0, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, Instant.now(), java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final String NAME) {
        this(null, NAME, 0, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, Instant.now(), java.time.Duration.ZERO, true, 800);
    }
    public ChartData(double VALUE) {
        this(null, "", VALUE, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, Instant.now(), java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final double VALUE, final Instant TIMESTAMP) {
        this(null, "", VALUE, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, TIMESTAMP, java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final String NAME, final Instant TIMESTAMP) {
        this(null, NAME, 0, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, TIMESTAMP, java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final String NAME, final Color FILL_COLOR) {
        this(null, NAME, 0, FILL_COLOR, Color.TRANSPARENT, Tile.FOREGROUND, Instant.now(), java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final String NAME, final double VALUE) {
        this(null, NAME, VALUE, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, Instant.now(), java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final String NAME, final double VALUE, final Instant TIMESTAMP) {
        this(null, NAME, VALUE, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, TIMESTAMP, java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final String NAME, final double VALUE, final java.time.Duration DURATION) {
        this(null, NAME, VALUE, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, Instant.now(), DURATION, true, 800);
    }
    public ChartData(final String NAME, final double VALUE, final Instant TIMESTAMP, final java.time.Duration DURATION) {
        this(null, NAME, VALUE, Tile.BLUE, Color.TRANSPARENT, Tile.FOREGROUND, TIMESTAMP, DURATION, true, 800);
    }
    public ChartData(final String NAME, final double VALUE, final Instant TIMESTAMP, final java.time.Duration DURATION, final Color FILL_COLOR) {
        this(null, NAME, VALUE, FILL_COLOR, Color.TRANSPARENT, Tile.FOREGROUND, TIMESTAMP, DURATION, true, 800);
    }
    public ChartData(final String NAME, final double VALUE, final Color FILL_COLOR) {
        this(null, NAME, VALUE, FILL_COLOR, Color.TRANSPARENT, Tile.FOREGROUND, Instant.now(), java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final String NAME, final double VALUE, final Color FILL_COLOR, final Instant TIMESTAMP) {
        this(null, NAME, VALUE, FILL_COLOR, Color.TRANSPARENT, Tile.FOREGROUND, TIMESTAMP, java.time.Duration.ZERO, true, 800);
    }
    public ChartData(final String NAME, final double VALUE ,final Color FILL_COLOR, final java.time.Duration DURATION) {
        this(null, NAME, VALUE, FILL_COLOR, Color.TRANSPARENT, Tile.FOREGROUND, Instant.now(), DURATION, true, 800);
    }
    public ChartData(final String NAME, final double VALUE, final Color FILL_COLOR, final Instant TIMESTAMP, final boolean ANIMATED, final long ANIMATION_DURATION) {
        this(null, NAME, VALUE, FILL_COLOR, Color.TRANSPARENT, Tile.FOREGROUND, TIMESTAMP, java.time.Duration.ZERO, ANIMATED, ANIMATION_DURATION);
    }
    public ChartData(final String NAME, final double VALUE, final Color FILL_COLOR, final Color STROKE_COLOR, final Instant TIMESTAMP, final boolean ANIMATED, final long ANIMATION_DURATION) {
        this(null, NAME, VALUE, FILL_COLOR, STROKE_COLOR, Tile.FOREGROUND, TIMESTAMP, java.time.Duration.ZERO, ANIMATED, ANIMATION_DURATION);
    }
    public ChartData(final String NAME, final double VALUE, final Color FILL_COLOR, final Color STROKE_COLOR, final Color TEXT_COLOR, final Instant TIMESTAMP, final boolean ANIMATED, final long ANIMATION_DURATION) {
        this(null, NAME, VALUE, FILL_COLOR, STROKE_COLOR, TEXT_COLOR, TIMESTAMP, java.time.Duration.ZERO, ANIMATED, ANIMATION_DURATION);
    }
    public ChartData(final Image IMAGE, final String NAME, final double VALUE, final Color FILL_COLOR, final Color STROKE_COLOR, final Color TEXT_COLOR, final Instant TIMESTAMP, final java.time.Duration DURATION, final boolean ANIMATED, final long ANIMATION_DURATION) {
        image              = IMAGE;
        name               = NAME;
        value              = VALUE;
        oldValue           = 0;
        fillColor          = FILL_COLOR;
        strokeColor        = STROKE_COLOR;
        textColor          = TEXT_COLOR;
        timestamp          = TIMESTAMP;
        duration           = DURATION;
        currentValue       = new DoublePropertyBase(value) {
            @Override protected void invalidated() {
                oldValue = value;
                value    = get();
                fireChartDataEvent(UPDATE_EVENT);
            }
            @Override public Object getBean() { return ChartData.this; }
            @Override public String getName() { return "currentValue"; }
        };
        currentDuration    = new ObjectPropertyBase<>(duration) {
            @Override protected void invalidated() {
                oldDuration = duration;
                duration    = get();
                fireChartDataEvent(UPDATE_EVENT);
            }
            @Override public Object getBean() { return ChartData.this; }
            @Override public String getName() { return "currentDuration"; }
        };
        currentTimestamp   = new ObjectPropertyBase<>(timestamp) {
            @Override protected void invalidated() {
                oldTimestamp = timestamp;
                timestamp    = get();
                fireChartDataEvent(UPDATE_EVENT);
            }
            @Override public Object getBean() { return ChartData.this; }
            @Override public String getName() { return "currentTimestamp"; }
        };
        timeline           = new Timeline();
        animated           = ANIMATED;
        animationDuration  = ANIMATION_DURATION;
        formatString       = "";
        minValue           = 0;
        maxValue           = 100;
        useChartDataColors = false;

        timeline.setOnFinished(e -> fireChartDataEvent(FINISHED_EVENT));
    }


    // ******************** Methods *******************************************
    public Image getImage() { return image; }
    public void setImage(final Image IMAGE) {
        image = IMAGE;
        fireChartDataEvent(UPDATE_EVENT);
    }

    public String getName() { return name; }
    public void setName(final String NAME) {
        name = NAME;
        if (null != location) { location.setName(NAME); }
        fireChartDataEvent(UPDATE_EVENT);
    }

    public double getValue() { return value; }
    public void setValue(final double VALUE) {
        if (animated) {
            oldValue = value;
            value    = VALUE;
            timeline.stop();
            KeyValue kv1 = new KeyValue(currentValue, oldValue, Interpolator.EASE_BOTH);
            KeyValue kv2 = new KeyValue(currentValue, VALUE, Interpolator.EASE_BOTH);
            KeyFrame kf1 = new KeyFrame(Duration.ZERO, kv1);
            KeyFrame kf2 = new KeyFrame(Duration.millis(animationDuration), kv2);
            timeline.getKeyFrames().setAll(kf1, kf2);
            timeline.play();
        } else {
            oldValue = value;
            value    = VALUE;
            fireChartDataEvent(FINISHED_EVENT);
        }
    }

    public ReadOnlyDoubleProperty currentValueProperty() { return currentValue; }

    public double getOldValue() { return oldValue; }

    public Color getFillColor() { return fillColor; }
    public void setFillColor(final Color FILL) {
        fillColor = FILL;
        if (null != location) { location.setFill(FILL); }
        fireChartDataEvent(UPDATE_EVENT);
    }

    public Color getStrokeColor() { return strokeColor; }
    public void setStrokeColor(final Color COLOR) {
        strokeColor = COLOR;
        fireChartDataEvent(UPDATE_EVENT);
    }

    public Color getTextColor() { return textColor; }
    public void setTextColor(final Color COLOR) {
        textColor = COLOR;
        fireChartDataEvent(UPDATE_EVENT);
    }

    public Instant getTimestamp() { return timestamp; }
    public void setTimestamp(final Instant TIMESTAMP) {
        if (animated) {
            oldTimestamp = timestamp;
            timestamp    = TIMESTAMP;
            timeline.stop();
            KeyValue kv1 = new KeyValue(currentTimestamp, oldTimestamp, Interpolator.EASE_BOTH);
            KeyValue kv2 = new KeyValue(currentTimestamp, TIMESTAMP, Interpolator.EASE_BOTH);
            KeyFrame kf1 = new KeyFrame(Duration.ZERO, kv1);
            KeyFrame kf2 = new KeyFrame(Duration.millis(animationDuration), kv2);
            timeline.getKeyFrames().setAll(kf1, kf2);
            timeline.play();
        } else {
            oldTimestamp = timestamp;
            timestamp    = TIMESTAMP;
            fireChartDataEvent(FINISHED_EVENT);
        }
    }

    public ReadOnlyObjectProperty currentTimestampProperty() { return currentTimestamp; }

    public java.time.Duration getDuration() { return duration; }
    public void setDuration(final java.time.Duration DURATION) {
        if (animated) {
            oldDuration = duration;
            duration    = DURATION;
            timeline.stop();
            KeyValue kv1 = new KeyValue(currentDuration, oldDuration, Interpolator.EASE_BOTH);
            KeyValue kv2 = new KeyValue(currentDuration, DURATION, Interpolator.EASE_BOTH);
            KeyFrame kf1 = new KeyFrame(Duration.ZERO, kv1);
            KeyFrame kf2 = new KeyFrame(Duration.millis(animationDuration), kv2);
            timeline.getKeyFrames().setAll(kf1, kf2);
            timeline.play();
        } else {
            oldDuration = duration;
            duration    = DURATION;
            fireChartDataEvent(FINISHED_EVENT);
        }
    }

    public ReadOnlyObjectProperty currentDurationProperty() { return currentDuration; }

    public Location getLocation() { return location; }
    public void setLocation(final Location LOCATION) {
        location = LOCATION;
        location.setName(getName());
        location.setFill(getFillColor());
        fireChartDataEvent(UPDATE_EVENT);
    }

    public ZonedDateTime getTimestampAsDateTime() { return getTimestampAsDateTime(ZoneId.systemDefault()); }
    public ZonedDateTime getTimestampAsDateTime(final ZoneId ZONE_ID) { return ZonedDateTime.ofInstant(timestamp, ZONE_ID); }

    public LocalDate getTimestampAsLocalDate() { return getTimestampAsLocalDate(ZoneId.systemDefault()); }
    public LocalDate getTimestampAsLocalDate(final ZoneId ZONE_ID) { return getTimestampAsDateTime(ZONE_ID).toLocalDate(); }

    public boolean isAnimated() { return animated; }
    public void setAnimated(final boolean ANIMATED) { animated = ANIMATED; }

    public long getAnimationDuration() { return animationDuration; }
    public void setAnimationDuration(final long DURATION) { animationDuration = clamp(10, 10000, DURATION); }

    public boolean isWithinTimePeriod(final java.time.Duration PERIOD) {
        return isWithinTimePeriod(Instant.now(), PERIOD);
    }
    public boolean isWithinTimePeriod(final Instant PERIOD_START, final java.time.Duration PERIOD) {
        return (timestamp.isBefore(PERIOD_START) || timestamp.equals(PERIOD_START)) && (timestamp.equals(PERIOD_START.minus(PERIOD)) || timestamp.isAfter(PERIOD_START.minus(PERIOD.plusSeconds(1))));
    }

    public String getFormatString() { return formatString; }
    public void setFormatString(final String FORMAT_STRING) {
        formatString = FORMAT_STRING;
        fireChartDataEvent(UPDATE_EVENT);
    }

    public double getMaxValue() { return maxValue; }
    public void setMaxValue(final double MAX_VALUE) { maxValue = MAX_VALUE; }

    public double getMinValue() { return minValue; }
    public void setMinValue(final double MIN_VALUE) { minValue = MIN_VALUE; }

    public GradientLookup getGradientLookup() { return gradientLookup; }
    public void setGradientLookup(final GradientLookup GRADIENT_LOOKUP) { gradientLookup = GRADIENT_LOOKUP; }

    public boolean getUseChartDataColor() { return useChartDataColors; }
    public void setUseChartDataColors(final boolean USE) { useChartDataColors = USE; }

    @Override public String toString() {
        return new StringBuilder().append("{\n")
                                  .append("  \"name\":\"").append(name).append("\",\n")
                                  .append("  \"value\":").append(value).append(",\n")
                                  .append("  \"fillColor\":\"").append(fillColor.toString().replace("0x", "#")).append("\",\n")
                                  .append("  \"strokeColor\":\"").append(strokeColor.toString().replace("0x", "#")).append("\",\n")
                                  .append("  \"timestamp\":").append(timestamp.toEpochMilli()).append(",\n")
                                  .append("  \"duration\":").append(duration.toMillis()).append("\n")
                                  .append("}")
                                  .toString();
    }

    @Override public int compareTo(final ChartData DATA) {
        return Double.compare(getValue(), DATA.getValue());
    }

    @Override public boolean equals(final Object OBJ) {
        if (OBJ == this) { return true; }
        if (!(OBJ instanceof ChartData)) { return false; }
        ChartData other = (ChartData) OBJ;
        boolean timestampEquals = (this.timestamp.equals(other.getTimestamp()));
        boolean durationEquals  = this.duration.equals(other.getDuration());
        boolean valueEquals     = (Double.compare(this.value, other.getValue()) == 0);
        return timestampEquals && durationEquals && valueEquals;
    }

    @Override public int hashCode() {
        return Objects.hash(name, value, timestamp);
    }


    // ******************** Event Handling ************************************
    public void setOnChartDataEvent(final ChartDataEventListener LISTENER) { addChartDataEventListener(LISTENER); }
    public void addChartDataEventListener(final ChartDataEventListener LISTENER) { if (!listenerList.contains(LISTENER)) listenerList.add(LISTENER); }
    public void removeChartDataEventListener(final ChartDataEventListener LISTENER) { if (listenerList.contains(LISTENER)) listenerList.remove(LISTENER); }

    public void fireChartDataEvent(final ChartDataEvent EVENT) {
        for (ChartDataEventListener listener : listenerList) { listener.onChartDataEvent(EVENT); }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy