mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-04 18:43:07 +02:00
286 lines
7.2 KiB
Java
286 lines
7.2 KiB
Java
/*
|
|
* Copyright 2009 Google Inc.
|
|
*
|
|
* 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 com.google.android.apps.mytracks;
|
|
|
|
import com.google.android.apps.mytracks.stats.ExtremityMonitor;
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Paint;
|
|
import android.graphics.Paint.Style;
|
|
import android.graphics.Path;
|
|
|
|
import java.text.NumberFormat;
|
|
|
|
/**
|
|
* This class encapsulates the meta data for one series of chart values.
|
|
*
|
|
* @author Sandor Dornbush
|
|
*/
|
|
public class ChartValueSeries {
|
|
|
|
private static final float STROKE_WIDTH = 2f;
|
|
|
|
private final ExtremityMonitor extremityMonitor;
|
|
private final NumberFormat numberFormat;
|
|
private final Path path;
|
|
private final Paint fillPaint;
|
|
private final Paint strokePaint;
|
|
private final Paint labelPaint;
|
|
private final YAxisDimension markingInterval;
|
|
private String title;
|
|
|
|
private boolean enabled = true;
|
|
private int interval = 1;
|
|
private int effectiveMin = 0;
|
|
private int effectiveMax = 1;
|
|
|
|
/**
|
|
* This class to calculates the y axis dimension, interval, effective min, and
|
|
* effective max.
|
|
*/
|
|
public static class YAxisDimension {
|
|
private final int numberOfIntervals;
|
|
private final int absoluteMin;
|
|
private final int absoluteMax;
|
|
private final int[] intervalValues;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param numberOfIntervals the number of intervals
|
|
* @param absoluteMin the absolute minimum value
|
|
* @param absoluteMax the absolute maximum value
|
|
* @param intervalValues the list of interval values
|
|
*/
|
|
public YAxisDimension(
|
|
int numberOfIntervals, int absoluteMin, int absoluteMax, int[] intervalValues) {
|
|
this.numberOfIntervals = numberOfIntervals;
|
|
this.absoluteMin = absoluteMin;
|
|
this.absoluteMax = absoluteMax;
|
|
this.intervalValues = intervalValues;
|
|
}
|
|
|
|
/**
|
|
* Gets the y axis dimension. Returns an array of int[3], containing interval, effectiveMin,
|
|
* and effectiveMax.
|
|
*
|
|
* @param min the min value
|
|
* @param max the max value
|
|
*/
|
|
public int[] getYAxisDimension(double min, double max) {
|
|
min = Math.max(min, absoluteMin);
|
|
max = Math.min(max, absoluteMax);
|
|
int interval = 0;
|
|
int effectiveMin = 0;
|
|
for (int i = 0; i < intervalValues.length; i++) {
|
|
interval = intervalValues[i];
|
|
effectiveMin = getEffetiveMin(min, interval);
|
|
double targetInterval = (max - effectiveMin) / numberOfIntervals;
|
|
if (interval >= targetInterval) {
|
|
break;
|
|
}
|
|
}
|
|
int effectiveMax = getEffectiveMax(max, interval);
|
|
return new int[] { interval, effectiveMin, effectiveMax };
|
|
}
|
|
|
|
/**
|
|
* Gets the effective min value.
|
|
*
|
|
* @param min the min value
|
|
* @param interval the interval
|
|
*/
|
|
private int getEffetiveMin(double min, int interval) {
|
|
int value = (int) (min / interval) * interval;
|
|
// value > min if min is negative
|
|
if (value > min) {
|
|
return value - interval;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Gets the effective max value
|
|
*
|
|
* @param max the max value
|
|
* @param interval the interval
|
|
*/
|
|
private int getEffectiveMax(double max, int interval) {
|
|
return ((int) (max / interval)) * interval + interval;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a new chart value series.
|
|
*
|
|
* @param context the context
|
|
* @param fillColor the fill color
|
|
* @param strokeColor the stroke color
|
|
* @param yAxisDimension the marking interval
|
|
* @param titleId the title id
|
|
*/
|
|
public ChartValueSeries(Context context, int fillColor, int strokeColor,
|
|
YAxisDimension yAxisDimension, int titleId) {
|
|
extremityMonitor = new ExtremityMonitor();
|
|
numberFormat = NumberFormat.getIntegerInstance();
|
|
path = new Path();
|
|
fillPaint = new Paint();
|
|
fillPaint.setStyle(Style.FILL);
|
|
fillPaint.setColor(context.getResources().getColor(fillColor));
|
|
fillPaint.setAntiAlias(true);
|
|
if (strokeColor != -1) {
|
|
strokePaint = new Paint();
|
|
strokePaint.setStyle(Style.STROKE);
|
|
strokePaint.setColor(context.getResources().getColor(strokeColor));
|
|
strokePaint.setAntiAlias(true);
|
|
// Make a copy of the stroke paint with the default thickness
|
|
labelPaint = new Paint(strokePaint);
|
|
strokePaint.setStrokeWidth(STROKE_WIDTH);
|
|
} else {
|
|
strokePaint = null;
|
|
labelPaint = fillPaint;
|
|
}
|
|
this.markingInterval = yAxisDimension;
|
|
title = context.getString(titleId);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the series has data.
|
|
*/
|
|
public boolean hasData() {
|
|
return extremityMonitor.hasData();
|
|
}
|
|
|
|
/**
|
|
* Updates the series with a new value.
|
|
*
|
|
* @param value the new value
|
|
*/
|
|
public void update(double value) {
|
|
extremityMonitor.update(value);
|
|
}
|
|
|
|
/**
|
|
* Gets the number format for the series.
|
|
*/
|
|
public NumberFormat getNumberFormat() {
|
|
return numberFormat;
|
|
}
|
|
|
|
/**
|
|
* Gets the path.
|
|
*/
|
|
public Path getPath() {
|
|
return path;
|
|
}
|
|
|
|
/**
|
|
* Gets the label paint.
|
|
*/
|
|
public Paint getLabelPaint() {
|
|
return labelPaint;
|
|
}
|
|
|
|
/**
|
|
* Gets the title.
|
|
*/
|
|
public String getTitle() {
|
|
return title;
|
|
}
|
|
|
|
/**
|
|
* Sets the title.
|
|
*
|
|
* @param title the title
|
|
*/
|
|
public void setTitle(String title) {
|
|
this.title = title;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the series is enabled.
|
|
*/
|
|
public boolean isEnabled() {
|
|
return enabled;
|
|
}
|
|
|
|
/**
|
|
* Sets the enabled value.
|
|
*
|
|
* @param enabled true to enable
|
|
*/
|
|
public void setEnabled(boolean enabled) {
|
|
this.enabled = enabled;
|
|
}
|
|
|
|
/**
|
|
* Draws the path on canvas.
|
|
*
|
|
* @param canvas the canvas
|
|
*/
|
|
public void drawPath(Canvas canvas) {
|
|
canvas.drawPath(path, fillPaint);
|
|
if (strokePaint != null) {
|
|
canvas.drawPath(path, strokePaint);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the y axis dimension.
|
|
*/
|
|
public void updateDimension() {
|
|
boolean hasData = extremityMonitor.hasData();
|
|
double min = hasData ? extremityMonitor.getMin() : 0.0;
|
|
double max = hasData ? extremityMonitor.getMax() : 1.0;
|
|
int[] dimension = markingInterval.getYAxisDimension(min, max);
|
|
interval = dimension[0];
|
|
effectiveMin = dimension[1];
|
|
effectiveMax = dimension[2];
|
|
}
|
|
|
|
/**
|
|
* Gets the y axis interval value.
|
|
*/
|
|
public int getInterval() {
|
|
return interval;
|
|
}
|
|
|
|
/**
|
|
* Gets the minimum value.
|
|
*/
|
|
public int getMin() {
|
|
return effectiveMin;
|
|
}
|
|
|
|
/**
|
|
* Gets the maximum value.
|
|
*/
|
|
@VisibleForTesting
|
|
int getMax() {
|
|
return effectiveMax;
|
|
}
|
|
|
|
/**
|
|
* Gets the maximum label length.
|
|
*/
|
|
public int getMaxLabelLength() {
|
|
return Math.max(numberFormat.format(getMin()).length(), numberFormat.format(getMax()).length());
|
|
}
|
|
}
|