Package org.ugate.gui.view

Source Code of org.ugate.gui.view.SensorReadingHistory

package org.ugate.gui.view;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.TextField;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Light;
import javafx.scene.effect.Lighting;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ugate.UGateUtil;
import org.ugate.gui.ControlBar;
import org.ugate.gui.GuiUtil;
import org.ugate.gui.components.SimpleCalendar;
import org.ugate.resources.RS;
import org.ugate.resources.RS.KEY;
import org.ugate.service.ServiceProvider;
import org.ugate.service.entity.jpa.RemoteNodeReading;

/**
* {@linkplain RemoteNodeReading} history
*/
public class SensorReadingHistory extends StackPane {

  private static final Logger log = LoggerFactory
      .getLogger(SensorReadingHistory.class);
  private final ControlBar cb;
  private final CategoryAxis xAxis = new CategoryAxis();
  private final NumberAxis yAxis = new NumberAxis();
  private final XYChart.Series<String, Number> laserSeries;
  private final XYChart.Series<String, Number> sonarSeries;
  private final XYChart.Series<String, Number> microwaveSeries;
  private final XYChart.Series<String, Number> pirSeries;
  private final XYChart.Series<String, Number> readTripsSeries;

  /**
   * Constructor
   *
   * @param controlBar
   *            the {@linkplain ControlBar}
   */
  public SensorReadingHistory(final ControlBar controlBar) {
    this.cb = controlBar;
    final StackedBarChart<String, Number> chart = new StackedBarChart<>(
        xAxis, yAxis);
    chart.setTitle(RS.rbLabel(KEY.ALARM_NOTIFICATION));
    // xAxis.setLabel(RS.rbLabel(KEYS.LABEL_GRAPH_AXIS_X));
    xAxis.setCategories(FXCollections.<String> observableArrayList());
    yAxis.setLabel(RS.rbLabel(KEY.LABEL_GRAPH_AXIS_Y));
    yAxis.setMinorTickVisible(false);
    yAxis.setAutoRanging(false);
    yAxis.setUpperBound(16d);
    yAxis.setTickUnit(1d);
    sonarSeries = new XYChart.Series<>();
    pirSeries = new XYChart.Series<>();
    microwaveSeries = new XYChart.Series<>();
    laserSeries = new XYChart.Series<>();
    readTripsSeries = new XYChart.Series<>();

    final SimpleCalendar simpleCalender = new SimpleCalendar();
    simpleCalender.setMaxSize(100d, 20d);
    final TextField dateField = new TextField(new SimpleDateFormat(
        "MM/dd/yyyy").format(simpleCalender.dateProperty().get()));
    dateField.setMaxSize(simpleCalender.getMaxWidth(),
        simpleCalender.getMaxHeight());
    dateField.setEditable(false);
    dateField.setDisable(true);
    simpleCalender.dateProperty().addListener(new ChangeListener<Date>() {
      @Override
      public void changed(final ObservableValue<? extends Date> ov,
          final Date oldDate, final Date newDate) {
        dateField.setText(new SimpleDateFormat("MM/dd/yyyy")
            .format(newDate));
        final Calendar cal = Calendar.getInstance();
        cal.setTime(newDate);
        populateData(chart, cal);
      }
    });

    final HBox dateBox = new HBox();
    dateBox.setAlignment(Pos.BOTTOM_RIGHT);
    dateBox.getChildren().addAll(dateField, simpleCalender);

    setPadding(new Insets(10d));
    setAlignment(Pos.BOTTOM_RIGHT);
    getChildren().addAll(chart, dateBox);

    sonarSeries.setName(RS.rbLabel(KEY.LABEL_GRAPH_SERIES_ALARM_SONAR));
    pirSeries.setName(RS.rbLabel(KEY.LABEL_GRAPH_SERIES_ALARM_PIR));
    microwaveSeries.setName(RS
        .rbLabel(KEY.LABEL_GRAPH_SERIES_ALARM_MICROWAVE));
    laserSeries.setName(RS.rbLabel(KEY.LABEL_GRAPH_SERIES_ALARM_LASER));
    readTripsSeries.setName(RS
        .rbLabel(KEY.LABEL_GRAPH_SERIES_ACTIVITY_READS));

    final Calendar cal = Calendar.getInstance();
    cal.setTime(simpleCalender.dateProperty().get());
    populateData(chart, cal);
  }

