diff --git a/MyTracks/src/com/google/android/apps/mytracks/ChartActivity.java b/MyTracks/src/com/google/android/apps/mytracks/ChartActivity.java index 25757e541..73f201776 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ChartActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ChartActivity.java @@ -60,6 +60,7 @@ import java.util.ArrayList; public class ChartActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener { + private final static int BUFFER_SIZE = 1024; private double profileLength = 0; private boolean metricUnits = true; @@ -101,7 +102,7 @@ public class ChartActivity extends Activity implements /* * UI elements: */ - private ChartView cv; + private ChartView chartView; private MenuItem chartSettingsMenuItem; private LinearLayout busyPane; private ZoomControls zoomControls; @@ -118,10 +119,10 @@ public class ChartActivity extends Activity implements @Override public void run() { busyPane.setVisibility(View.GONE); - zoomControls.setIsZoomInEnabled(cv.canZoomIn()); - zoomControls.setIsZoomOutEnabled(cv.canZoomOut()); - cv.setShowPointer(selectedTrackIsRecording()); - cv.invalidate(); + zoomControls.setIsZoomInEnabled(chartView.canZoomIn()); + zoomControls.setIsZoomOutEnabled(chartView.canZoomOut()); + chartView.setShowPointer(selectedTrackIsRecording()); + chartView.invalidate(); } }; @@ -158,54 +159,12 @@ public class ChartActivity extends Activity implements private Handler updateTrackHandler; /** - * A runnable that update the profile from the provider. + * A runnable that updates the profile from the provider. */ private final Runnable updateTrackRunnable = new Runnable() { @Override public void run() { - Log.d(MyTracksConstants.TAG, "MyTracks: Updating chart."); - Track track = providerUtils.getTrack(recordingTrackId); - if (track == null) { - Log.w(MyTracksConstants.TAG, "MyTracks: track not found"); - return; - } - Cursor cursor = null; - try { - cursor = providerUtils.getLocationsCursor(recordingTrackId, - lastSeenLocationId + 1, - MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS - cv.getData().size(), - true); - if (cursor != null) { - if (cursor.moveToLast()) { - final int idColumnIdx = - cursor.getColumnIndexOrThrow(TrackPointsColumns._ID); - ArrayList data = new ArrayList(); - // Need two locations so we can keep track of the last location. - Location location = new MyTracksLocation(""); - do { - lastSeenLocationId = cursor.getLong(idColumnIdx); - providerUtils.fillLocation(cursor, location); - if (MyTracksUtils.isValidLocation(location)) { - double[] point = new double[6]; - location = getDataPoint(location, track, point); - data.add(point); - } - } while (cursor.moveToPrevious()); - cv.addDataPoints(data); - } - } - } catch (RuntimeException e) { - Log.w(MyTracksConstants.TAG, "Caught an unexpected exception.", e); - } finally { - if (cursor != null) { - cursor.close(); - } - uiHandler.post(new Runnable() { - public void run() { - cv.invalidate(); - } - }); - } + readNewTrackPoints(); } }; @@ -222,13 +181,13 @@ public class ChartActivity extends Activity implements metricUnits = sharedPreferences.getBoolean(getString(R.string.metric_units_key), true); - cv.setMetricUnits(metricUnits); + chartView.setMetricUnits(metricUnits); readProfileAsync(); } else if (key.equals(getString(R.string.report_speed_key))) { reportSpeed = sharedPreferences.getBoolean(getString(R.string.report_speed_key), true); - cv.setReportSpeed(reportSpeed, this); + chartView.setReportSpeed(reportSpeed, this); readProfileAsync(); } else if (key.equals(getString(R.string.recording_track_key))) { recordingTrackId = @@ -254,11 +213,11 @@ public class ChartActivity extends Activity implements requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.mytracks_charts); ViewGroup layout = (ViewGroup) findViewById(R.id.elevation_chart); - cv = new ChartView(this); - cv.setMode(this.mode); + chartView = new ChartView(this); + chartView.setMode(this.mode); LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); - layout.addView(cv, params); + layout.addView(chartView, params); SharedPreferences preferences = getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0); @@ -269,10 +228,10 @@ public class ChartActivity extends Activity implements preferences.getLong(getString(R.string.recording_track_key), -1); metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true); - cv.setMetricUnits(metricUnits); + chartView.setMetricUnits(metricUnits); reportSpeed = preferences.getBoolean(getString(R.string.report_speed_key), true); - cv.setReportSpeed(reportSpeed, this); + chartView.setReportSpeed(reportSpeed, this); preferences.registerOnSharedPreferenceChangeListener(this); } @@ -332,7 +291,7 @@ public class ChartActivity extends Activity implements ChartActivity.this.runOnUiThread(new Runnable() { @Override public void run() { - cv.invalidate(); + chartView.invalidate(); } }); } @@ -384,21 +343,21 @@ public class ChartActivity extends Activity implements } private void zoomIn() { - cv.zoomIn(); - zoomControls.setIsZoomInEnabled(cv.canZoomIn()); - zoomControls.setIsZoomOutEnabled(cv.canZoomOut()); + chartView.zoomIn(); + zoomControls.setIsZoomInEnabled(chartView.canZoomIn()); + zoomControls.setIsZoomOutEnabled(chartView.canZoomOut()); } private void zoomOut() { - cv.zoomOut(); - zoomControls.setIsZoomInEnabled(cv.canZoomIn()); - zoomControls.setIsZoomOutEnabled(cv.canZoomOut()); + chartView.zoomOut(); + zoomControls.setIsZoomInEnabled(chartView.canZoomIn()); + zoomControls.setIsZoomOutEnabled(chartView.canZoomOut()); } public void setMode(Mode newMode) { if (this.mode != newMode) { this.mode = newMode; - cv.setMode(this.mode); + chartView.setMode(this.mode); readProfileAsync(); } } @@ -408,12 +367,12 @@ public class ChartActivity extends Activity implements } public void setSeriesEnabled(int index, boolean enabled) { - cv.getChartValueSeries(index).setEnabled(enabled); + chartView.getChartValueSeries(index).setEnabled(enabled); runOnUiThread(updateChart); } public boolean isSeriesEnabled(int index) { - return cv.getChartValueSeries(index).isEnabled(); + return chartView.getChartValueSeries(index).isEnabled(); } private void readWaypoints() { @@ -421,7 +380,7 @@ public class ChartActivity extends Activity implements return; } Cursor cursor = null; - cv.clearWaypoints(); + chartView.clearWaypoints(); try { // We will silently drop extra waypoints to make the app responsive. cursor = @@ -431,7 +390,7 @@ public class ChartActivity extends Activity implements if (cursor.moveToFirst()) { do { Waypoint wpt = providerUtils.createWaypoint(cursor); - cv.addWaypoint(wpt); + chartView.addWaypoint(wpt); } while (cursor.moveToNext()); } } @@ -575,7 +534,7 @@ public class ChartActivity extends Activity implements * Sets the chart data points reading from the provider. This is non-blocking. */ private void readProfileAsync() { - cv.reset(); + chartView.reset(); updateTrackHandler.post(new Runnable() { public void run() { runOnUiThread(showSpinner); @@ -594,7 +553,6 @@ public class ChartActivity extends Activity implements profileLength = 0; lastLocation = null; startTime = -1; - Cursor cursor = null; if (selectedTrackId < 0) { return; } @@ -602,26 +560,70 @@ public class ChartActivity extends Activity implements if (track == null) { return; } - long lastLocationRead = track.getStartId(); - long totalLocations = track.getStopId() - track.getStartId(); + lastSeenLocationId = track.getStartId(); + final ArrayList theData = readPointsToList(track); + runOnUiThread(new Runnable() { + public void run() { + chartView.setDataPoints(theData); + } + }); + } - // Limit the number of chart readings. Ideally we would want around 1024. - int chartSamplingFrequency = Math.max(1, (int) (totalLocations / 1024.0)); - int bufferSize = 1024; + /** + * Read all new track points. + */ + private void readNewTrackPoints() { + Log.i(MyTracksConstants.TAG, "MyTracks: Updating chart last seen: " + lastSeenLocationId); + Track track = providerUtils.getTrack(recordingTrackId); + if (track == null) { + Log.w(MyTracksConstants.TAG, "MyTracks: track not found"); + return; + } + chartView.addDataPoints(readPointsToList(track)); + uiHandler.post(new Runnable() { + public void run() { + chartView.invalidate(); + } + }); + Log.i(MyTracksConstants.TAG, "MyTracks: Updated chart last seen: " + lastSeenLocationId); + } + + /** + * Get the frequency at which points should be displayed. + * Limit the number of chart readings. Ideally we would want around 1024. + * @param track The track which will be displayed. + * @return The inverse of the frequency of points to be displayed. + */ + private int getSamplingFrequency(Track track) { + long totalLocations = track.getStopId() - track.getStartId(); + return Math.max(1, (int) (totalLocations / 1024.0)); + } + + private Cursor getLocationsCursor(long lastLocationRead) { + return providerUtils.getLocationsCursor(selectedTrackId, lastLocationRead, BUFFER_SIZE, false); + } + + /** + * Read all of the points to a list. + * @param track The track which will be displayed. + * @return + */ + private ArrayList readPointsToList(Track track) { + Cursor cursor = null; + long lastLocationRead = lastSeenLocationId; + int points = 0; + int chartSamplingFrequency = getSamplingFrequency(track); + ArrayList result = new ArrayList(); + // Need two locations so we can keep track of the last location. + Location location = new MyTracksLocation(""); try { - final ArrayList theData = new ArrayList(); - int points = 0; - // Need two locations so we can keep track of the last location. - Location location = new MyTracksLocation(""); - while (lastLocationRead < track.getStopId()) { - cursor = providerUtils.getLocationsCursor( - selectedTrackId, lastLocationRead, bufferSize, false); + while (lastSeenLocationId < track.getStopId()) { + cursor = getLocationsCursor(lastLocationRead); if (cursor != null) { elevationBuffer.reset(); speedBuffer.reset(); if (cursor.moveToFirst()) { - final int idColumnIdx = - cursor.getColumnIndexOrThrow(TrackPointsColumns._ID); + final int idColumnIdx = cursor.getColumnIndexOrThrow(TrackPointsColumns._ID); while (cursor.moveToNext()) { points++; providerUtils.fillLocation(cursor, location); @@ -632,26 +634,20 @@ public class ChartActivity extends Activity implements double[] point = new double[6]; location = getDataPoint(location, track, point); if (points % chartSamplingFrequency == 0) { - theData.add(point); + result.add(point); } } } } else { - lastLocationRead += bufferSize; + lastLocationRead += BUFFER_SIZE; } } else { - lastLocationRead += bufferSize; + lastLocationRead += BUFFER_SIZE; } cursor.close(); cursor = null; } - runOnUiThread(new Runnable() { - public void run() { - cv.setDataPoints(theData); - } - }); - } catch (RuntimeException e) { - Log.w(MyTracksConstants.TAG, "Caught unexpected exception.", e); + return result; } finally { if (cursor != null) { cursor.close(); diff --git a/MyTracks/src/com/google/android/apps/mytracks/ChartView.java b/MyTracks/src/com/google/android/apps/mytracks/ChartView.java index 948b5439d..753a4a753 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/ChartView.java +++ b/MyTracks/src/com/google/android/apps/mytracks/ChartView.java @@ -216,7 +216,7 @@ public class ChartView extends View { R.color.speed_fill, R.color.speed_border, new ZoomSettings(MAX_INTERVALS, 0, Integer.MIN_VALUE, - new int[] {5, 10, 20, 50}), + new int[] {1, 5, 10, 20, 50}), R.string.speed); series[POWER_SERIES] = new ChartValueSeries(context, @@ -610,7 +610,8 @@ public class ChartView extends View { c.translate(getScrollX(), 0); drawYAxis(c); - final int spacer = 5; + 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()) { @@ -726,9 +727,10 @@ public class ChartView extends View { maxLength += cvs.getMaxLabelLength(); } } - leftBorder = 4 + 8 * maxLength; - effectiveWidth = w - leftBorder - RIGHT_BORDER; float density = getContext().getResources().getDisplayMetrics().density; + // TODO: This should be function of the number of variables displayed. + leftBorder = (int) (density * (4 + 8 * maxLength)); + effectiveWidth = w - leftBorder - RIGHT_BORDER; bottomBorder = (int) (density * BOTTOM_BORDER); topBorder = (int) (density * TOP_BORDER); effectiveHeight = h - topBorder - bottomBorder; @@ -739,8 +741,9 @@ public class ChartView extends View { } private int getY(ChartValueSeries cvs, double y) { + int effectiveSpread = cvs.getInterval() * MAX_INTERVALS; return topBorder + effectiveHeight - - (int) ((y - cvs.getMin()) * effectiveHeight / cvs.getSpread()); + - (int) ((y - cvs.getMin()) * effectiveHeight / effectiveSpread); } private void drawXLabels(Canvas c) {