docs: @Override
      protected void onDataChanged() {
  
          if(!mSeries.isEmpty()) {
              int   seriesCount  = mSeries.size();
              float maxValue     = 0.f;
              float minValue     = Float.MAX_VALUE;
              mNegativeValue     = 0.f;
              mNegativeOffset    = 0.f;
              mHasNegativeValues = false;
  
              // calculate the maximum and minimum value present in data
              for (ValueLineSeries series : mSeries) {
                  for (ValueLinePoint point : series.getSeries()) {
  
                      if (point.getValue() > maxValue)
                          maxValue = point.getValue();
  
                      if (point.getValue() < mNegativeValue)
                          mNegativeValue = point.getValue();
  
                      if (point.getValue() < minValue)
                          minValue = point.getValue();
                  }
              }
  
              // check if the standardvalue is greater than all other values
              if(mShowStandardValues) {
                  for (StandardValue value : mStandardValues) {
  
                      if(value.getValue() > maxValue)
                          maxValue = value.getValue();
  
                      if (value.getValue() < mNegativeValue)
                          mNegativeValue = value.getValue();
  
                      if (value.getValue() < minValue)
                          minValue = value.getValue();
                  }
              }
  
  
              if(!mUseDynamicScaling) {
                  minValue = 0;
              }
              else {
                  minValue *= mScalingFactor;
              }
  
              // check if values below zero were found
              if(mNegativeValue < 0) {
                  mHasNegativeValues = true;
                  maxValue += (mNegativeValue * -1);
                  minValue = 0;
              }
  
  
              float heightMultiplier  = mUsableGraphHeight / (maxValue - minValue);
  
              // calculate the offset
              if(mHasNegativeValues) {
                  mNegativeOffset = (mNegativeValue * -1) * heightMultiplier;
              }
  
              // calculate the y position for standardValue
              if(mShowStandardValues) {
                  for (StandardValue value : mStandardValues) {
                      value.setY((int) (mGraphHeight - mNegativeOffset - ((value.getValue() - minValue) * heightMultiplier)));
                  }
              }
  
              for (ValueLineSeries series : mSeries) {
  
                  int   seriesPointCount  = series.getSeries().size();
  
                  // check if more than one point is available
                  if (seriesPointCount <= 1) {
                      Log.w(LOG_TAG, "More than one point should be available!");
                  }
                  else {
  
                      float widthOffset = (float) mGraphWidth / (float) seriesPointCount;
                      widthOffset += widthOffset / seriesPointCount;
                      float currentOffset = 0;
                      series.setWidthOffset(widthOffset);
  
                      // used to store first point and set it later as ending point, if a graph fill is selected
                      float firstX = currentOffset;
                      float firstY = mGraphHeight - ((series.getSeries().get(0).getValue() - minValue) * heightMultiplier);
  
                      Path path = new Path();
                      path.moveTo(firstX, firstY);
                      series.getSeries().get(0).setCoordinates(new Point2D(firstX, firstY));
  
                      // If a cubic curve should be drawn then calculate cubic path
                      // If not then just draw basic lines
                      if (mUseCubic) {
                          Point2D P1 = new Point2D();
                          Point2D P2 = new Point2D();
                          Point2D P3 = new Point2D();
  
                          for (int i = 0; i < seriesPointCount - 1; i++) {
  
                              int i3 = (seriesPointCount - i) < 3 ? i + 1 : i + 2;
                              float offset2 = (seriesPointCount - i) < 3 ? mGraphWidth : currentOffset + widthOffset;
                              float offset3 = (seriesPointCount - i) < 3 ? mGraphWidth : currentOffset + (2*widthOffset);
  
                              P1.setX(currentOffset);
                              P1.setY(mGraphHeight - ((series.getSeries().get(i).getValue() - minValue) * heightMultiplier));
  
                              P2.setX(offset2);
                              P2.setY(mGraphHeight - ((series.getSeries().get(i + 1).getValue() - minValue) * heightMultiplier));
                              Utils.calculatePointDiff(P1, P2, P1, mSecondMultiplier);
  
                              P3.setX(offset3);
                              P3.setY(mGraphHeight - ((series.getSeries().get(i3).getValue() - minValue) * heightMultiplier));
                              Utils.calculatePointDiff(P2, P3, P3, mFirstMultiplier);
  
                              currentOffset += widthOffset;
  
                              series.getSeries().get(i + 1).setCoordinates(new Point2D(P2.getX(), P2.getY()));
                              path.cubicTo(P1.getX(), P1.getY(), P2.getX(), P2.getY(), P3.getX(), P3.getY());
                          }
                      } else {
                          boolean first = true;
                          int count = 1;
  
                          for (ValueLinePoint point : series.getSeries()) {
                              if (first) {
                                  first = false;
                                  continue;
                              }
                              currentOffset += widthOffset;
                              if (count == seriesPointCount - 1) {
                                  // if the last offset is smaller than the width, then the offset should be as long as the graph
                                  // to prevent a graph drop
                                  if (currentOffset < mGraphWidth) {
                                      currentOffset = mGraphWidth;
                                  }
                              }
                              point.setCoordinates(new Point2D(currentOffset, mGraphHeight - ((point.getValue() - minValue) * heightMultiplier)));
                              path.lineTo(point.getCoordinates().getX(), point.getCoordinates().getY());
                              count++;
                          }
                      }
  
                      if (mUseOverlapFill) {
                          path.lineTo(mGraphWidth, mGraphHeight);
                          path.lineTo(0, mGraphHeight);
                          path.lineTo(firstX, firstY);
                      }
  
                      series.setPath(path);
                  }
              }
  
              if(calculateLegendBounds())
                  Utils.calculateLegendInformation(mSeries.get(0).getSeries(), 0, mGraphWidth, mLegendPaint);
  
              // set the first point for the indicator
              if(mShowIndicator && mSeries.size() == 1) {
                  int size = mSeries.get(0).getSeries().size();
                  int index;
  
                  // Only calculate if more than one point is available
                  if (size > 1) {
                      // position the indicator in the middle at the nearest value
                      if (size == 3) {
                          index = size / 2;
                      } else {
                          index = (size / 2) - 1;
                      }
  
                      mFocusedPoint = mSeries.get(0).getSeries().get(index);
                      mTouchedArea = mFocusedPoint.getCoordinates();
  
                      calculateValueTextHeight();
                  }
              }
  
              resetZoom(false);
          }
  
          super.onDataChanged();
      }