  /**
   * Updates the {@linkplain XYChart.Series} using
   * {@linkplain RemoteNodeReading}(s) for a given {@linkplain Calendar}
   *
   * @param cal
   *            the {@linkplain Calendar} to get the
   *            {@linkplain RemoteNodeReading}(s) for (will not use time)
   * @return the number of {@linkplain RemoteNodeReading}s
   */
  protected int populateData(final XYChart<String, Number> chart,
      final Calendar cal) {
    final List<RemoteNodeReading> rnrs = ServiceProvider.IMPL
        .getRemoteNodeService().findReadingsByDate(cb.getRemoteNode(),
            cal, true);
    // add zero plot for 24hr period for each series
    xAxis.getCategories().clear();
    sonarSeries.getData().clear();
    pirSeries.getData().clear();
    microwaveSeries.getData().clear();
    laserSeries.getData().clear();
    readTripsSeries.getData().clear();
    if (rnrs.size() > 0) {
      String time;
      final int d = 0;// Double.MIN_NORMAL;
      Number l = d, m = d, p = d, s = d, r = d;
      for (final RemoteNodeReading rnr : rnrs) {
        l = m = p = s = r = d;
        time = UGateUtil.dateFormatTime(rnr.getReadDate());
        xAxis.getCategories().add(time);
        switch (rnr.getFromMultiState()) {
        case 1:
          l = 1;
          break;
        case 2:
          m = 1;
          break;
        case 3:
          l = 2;
          m = 2;
          break;
        case 4:
          p = 1;
          break;
        case 5:
          l = 2;
          p = 2;
          break;
        case 6:
          m = 2;
          p = 2;
          break;
        case 7:
          l = 3;
          m = 3;
          p = 3;
          break;
        case 8:
          s = 1;
          break;
        case 9:
          l = 2;
          s = 2;
          break;
        case 10:
          m = 2;
          s = 2;
          break;
        case 11:
          l = 3;
          m = 3;
          s = 3;
          break;
        case 12:
          p = 2;
          s = 2;
          break;
        case 13:
          l = 3;
          p = 3;
          s = 3;
          break;
        case 14:
          m = 3;
          p = 3;
          s = 3;
          break;
        case 15:
          l = 4;
          m = 4;
          p = 4;
          s = 4;
          break;
        case 16:
          r = 1;
          break;
        default:
          log.warn(String.format(
              "%1$s for ID %2$s invalid for multi-state %3$s",
              RemoteNodeReading.class.getName(), rnr.getId(),
              rnr.getFromMultiState()));
        }
        int i = -1;
        addData(chart, sonarSeries, new XYChart.Data<>(time, s), ++i);
        addData(chart, pirSeries, new XYChart.Data<>(time, p), ++i);
        addData(chart, microwaveSeries, new XYChart.Data<>(time, m),
            ++i);
        addData(chart, laserSeries, new XYChart.Data<>(time, l), ++i);
        addData(chart, readTripsSeries, new XYChart.Data<>(time, r),
            ++i);
      }
      if (chart.getData().isEmpty()) {
        chart.setData(FXCollections.observableArrayList(Arrays.asList(
            sonarSeries, pirSeries, microwaveSeries, laserSeries,
            readTripsSeries)));
        chart.setLegendVisible(true);
      }
      // chart legend will not update using the data node style- need to
      // set it here
      Platform.runLater(new Runnable() {
        @Override
        public void run() {
          final Set<Node> nodes = chart
              .lookupAll(".chart-legend-item-symbol");
          int i = -1;
          for (final Node n : nodes) {
            applyBarFillColorHex(n, getBarFillColorHex(++i));
          }
        }
      });
    } else {
      if (!chart.getData().isEmpty()) {
        chart.getData().clear();
      }
      chart.setLegendVisible(false);
    }
    return rnrs.size();
  }

  /**
   * Adds {@linkplain XYChart.Data} to a {@linkplain XYChart.Series} for a
   * specified index and sets the fill based upon the index.
   *
   * @param chart
   *         the {@linkplain XYChart}
   * @param series
   *         the {@linkplain XYChart.Series
   * @param data
   *         the {@linkplain XYChart.Data}
   * @param index
   *         the index
   */
  protected <X, Y> void addData(final XYChart<X, Y> chart,
      final XYChart.Series<X, Y> series, final XYChart.Data<X, Y> data,
      final int index) {
    series.getData().add(data);
    final String colorHex = getBarFillColorHex(index);
    series.nodeProperty().addListener(new ChangeListener<Node>() {
      @Override
      public void changed(final ObservableValue<? extends Node> ob,
          final Node oldNode, final Node newNode) {
        applyBarFillColorHex(newNode, colorHex);
      }
    });
    data.nodeProperty().addListener(new ChangeListener<Node>() {
      @Override
      public void changed(final ObservableValue<? extends Node> ob,
          final Node oldNode, final Node newNode) {
        applyBarFillColorHex(newNode, colorHex);
      }
    });
  }

  /**
   * Gets the hexadecimal {@linkplain Color} used for items in the
   * {@linkplain XYChart}
   *
   * @param index
   *            the index of the item
   * @return the hexadecimal {@linkplain Color}
   */
  protected String getBarFillColorHex(final int index) {
    final String color = GuiUtil.COLORS_CHART[index].toString();
    return '#' + color.substring(2, color.length() - 2);
  }

  /**
   * Applies the hexadecimal {@linkplain Color} to a {@linkplain Node}
   *
   * @param node
   *            the {@linkplain Node} to apply the hexadecimal
   *            {@linkplain Color} to
   * @param colorHex
   *            the hexadecimal {@linkplain Color}
   */
  protected void applyBarFillColorHex(final Node node, final String colorHex) {
    node.setStyle("-fx-bar-fill: " + colorHex + ";");
    final DropShadow ds = new DropShadow();
    ds.setOffsetX(3.0);
    ds.setOffsetY(3.0);
    final Lighting lighting = new Lighting();
    lighting.setSurfaceScale(1d);
    lighting.setLight(new Light.Distant());
    ds.setInput(lighting);
    node.setEffect(ds);
  }
}
TOP

Related Classes of org.ugate.gui.view.SensorReadingHistory

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.