forked from upstream-mirrors/OpenTracks
Breaking down chart drawing methods as suggested by Sandor.
This commit is contained in:
@@ -510,78 +510,102 @@ public class ChartView extends View {
|
|||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas c) {
|
protected void onDraw(Canvas c) {
|
||||||
synchronized (data) {
|
synchronized (data) {
|
||||||
if (w != c.getWidth() || h != c.getHeight()) {
|
updateEffectiveDimensionsIfChanged(c);
|
||||||
// Dimensions have changed (for example due to orientation change).
|
|
||||||
w = c.getWidth();
|
// Keep original state.
|
||||||
h = c.getHeight();
|
|
||||||
effectiveWidth = Math.max(0, w - leftBorder - RIGHT_BORDER);
|
|
||||||
effectiveHeight = Math.max(0, h - topBorder - bottomBorder);
|
|
||||||
setUpPath();
|
|
||||||
}
|
|
||||||
c.save();
|
c.save();
|
||||||
|
|
||||||
c.drawColor(Color.WHITE);
|
c.drawColor(Color.WHITE);
|
||||||
if (data.size() < 1) {
|
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
// No data, draw only axes
|
||||||
drawXAxis(c);
|
drawXAxis(c);
|
||||||
drawYAxis(c);
|
drawYAxis(c);
|
||||||
c.restore();
|
c.restore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clip to graph drawing space
|
||||||
c.save();
|
c.save();
|
||||||
c.clipRect(leftBorder + 1 + getScrollX(), topBorder + 1,
|
clipToGraphSpace(c);
|
||||||
w - RIGHT_BORDER + getScrollX() - 1, h - bottomBorder - 1);
|
|
||||||
|
|
||||||
|
// Draw the grid and the data on it.
|
||||||
drawGrid(c);
|
drawGrid(c);
|
||||||
|
drawDataSeries(c);
|
||||||
|
drawWaypoints(c);
|
||||||
|
|
||||||
// Draw the data series.
|
// Go back to full canvas drawing.
|
||||||
for (ChartValueSeries cvs : series) {
|
|
||||||
if (cvs.isEnabled() && cvs.hasData()) {
|
|
||||||
cvs.drawPath(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the waypoints.
|
|
||||||
for (int i = 1; i < waypoints.size(); i++) {
|
|
||||||
final Waypoint waypoint = waypoints.get(i);
|
|
||||||
if (waypoint.getLocation() == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
c.save();
|
|
||||||
|
|
||||||
final float x = getWaypointX(waypoint);
|
|
||||||
c.drawLine(x, h - bottomBorder, x, topBorder, gridPaint);
|
|
||||||
c.translate(x - markerWidth / 2, markerHeight);
|
|
||||||
if (waypoints.get(i).getType() == Waypoint.TYPE_STATISTICS) {
|
|
||||||
statsMarker.draw(c);
|
|
||||||
} else {
|
|
||||||
waypointMarker.draw(c);
|
|
||||||
}
|
|
||||||
c.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
c.restore();
|
c.restore();
|
||||||
|
|
||||||
// Draw the axis and labels.
|
// Draw the axes and their labels.
|
||||||
drawXLabels(c);
|
drawAxesAndLabels(c);
|
||||||
drawXAxis(c);
|
|
||||||
drawSeriesTitles(c);
|
|
||||||
|
|
||||||
c.translate(getScrollX(), 0);
|
// Go back to original state.
|
||||||
drawYAxis(c);
|
c.restore();
|
||||||
float density = getContext().getResources().getDisplayMetrics().density;
|
|
||||||
final int spacer = (int) (5 * density);
|
// Draw the pointer
|
||||||
int x = leftBorder - spacer;
|
if (showPointer) {
|
||||||
for (ChartValueSeries cvs : series) {
|
drawPointer(c);
|
||||||
if (cvs.isEnabled() && cvs.hasData()) {
|
}
|
||||||
x -= drawYLabels(cvs, c, x) + spacer;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void clipToGraphSpace(Canvas c) {
|
||||||
|
c.clipRect(leftBorder + 1 + getScrollX(), topBorder + 1,
|
||||||
|
w - RIGHT_BORDER + getScrollX() - 1, h - bottomBorder - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawAxesAndLabels(Canvas c) {
|
||||||
|
// Draw the axis and labels.
|
||||||
|
drawXLabels(c);
|
||||||
|
drawXAxis(c);
|
||||||
|
drawSeriesTitles(c);
|
||||||
|
|
||||||
|
c.translate(getScrollX(), 0);
|
||||||
|
drawYAxis(c);
|
||||||
|
float density = getContext().getResources().getDisplayMetrics().density;
|
||||||
|
final int spacer = (int) (5 * density);
|
||||||
|
int x = leftBorder - spacer;
|
||||||
|
for (ChartValueSeries cvs : series) {
|
||||||
|
if (cvs.isEnabled() && cvs.hasData()) {
|
||||||
|
x -= drawYLabels(cvs, c, x) + spacer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawPointer(Canvas c) {
|
||||||
|
c.translate(getX(maxX) - pointer.getIntrinsicWidth() / 2,
|
||||||
|
getY(series[0], data.get(data.size() - 1)[1])
|
||||||
|
- pointer.getIntrinsicHeight() / 2 - 12);
|
||||||
|
pointer.draw(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawWaypoints(Canvas c) {
|
||||||
|
// Draw the waypoints.
|
||||||
|
for (int i = 1; i < waypoints.size(); i++) {
|
||||||
|
final Waypoint waypoint = waypoints.get(i);
|
||||||
|
if (waypoint.getLocation() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
c.save();
|
||||||
|
|
||||||
|
final float x = getWaypointX(waypoint);
|
||||||
|
c.drawLine(x, h - bottomBorder, x, topBorder, gridPaint);
|
||||||
|
c.translate(x - markerWidth / 2, markerHeight);
|
||||||
|
if (waypoints.get(i).getType() == Waypoint.TYPE_STATISTICS) {
|
||||||
|
statsMarker.draw(c);
|
||||||
|
} else {
|
||||||
|
waypointMarker.draw(c);
|
||||||
}
|
}
|
||||||
c.restore();
|
c.restore();
|
||||||
if (showPointer && !data.isEmpty()) {
|
}
|
||||||
c.translate(getX(maxX) - pointer.getIntrinsicWidth() / 2,
|
}
|
||||||
getY(series[0], data.get(data.size() - 1)[1])
|
|
||||||
- pointer.getIntrinsicHeight() / 2 - 12);
|
private void drawDataSeries(Canvas c) {
|
||||||
pointer.draw(c);
|
// Draw the data series.
|
||||||
|
for (ChartValueSeries cvs : series) {
|
||||||
|
if (cvs.isEnabled() && cvs.hasData()) {
|
||||||
|
cvs.drawPath(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -603,7 +627,7 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the path that is used to draw the histogram in onDraw(). The path
|
* Sets up the path that is used to draw the chart in onDraw(). The path
|
||||||
* needs to be updated any time after the data or histogram dimensions change.
|
* needs to be updated any time after the data or histogram dimensions change.
|
||||||
*/
|
*/
|
||||||
private void setUpPath() {
|
private void setUpPath() {
|
||||||
@@ -611,49 +635,57 @@ public class ChartView extends View {
|
|||||||
for (ChartValueSeries cvs : series) {
|
for (ChartValueSeries cvs : series) {
|
||||||
cvs.getPath().reset();
|
cvs.getPath().reset();
|
||||||
}
|
}
|
||||||
if (data.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All of the data points to the respective series.
|
if (!data.isEmpty()) {
|
||||||
// TODO: Come up with a better sampling than Math.max(1, (maxZoomLevel - zoomLevel + 1) / 2);
|
drawPath();
|
||||||
int sampling = 1;
|
closePath();
|
||||||
for (int i = 0; i < data.size(); i += sampling) {
|
|
||||||
double[] d = data.get(i);
|
|
||||||
int min = Math.min(series.length, d.length - 1);
|
|
||||||
for (int j = 0; j < min; ++j) {
|
|
||||||
ChartValueSeries cvs = series[j];
|
|
||||||
Path path = cvs.getPath();
|
|
||||||
int x = getX(d[0]);
|
|
||||||
int y = getY(cvs, d[j + 1]);
|
|
||||||
if (i == 0) {
|
|
||||||
path.moveTo(x, y);
|
|
||||||
} else {
|
|
||||||
path.lineTo(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Close the path.
|
/** Actually draws the data points as a path. */
|
||||||
int yCorner = topBorder + effectiveHeight;
|
private void drawPath() {
|
||||||
int xCorner = getX(data.get(0)[0]);
|
// All of the data points to the respective series.
|
||||||
int min = series.length;
|
// TODO: Come up with a better sampling than Math.max(1, (maxZoomLevel - zoomLevel + 1) / 2);
|
||||||
for (int j = 0; j < min; j++) {
|
int sampling = 1;
|
||||||
|
for (int i = 0; i < data.size(); i += sampling) {
|
||||||
|
double[] d = data.get(i);
|
||||||
|
int min = Math.min(series.length, d.length - 1);
|
||||||
|
for (int j = 0; j < min; ++j) {
|
||||||
ChartValueSeries cvs = series[j];
|
ChartValueSeries cvs = series[j];
|
||||||
Path path = cvs.getPath();
|
Path path = cvs.getPath();
|
||||||
int first = getFirstPointPopulatedIndex(j + 1);
|
int x = getX(d[0]);
|
||||||
if (first != -1) {
|
int y = getY(cvs, d[j + 1]);
|
||||||
// Bottom right corner
|
if (i == 0) {
|
||||||
path.lineTo(getX(data.get(data.size() - 1)[0]), yCorner);
|
path.moveTo(x, y);
|
||||||
// Bottom left corner
|
} else {
|
||||||
path.lineTo(xCorner, yCorner);
|
path.lineTo(x, y);
|
||||||
// Top right corner
|
|
||||||
path.lineTo(xCorner, getY(cvs, data.get(first)[j + 1]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Closes the drawn path so it looks like a solid graph. */
|
||||||
|
private void closePath() {
|
||||||
|
// Close the path.
|
||||||
|
int yCorner = topBorder + effectiveHeight;
|
||||||
|
int xCorner = getX(data.get(0)[0]);
|
||||||
|
int min = series.length;
|
||||||
|
for (int j = 0; j < min; j++) {
|
||||||
|
ChartValueSeries cvs = series[j];
|
||||||
|
Path path = cvs.getPath();
|
||||||
|
int first = getFirstPointPopulatedIndex(j + 1);
|
||||||
|
if (first != -1) {
|
||||||
|
// Bottom right corner
|
||||||
|
path.lineTo(getX(data.get(data.size() - 1)[0]), yCorner);
|
||||||
|
// Bottom left corner
|
||||||
|
path.lineTo(xCorner, yCorner);
|
||||||
|
// Top right corner
|
||||||
|
path.lineTo(xCorner, getY(cvs, data.get(first)[j + 1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the index of the first point which has a series populated.
|
* Find the index of the first point which has a series populated.
|
||||||
* @param seriesIndex The index of the value series to search for.
|
* @param seriesIndex The index of the value series to search for.
|
||||||
@@ -691,10 +723,24 @@ public class ChartView extends View {
|
|||||||
float density = getContext().getResources().getDisplayMetrics().density;
|
float density = getContext().getResources().getDisplayMetrics().density;
|
||||||
maxLength = Math.max(maxLength, 1);
|
maxLength = Math.max(maxLength, 1);
|
||||||
leftBorder = (int) (density * (4 + 8 * maxLength));
|
leftBorder = (int) (density * (4 + 8 * maxLength));
|
||||||
effectiveWidth = w - leftBorder - RIGHT_BORDER;
|
|
||||||
bottomBorder = (int) (density * BOTTOM_BORDER);
|
bottomBorder = (int) (density * BOTTOM_BORDER);
|
||||||
topBorder = (int) (density * TOP_BORDER);
|
topBorder = (int) (density * TOP_BORDER);
|
||||||
effectiveHeight = h - topBorder - bottomBorder;
|
updateEffectiveDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateEffectiveDimensions() {
|
||||||
|
effectiveWidth = Math.max(0, w - leftBorder - RIGHT_BORDER);
|
||||||
|
effectiveHeight = Math.max(0, h - topBorder - bottomBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateEffectiveDimensionsIfChanged(Canvas c) {
|
||||||
|
if (w != c.getWidth() || h != c.getHeight()) {
|
||||||
|
// Dimensions have changed (for example due to orientation change).
|
||||||
|
w = c.getWidth();
|
||||||
|
h = c.getHeight();
|
||||||
|
updateEffectiveDimensions();
|
||||||
|
setUpPath();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getX(double distance) {
|
private int getX(double distance) {
|
||||||
@@ -795,10 +841,6 @@ public class ChartView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void drawGrid(Canvas c) {
|
private void drawGrid(Canvas c) {
|
||||||
if (data.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float rightEdge = getX(maxX);
|
float rightEdge = getX(maxX);
|
||||||
for (int i = 1; i < MAX_INTERVALS; ++i) {
|
for (int i = 1; i < MAX_INTERVALS; ++i) {
|
||||||
int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
|
int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
|
||||||
|
|||||||
Reference in New Issue
Block a user