forked from upstream-mirrors/OpenTracks
Use the same list item layout for TrackList, MarkerList, and SearchList.
Use the same contextual menu for TrackList, MarkerList, and SearchList.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.util.SystemUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* A DialogFragment to show information about My Tracks.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class AboutDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String ABOUT_DIALOG_TAG = "aboutDialog";
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
View view = getActivity().getLayoutInflater().inflate(R.layout.about, null);
|
||||
TextView aboutVersion = (TextView) view.findViewById(R.id.about_version);
|
||||
aboutVersion.setText(SystemUtils.getMyTracksVersion(getActivity()));
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(R.string.about_license, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
EulaDialogFragment.newInstance(true).show(
|
||||
getActivity().getSupportFragmentManager(), EulaDialogFragment.EULA_DIALOG_TAG);
|
||||
}
|
||||
})
|
||||
.setPositiveButton(R.string.generic_ok, null)
|
||||
.setTitle(R.string.help_about)
|
||||
.setView(view)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.ChartView;
|
||||
import com.google.android.apps.mytracks.ChartView.Mode;
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.MyTracksApplication;
|
||||
import com.google.android.apps.mytracks.content.MyTracksLocation;
|
||||
import com.google.android.apps.mytracks.content.Sensor;
|
||||
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
||||
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
||||
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
|
||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ZoomControls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* A fragment to display track chart to the user.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class ChartFragment extends Fragment implements TrackDataListener {
|
||||
|
||||
// Android reports 128 when the speed is invalid
|
||||
private static final int INVALID_SPEED = 128;
|
||||
private final DoubleBuffer elevationBuffer = new DoubleBuffer(
|
||||
Constants.ELEVATION_SMOOTHING_FACTOR);
|
||||
private final DoubleBuffer speedBuffer = new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR);
|
||||
private final ArrayList<double[]> pendingPoints = new ArrayList<double[]>();
|
||||
|
||||
private TrackDataHub trackDataHub;
|
||||
|
||||
// Stats gathered from the received data
|
||||
private double totalDistance = 0.0;
|
||||
private long startTime = -1L;
|
||||
private Location lastLocation = null;
|
||||
private double trackMaxSpeed = 0.0;
|
||||
|
||||
// Modes of operation
|
||||
private boolean metricUnits = true;
|
||||
private boolean reportSpeed = true;
|
||||
|
||||
// UI elements
|
||||
private ChartView chartView;
|
||||
private LinearLayout busyPane;
|
||||
private ZoomControls zoomControls;
|
||||
|
||||
/**
|
||||
* A runnable that will remove the spinner (if any), enable/disable zoom
|
||||
* controls and orange pointer as appropriate and redraw.
|
||||
*/
|
||||
private final Runnable updateChart = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (trackDataHub == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
busyPane.setVisibility(View.GONE);
|
||||
zoomControls.setIsZoomInEnabled(chartView.canZoomIn());
|
||||
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
|
||||
chartView.setShowPointer(isRecording());
|
||||
chartView.invalidate();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
/*
|
||||
* Create a chartView here to store data thus won't need to reload all the
|
||||
* data on every onStart or onResume.
|
||||
*/
|
||||
chartView = new ChartView(getActivity());
|
||||
};
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.mytracks_charts, container, false);
|
||||
busyPane = (LinearLayout) view.findViewById(R.id.elevation_busypane);
|
||||
zoomControls = (ZoomControls) view.findViewById(R.id.elevation_zoom);
|
||||
zoomControls.setOnZoomInClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
zoomIn();
|
||||
}
|
||||
});
|
||||
zoomControls.setOnZoomOutClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
zoomOut();
|
||||
}
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
ViewGroup layout = (ViewGroup) getActivity().findViewById(R.id.elevation_chart);
|
||||
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT);
|
||||
layout.addView(chartView, layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
resumeTrackDataHub();
|
||||
getActivity().runOnUiThread(updateChart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
pauseTrackDataHub();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
ViewGroup layout = (ViewGroup) getActivity().findViewById(R.id.elevation_chart);
|
||||
layout.removeView(chartView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the chart view mode.
|
||||
*
|
||||
* @param mode the chart view mode
|
||||
*/
|
||||
public void setMode(Mode mode) {
|
||||
if (chartView.getMode() != mode) {
|
||||
chartView.setMode(mode);
|
||||
reloadTrackDataHub();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chart view mode.
|
||||
*/
|
||||
public Mode getMode() {
|
||||
return chartView.getMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the chart value series.
|
||||
*
|
||||
* @param index the index of the series
|
||||
* @param enabled true to enable, false to disable
|
||||
*/
|
||||
public void setChartValueSeriesEnabled(int index, boolean enabled) {
|
||||
chartView.setChartValueSeriesEnabled(index, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the chart value series is enabled.
|
||||
*
|
||||
* @param index the index of the series
|
||||
*/
|
||||
public boolean isChartValueSeriesEnabled(int index) {
|
||||
return chartView.isChartValueSeriesEnabled(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to report speed instead of pace.
|
||||
*/
|
||||
public boolean isReportSpeed() {
|
||||
return reportSpeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the chart.
|
||||
*/
|
||||
public void update() {
|
||||
chartView.postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderStateChange(ProviderState state) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentLocationChanged(Location loc) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentHeadingChanged(double heading) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedTrackChanged(Track track, boolean isRecording) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
busyPane.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackUpdated(Track track) {
|
||||
if (track == null || track.getStatistics() == null) {
|
||||
trackMaxSpeed = 0.0;
|
||||
return;
|
||||
}
|
||||
trackMaxSpeed = track.getStatistics().getMaxSpeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTrackPoints() {
|
||||
totalDistance = 0.0;
|
||||
startTime = -1L;
|
||||
lastLocation = null;
|
||||
|
||||
elevationBuffer.reset();
|
||||
speedBuffer.reset();
|
||||
pendingPoints.clear();
|
||||
|
||||
chartView.reset();
|
||||
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chartView.resetScroll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPoint(Location location) {
|
||||
if (LocationUtils.isValidLocation(location)) {
|
||||
double[] data = new double[6];
|
||||
fillDataPoint(location, data);
|
||||
pendingPoints.add(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSampledOutTrackPoint(Location location) {
|
||||
if (LocationUtils.isValidLocation(location)) {
|
||||
// Still account for the point in the smoothing buffers.
|
||||
fillDataPoint(location, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSegmentSplit() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPointsDone() {
|
||||
chartView.addDataPoints(pendingPoints);
|
||||
pendingPoints.clear();
|
||||
getActivity().runOnUiThread(updateChart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearWaypoints() {
|
||||
chartView.clearWaypoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypoint(Waypoint waypoint) {
|
||||
if (waypoint != null && LocationUtils.isValidLocation(waypoint.getLocation())) {
|
||||
chartView.addWaypoint(waypoint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypointsDone() {
|
||||
getActivity().runOnUiThread(updateChart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUnitsChanged(boolean metric) {
|
||||
if (metricUnits == metric) {
|
||||
return false;
|
||||
}
|
||||
metricUnits = metric;
|
||||
chartView.setMetricUnits(metricUnits);
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chartView.requestLayout();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onReportSpeedChanged(boolean speed) {
|
||||
if (reportSpeed == speed) {
|
||||
return false;
|
||||
}
|
||||
reportSpeed = speed;
|
||||
chartView.setReportSpeed(speed, getActivity());
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chartView.requestLayout();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes the trackDataHub. Needs to be synchronized because trackDataHub can be
|
||||
* accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void resumeTrackDataHub() {
|
||||
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
||||
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||
ListenerDataType.TRACK_UPDATES,
|
||||
ListenerDataType.WAYPOINT_UPDATES,
|
||||
ListenerDataType.POINT_UPDATES,
|
||||
ListenerDataType.SAMPLED_OUT_POINT_UPDATES,
|
||||
ListenerDataType.DISPLAY_PREFERENCES));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the trackDataHub. Needs to be synchronized because trackDataHub can be
|
||||
* accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void pauseTrackDataHub() {
|
||||
trackDataHub.unregisterTrackDataListener(this);
|
||||
trackDataHub = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if recording. Needs to be synchronized because trackDataHub
|
||||
* can be accessed by multiple threads.
|
||||
*/
|
||||
private synchronized boolean isRecording() {
|
||||
return trackDataHub != null && trackDataHub.isRecordingSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the trackDataHub. Needs to be synchronized because trackDataHub can be
|
||||
* accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void reloadTrackDataHub() {
|
||||
if (trackDataHub != null) {
|
||||
trackDataHub.reloadDataForListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To zoom in.
|
||||
*/
|
||||
private void zoomIn() {
|
||||
chartView.zoomIn();
|
||||
zoomControls.setIsZoomInEnabled(chartView.canZoomIn());
|
||||
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
|
||||
}
|
||||
|
||||
/**
|
||||
* To zoom out.
|
||||
*/
|
||||
private void zoomOut() {
|
||||
chartView.zoomOut();
|
||||
zoomControls.setIsZoomInEnabled(chartView.canZoomIn());
|
||||
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a location, fill in a data point, an array of double[6]. <br>
|
||||
* data[0] = time/distance <br>
|
||||
* data[1] = elevation <br>
|
||||
* data[2] = speed <br>
|
||||
* data[3] = power <br>
|
||||
* data[4] = cadence <br>
|
||||
* data[5] = heart rate <br>
|
||||
*
|
||||
* @param location the location
|
||||
* @param data the data point to fill in, can be null
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void fillDataPoint(Location location, double data[]) {
|
||||
double timeOrDistance = Double.NaN;
|
||||
double elevation = Double.NaN;
|
||||
double speed = Double.NaN;
|
||||
double power = Double.NaN;
|
||||
double cadence = Double.NaN;
|
||||
double heartRate = Double.NaN;
|
||||
|
||||
// TODO: Use TripStatisticsBuilder
|
||||
if (chartView.getMode() == Mode.BY_DISTANCE) {
|
||||
if (lastLocation != null) {
|
||||
double distance = lastLocation.distanceTo(location) * UnitConversions.M_TO_KM;
|
||||
if (metricUnits) {
|
||||
totalDistance += distance;
|
||||
} else {
|
||||
totalDistance += distance * UnitConversions.KM_TO_MI;
|
||||
}
|
||||
}
|
||||
timeOrDistance = totalDistance;
|
||||
} else {
|
||||
if (startTime == -1L) {
|
||||
startTime = location.getTime();
|
||||
}
|
||||
timeOrDistance = location.getTime() - startTime;
|
||||
}
|
||||
|
||||
elevationBuffer.setNext(metricUnits ? location.getAltitude() : location.getAltitude()
|
||||
* UnitConversions.M_TO_FT);
|
||||
elevation = elevationBuffer.getAverage();
|
||||
|
||||
if (lastLocation == null) {
|
||||
if (Math.abs(location.getSpeed() - INVALID_SPEED) > 1) {
|
||||
speedBuffer.setNext(location.getSpeed());
|
||||
}
|
||||
} else if (TripStatisticsBuilder.isValidSpeed(location.getTime(), location.getSpeed(),
|
||||
lastLocation.getTime(), lastLocation.getSpeed(), speedBuffer)
|
||||
&& (location.getSpeed() <= trackMaxSpeed)) {
|
||||
speedBuffer.setNext(location.getSpeed());
|
||||
}
|
||||
speed = speedBuffer.getAverage() * UnitConversions.MS_TO_KMH;
|
||||
if (!metricUnits) {
|
||||
speed *= UnitConversions.KM_TO_MI;
|
||||
}
|
||||
if (!reportSpeed) {
|
||||
speed = speed == 0 ? 0.0 : 60.0 / speed;
|
||||
}
|
||||
|
||||
if (location instanceof MyTracksLocation
|
||||
&& ((MyTracksLocation) location).getSensorDataSet() != null) {
|
||||
SensorDataSet sensorDataSet = ((MyTracksLocation) location).getSensorDataSet();
|
||||
if (sensorDataSet.hasPower() && sensorDataSet.getPower().getState() == Sensor.SensorState.SENDING
|
||||
&& sensorDataSet.getPower().hasValue()) {
|
||||
power = sensorDataSet.getPower().getValue();
|
||||
}
|
||||
if (sensorDataSet.hasCadence()
|
||||
&& sensorDataSet.getCadence().getState() == Sensor.SensorState.SENDING
|
||||
&& sensorDataSet.getCadence().hasValue()) {
|
||||
cadence = sensorDataSet.getCadence().getValue();
|
||||
}
|
||||
if (sensorDataSet.hasHeartRate()
|
||||
&& sensorDataSet.getHeartRate().getState() == Sensor.SensorState.SENDING
|
||||
&& sensorDataSet.getHeartRate().hasValue()) {
|
||||
heartRate = sensorDataSet.getHeartRate().getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (data != null) {
|
||||
data[0] = timeOrDistance;
|
||||
data[1] = elevation;
|
||||
data[2] = speed;
|
||||
data[3] = power;
|
||||
data[4] = cadence;
|
||||
data[5] = heartRate;
|
||||
}
|
||||
lastLocation = location;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ChartView getChartView() {
|
||||
return chartView;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setChartView(ChartView view) {
|
||||
chartView = view;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setTrackMaxSpeed(double value) {
|
||||
trackMaxSpeed = value;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setMetricUnits(boolean value) {
|
||||
metricUnits = value;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setReportSpeed(boolean value) {
|
||||
reportSpeed = value;
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.CHART_TAB_TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.ChartView;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
/**
|
||||
* A DialogFragment to show chart settings.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class ChartSettingsDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String CHART_SETTINGS_DIALOG_TAG = "chartSettingsDialog";
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final ChartFragment chartFragment = (ChartFragment) getActivity()
|
||||
.getSupportFragmentManager().findFragmentByTag(CHART_TAB_TAG);
|
||||
View view = getActivity().getLayoutInflater().inflate(R.layout.chart_settings, null);
|
||||
final RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.chart_settings_x);
|
||||
radioGroup.check(chartFragment.getMode() == ChartView.Mode.BY_DISTANCE
|
||||
? R.id.chart_settings_by_distance : R.id.chart_settings_by_time);
|
||||
|
||||
final CheckBox[] checkBoxes = new CheckBox[ChartView.NUM_SERIES];
|
||||
checkBoxes[ChartView.ELEVATION_SERIES] = (CheckBox) view.findViewById(
|
||||
R.id.chart_settings_elevation);
|
||||
checkBoxes[ChartView.SPEED_SERIES] = (CheckBox) view.findViewById(R.id.chart_settings_speed);
|
||||
checkBoxes[ChartView.POWER_SERIES] = (CheckBox) view.findViewById(R.id.chart_settings_power);
|
||||
checkBoxes[ChartView.CADENCE_SERIES] = (CheckBox) view.findViewById(
|
||||
R.id.chart_settings_cadence);
|
||||
checkBoxes[ChartView.HEART_RATE_SERIES] = (CheckBox) view.findViewById(
|
||||
R.id.chart_settings_heart_rate);
|
||||
|
||||
// set checkboxes values
|
||||
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
|
||||
checkBoxes[i].setChecked(chartFragment.isChartValueSeriesEnabled(i));
|
||||
}
|
||||
checkBoxes[ChartView.SPEED_SERIES].setText(chartFragment.isReportSpeed()
|
||||
? R.string.stat_speed : R.string.stat_pace);
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(R.string.generic_cancel, null)
|
||||
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
chartFragment.setMode(
|
||||
radioGroup.getCheckedRadioButtonId() == R.id.chart_settings_by_distance
|
||||
? ChartView.Mode.BY_DISTANCE : ChartView.Mode.BY_TIME);
|
||||
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
|
||||
chartFragment.setChartValueSeriesEnabled(i, checkBoxes[i].isChecked());
|
||||
}
|
||||
chartFragment.update();
|
||||
}
|
||||
})
|
||||
.setTitle(R.string.menu_chart_settings)
|
||||
.setView(view)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
import com.google.android.apps.mytracks.util.CheckUnitsUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
/**
|
||||
* A DialogFragment to check preferred units.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class CheckUnitsDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String CHECK_UNITS_DIALOG_TAG = "checkUnitsDialog";
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(true)
|
||||
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
CheckUnitsUtils.setCheckUnitsValue(getActivity());
|
||||
}
|
||||
})
|
||||
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
CheckUnitsUtils.setCheckUnitsValue(getActivity());
|
||||
|
||||
int position = ((AlertDialog) dialog).getListView().getSelectedItemPosition();
|
||||
SharedPreferences sharedPreferences = getActivity()
|
||||
.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(sharedPreferences.edit()
|
||||
.putBoolean(getString(R.string.metric_units_key), position == 0));
|
||||
}
|
||||
})
|
||||
.setSingleChoiceItems(new CharSequence[] { getString(R.string.preferred_units_metric),
|
||||
getString(R.string.preferred_units_imperial) }, 0, null)
|
||||
.setTitle(R.string.preferred_units_title)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
/**
|
||||
* A DialogFragment to delete all tracks.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class DeleteAllTrackDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String DELETE_ALL_TRACK_DIALOG_TAG = "deleteAllTrackDialog";
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return DialogUtils.createConfirmationDialog(getActivity(),
|
||||
R.string.track_list_delete_all_confirm_message, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
MyTracksProviderUtils.Factory.get(getActivity()).deleteAllTracks();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.MarkerListActivity;
|
||||
import com.google.android.apps.mytracks.content.DescriptionGeneratorImpl;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
/**
|
||||
* A DialogFragment to delete one marker.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class DeleteOneMarkerDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String DELETE_ONE_MARKER_DIALOG_TAG = "deleteOneMarkerDialog";
|
||||
private static final String KEY_MARKER_ID = "markerId";
|
||||
|
||||
public static DeleteOneMarkerDialogFragment newInstance(long markerId) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(KEY_MARKER_ID, markerId);
|
||||
|
||||
DeleteOneMarkerDialogFragment deleteOneMarkerDialogFragment = new DeleteOneMarkerDialogFragment();
|
||||
deleteOneMarkerDialogFragment.setArguments(bundle);
|
||||
return deleteOneMarkerDialogFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return DialogUtils.createConfirmationDialog(getActivity(),
|
||||
R.string.marker_delete_one_marker_confirm_message, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
MyTracksProviderUtils.Factory.get(getActivity()).deleteWaypoint(
|
||||
getArguments().getLong(KEY_MARKER_ID), new DescriptionGeneratorImpl(getActivity()));
|
||||
startActivity(new Intent(getActivity(), MarkerListActivity.class).addFlags(
|
||||
Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.util.DialogUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
/**
|
||||
* A DialogFragment to delete one track.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class DeleteOneTrackDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String DELETE_ONE_TRACK_DIALOG_TAG = "deleteOneTrackDialog";
|
||||
private static final String KEY_TRACK_ID = "trackId";
|
||||
|
||||
public static DeleteOneTrackDialogFragment newInstance(long trackId) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(KEY_TRACK_ID, trackId);
|
||||
|
||||
DeleteOneTrackDialogFragment deleteOneTrackDialogFragment = new DeleteOneTrackDialogFragment();
|
||||
deleteOneTrackDialogFragment.setArguments(bundle);
|
||||
return deleteOneTrackDialogFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return DialogUtils.createConfirmationDialog(getActivity(),
|
||||
R.string.track_detail_delete_confirm_message, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
MyTracksProviderUtils.Factory.get(getActivity())
|
||||
.deleteTrack(getArguments().getLong(KEY_TRACK_ID));
|
||||
startActivity(new Intent(getActivity(), TrackListActivity.class).addFlags(
|
||||
Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.util.EulaUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
/**
|
||||
* A DialogFragment to show EULA.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class EulaDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String EULA_DIALOG_TAG = "eulaDialog";
|
||||
private static final String KEY_HAS_ACCEPTED = "hasAccepted";
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link EulaDialogFragment}.
|
||||
*
|
||||
* @param hasAccepted true if the user has accepted the eula.
|
||||
*/
|
||||
public static EulaDialogFragment newInstance(boolean hasAccepted) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(KEY_HAS_ACCEPTED, hasAccepted);
|
||||
|
||||
EulaDialogFragment eulaDialogFragment = new EulaDialogFragment();
|
||||
eulaDialogFragment.setArguments(bundle);
|
||||
return eulaDialogFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
boolean hasAccepted = getArguments().getBoolean(KEY_HAS_ACCEPTED);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(true)
|
||||
.setMessage(EulaUtils.getEulaMessage(getActivity()))
|
||||
.setTitle(R.string.eula_title);
|
||||
|
||||
if (hasAccepted) {
|
||||
builder.setPositiveButton(R.string.generic_ok, null);
|
||||
} else {
|
||||
builder.setNegativeButton(R.string.eula_decline, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
getActivity().finish();
|
||||
}
|
||||
})
|
||||
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
getActivity().finish();
|
||||
}
|
||||
})
|
||||
.setPositiveButton(R.string.eula_accept, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
EulaUtils.setEulaValue(getActivity());
|
||||
new WelcomeDialogFragment().show(
|
||||
getActivity().getSupportFragmentManager(), WelcomeDialogFragment.WELCOME_DIALOG_TAG);
|
||||
}
|
||||
});
|
||||
}
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.io.file.SaveActivity;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
/**
|
||||
* A DialogFragment to install Google Earth.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class InstallEarthDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String INSTALL_EARTH_DIALOG_TAG = "installEarthDialog";
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(true)
|
||||
.setMessage(R.string.track_detail_install_earth_message)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
startActivity(new Intent().setData(Uri.parse(SaveActivity.GOOGLE_EARTH_MARKET_URL)));
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* Copyright 2008 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.MapOverlay;
|
||||
import com.google.android.apps.mytracks.MyTracksApplication;
|
||||
import com.google.android.apps.mytracks.TrackDetailActivity;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
||||
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.GeoRect;
|
||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
import com.google.android.maps.MapController;
|
||||
import com.google.android.maps.MapView;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* A fragment to display map to the user.
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class MapFragment extends Fragment
|
||||
implements View.OnTouchListener, View.OnClickListener, TrackDataListener {
|
||||
|
||||
private static final String KEY_CURRENT_LOCATION = "currentLocation";
|
||||
private static final String KEY_KEEP_MY_LOCATION_VISIBLE = "keepMyLocationVisible";
|
||||
|
||||
private TrackDataHub trackDataHub;
|
||||
|
||||
// True to keep my location visible.
|
||||
private boolean keepMyLocationVisible;
|
||||
|
||||
// True to zoom to my location. Only apply when keepMyLocationVisible is true.
|
||||
private boolean zoomToMyLocation;
|
||||
|
||||
// The track id of the marker to show.
|
||||
private long markerTrackId;
|
||||
|
||||
// The marker id to show
|
||||
private long markerId;
|
||||
|
||||
// The current selected track id. Set in onSelectedTrackChanged.
|
||||
private long currentSelectedTrackId;
|
||||
|
||||
// The current location. Set in onCurrentLocationChanged.
|
||||
private Location currentLocation;
|
||||
|
||||
// UI elements
|
||||
private View mapViewContainer;
|
||||
private MapOverlay mapOverlay;
|
||||
private RelativeLayout screen;
|
||||
private MapView mapView;
|
||||
private LinearLayout messagePane;
|
||||
private TextView messageText;
|
||||
private LinearLayout busyPane;
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
mapViewContainer = ((TrackDetailActivity) getActivity()).getMapViewContainer();
|
||||
|
||||
mapOverlay = new MapOverlay(getActivity());
|
||||
|
||||
screen = (RelativeLayout) mapViewContainer.findViewById(R.id.screen);
|
||||
mapView = (MapView) mapViewContainer.findViewById(R.id.map);
|
||||
mapView.requestFocus();
|
||||
mapView.setOnTouchListener(this);
|
||||
mapView.setBuiltInZoomControls(true);
|
||||
mapView.getOverlays().add(mapOverlay);
|
||||
messagePane = (LinearLayout) mapViewContainer.findViewById(R.id.messagepane);
|
||||
messageText = (TextView) mapViewContainer.findViewById(R.id.messagetext);
|
||||
busyPane = (LinearLayout) mapViewContainer.findViewById(R.id.busypane);
|
||||
|
||||
return mapViewContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
keepMyLocationVisible = savedInstanceState.getBoolean(KEY_KEEP_MY_LOCATION_VISIBLE, false);
|
||||
currentLocation = (Location) savedInstanceState.getParcelable(KEY_CURRENT_LOCATION);
|
||||
if (currentLocation != null) {
|
||||
updateCurrentLocation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
resumeTrackDataHub();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(KEY_KEEP_MY_LOCATION_VISIBLE, keepMyLocationVisible);
|
||||
if (currentLocation != null) {
|
||||
outState.putParcelable(KEY_CURRENT_LOCATION, currentLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
pauseTrackDataHub();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
ViewGroup parentViewGroup = (ViewGroup) mapViewContainer.getParent();
|
||||
if (parentViewGroup != null) {
|
||||
parentViewGroup.removeView(mapViewContainer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows my location.
|
||||
*/
|
||||
public void showMyLocation() {
|
||||
updateTrackDataHub();
|
||||
keepMyLocationVisible = true;
|
||||
zoomToMyLocation = true;
|
||||
if (currentLocation != null) {
|
||||
updateCurrentLocation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the marker.
|
||||
*
|
||||
* @param id the marker id
|
||||
*/
|
||||
private void showMarker(long id) {
|
||||
MyTracksProviderUtils MyTracksProviderUtils = Factory.get(getActivity());
|
||||
Waypoint waypoint = MyTracksProviderUtils.getWaypoint(id);
|
||||
if (waypoint != null && waypoint.getLocation() != null) {
|
||||
keepMyLocationVisible = false;
|
||||
GeoPoint center = new GeoPoint((int) (waypoint.getLocation().getLatitude() * 1E6),
|
||||
(int) (waypoint.getLocation().getLongitude() * 1E6));
|
||||
mapView.getController().setCenter(center);
|
||||
mapView.getController().setZoom(mapView.getMaxZoomLevel());
|
||||
mapView.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the marker.
|
||||
*
|
||||
* @param trackId the track id
|
||||
* @param id the marker id
|
||||
*/
|
||||
public void showMarker(long trackId, long id) {
|
||||
/*
|
||||
* Synchronize to prevent race condition in changing markerTrackId and
|
||||
* markerId variables.
|
||||
*/
|
||||
synchronized (this) {
|
||||
if (trackId == currentSelectedTrackId) {
|
||||
showMarker(id);
|
||||
markerTrackId = -1L;
|
||||
markerId = -1L;
|
||||
return;
|
||||
}
|
||||
markerTrackId = trackId;
|
||||
markerId = id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if in satellite mode.
|
||||
*/
|
||||
public boolean isSatelliteView() {
|
||||
return mapView.isSatellite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the satellite mode
|
||||
*
|
||||
* @param enabled true for satellite mode, false for map mode
|
||||
*/
|
||||
public void setSatelliteView(boolean enabled) {
|
||||
mapView.setSatellite(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent event) {
|
||||
if (keepMyLocationVisible && event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if (!isVisible(currentLocation)) {
|
||||
/*
|
||||
* Only set to false when no longer visible. Thus can keep showing the
|
||||
* current location with the next location update.
|
||||
*/
|
||||
keepMyLocationVisible = false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == messagePane) {
|
||||
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderStateChange(ProviderState state) {
|
||||
final int messageId;
|
||||
final boolean isGpsDisabled;
|
||||
switch (state) {
|
||||
case DISABLED:
|
||||
messageId = R.string.gps_need_to_enable;
|
||||
isGpsDisabled = true;
|
||||
break;
|
||||
case NO_FIX:
|
||||
case BAD_FIX:
|
||||
messageId = R.string.gps_wait_for_fix;
|
||||
isGpsDisabled = false;
|
||||
break;
|
||||
case GOOD_FIX:
|
||||
messageId = -1;
|
||||
isGpsDisabled = false;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected state: " + state);
|
||||
}
|
||||
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (messageId != -1) {
|
||||
messageText.setText(messageId);
|
||||
messagePane.setVisibility(View.VISIBLE);
|
||||
|
||||
if (isGpsDisabled) {
|
||||
Toast.makeText(getActivity(), R.string.gps_not_found, Toast.LENGTH_LONG).show();
|
||||
|
||||
// Click to show the location source settings
|
||||
messagePane.setOnClickListener(MapFragment.this);
|
||||
} else {
|
||||
messagePane.setOnClickListener(null);
|
||||
}
|
||||
} else {
|
||||
messagePane.setVisibility(View.GONE);
|
||||
}
|
||||
screen.requestLayout();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentLocationChanged(Location location) {
|
||||
currentLocation = location;
|
||||
updateCurrentLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentHeadingChanged(double heading) {
|
||||
if (mapOverlay.setHeading((float) heading)) {
|
||||
mapView.postInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedTrackChanged(final Track track, final boolean isRecording) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean hasTrack = track != null;
|
||||
mapOverlay.setTrackDrawingEnabled(hasTrack);
|
||||
|
||||
if (hasTrack) {
|
||||
busyPane.setVisibility(View.VISIBLE);
|
||||
|
||||
synchronized (this) {
|
||||
/*
|
||||
* Synchronize to prevent race condition in changing markerTrackId
|
||||
* and markerId variables.
|
||||
*/
|
||||
currentSelectedTrackId = track.getId();
|
||||
updateMap(track);
|
||||
}
|
||||
mapOverlay.setShowEndMarker(!isRecording);
|
||||
busyPane.setVisibility(View.GONE);
|
||||
}
|
||||
mapView.invalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackUpdated(Track track) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTrackPoints() {
|
||||
mapOverlay.clearPoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPoint(Location location) {
|
||||
if (LocationUtils.isValidLocation(location)) {
|
||||
mapOverlay.addLocation(location);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSampledOutTrackPoint(Location loc) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSegmentSplit() {
|
||||
mapOverlay.addSegmentSplit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPointsDone() {
|
||||
mapView.postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearWaypoints() {
|
||||
mapOverlay.clearWaypoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypoint(Waypoint waypoint) {
|
||||
if (waypoint != null && LocationUtils.isValidLocation(waypoint.getLocation())) {
|
||||
// TODO: Optimize locking inside addWaypoint
|
||||
mapOverlay.addWaypoint(waypoint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypointsDone() {
|
||||
mapView.postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUnitsChanged(boolean metric) {
|
||||
// We don't care.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onReportSpeedChanged(boolean reportSpeed) {
|
||||
// We don't care.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes the trackDataHub. Needs to be synchronized because trackDataHub can be
|
||||
* accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void resumeTrackDataHub() {
|
||||
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
||||
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||
ListenerDataType.WAYPOINT_UPDATES,
|
||||
ListenerDataType.POINT_UPDATES,
|
||||
ListenerDataType.LOCATION_UPDATES,
|
||||
ListenerDataType.COMPASS_UPDATES));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the trackDataHub. Needs to be synchronized because trackDataHub can be
|
||||
* accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void pauseTrackDataHub() {
|
||||
trackDataHub.unregisterTrackDataListener(this);
|
||||
trackDataHub = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the trackDataHub. Needs to be synchronized because trackDataHub can be
|
||||
* accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void updateTrackDataHub() {
|
||||
if (trackDataHub != null) {
|
||||
trackDataHub.forceUpdateLocation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the map by either zooming to the requested marker or showing the track.
|
||||
*
|
||||
* @param track the track
|
||||
*/
|
||||
private void updateMap(Track track) {
|
||||
if (track.getId() == markerTrackId) {
|
||||
// Show the marker
|
||||
showMarker(markerId);
|
||||
|
||||
markerTrackId = -1L;
|
||||
markerId = -1L;
|
||||
} else {
|
||||
// Show the track
|
||||
showTrack(track);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the location is visible.
|
||||
*
|
||||
* @param location the location
|
||||
*/
|
||||
private boolean isVisible(Location location) {
|
||||
if (location == null || mapView == null) {
|
||||
return false;
|
||||
}
|
||||
GeoPoint mapCenter = mapView.getMapCenter();
|
||||
int latitudeSpan = mapView.getLatitudeSpan();
|
||||
int longitudeSpan = mapView.getLongitudeSpan();
|
||||
|
||||
/*
|
||||
* The bottom of the mapView is obscured by the zoom controls, subtract its
|
||||
* height from the visible area.
|
||||
*/
|
||||
GeoPoint zoomControlBottom = mapView.getProjection().fromPixels(0, mapView.getHeight());
|
||||
GeoPoint zoomControlTop = mapView.getProjection().fromPixels(
|
||||
0, mapView.getHeight() - mapView.getZoomButtonsController().getZoomControls().getHeight());
|
||||
int zoomControlMargin = Math.abs(zoomControlTop.getLatitudeE6()
|
||||
- zoomControlBottom.getLatitudeE6());
|
||||
GeoRect geoRect = new GeoRect(mapCenter, latitudeSpan, longitudeSpan);
|
||||
geoRect.top += zoomControlMargin;
|
||||
|
||||
GeoPoint geoPoint = LocationUtils.getGeoPoint(location);
|
||||
return geoRect.contains(geoPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current location and centers it if necessary.
|
||||
*/
|
||||
private void updateCurrentLocation() {
|
||||
if (mapOverlay == null || mapView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mapOverlay.setMyLocation(currentLocation);
|
||||
mapView.postInvalidate();
|
||||
|
||||
if (currentLocation != null && keepMyLocationVisible && !isVisible(currentLocation)) {
|
||||
GeoPoint geoPoint = LocationUtils.getGeoPoint(currentLocation);
|
||||
MapController mapController = mapView.getController();
|
||||
mapController.animateTo(geoPoint);
|
||||
if (zoomToMyLocation) {
|
||||
// Only zoom in the first time we show the location.
|
||||
zoomToMyLocation = false;
|
||||
if (mapView.getZoomLevel() < mapView.getMaxZoomLevel()) {
|
||||
mapController.setZoom(mapView.getMaxZoomLevel());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the track.
|
||||
*
|
||||
* @param track the track
|
||||
*/
|
||||
private void showTrack(Track track) {
|
||||
if (mapView == null || track == null || track.getNumberOfPoints() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
TripStatistics tripStatistics = track.getStatistics();
|
||||
int bottom = tripStatistics.getBottom();
|
||||
int left = tripStatistics.getLeft();
|
||||
int latitudeSpanE6 = tripStatistics.getTop() - bottom;
|
||||
int longitudeSpanE6 = tripStatistics.getRight() - left;
|
||||
if (latitudeSpanE6 > 0 && latitudeSpanE6 < 180E6 && longitudeSpanE6 > 0
|
||||
&& longitudeSpanE6 < 360E6) {
|
||||
keepMyLocationVisible = false;
|
||||
GeoPoint center = new GeoPoint(bottom + latitudeSpanE6 / 2, left + longitudeSpanE6 / 2);
|
||||
if (LocationUtils.isValidGeoPoint(center)) {
|
||||
mapView.getController().setCenter(center);
|
||||
mapView.getController().zoomToSpan(latitudeSpanE6, longitudeSpanE6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright 2008 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.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.MyTracksApplication;
|
||||
import com.google.android.apps.mytracks.StatsUtilities;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
|
||||
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* A fragment to display track statistics to the user.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class StatsFragment extends Fragment implements TrackDataListener {
|
||||
|
||||
private static final String TAG = StatsFragment.class.getSimpleName();
|
||||
|
||||
private StatsUtilities statsUtilities;
|
||||
private TrackDataHub trackDataHub;
|
||||
private UiUpdateThread uiUpdateThread;
|
||||
|
||||
// The start time of the current track.
|
||||
private long startTime = -1L;
|
||||
|
||||
// A runnable to update the total time field.
|
||||
private final Runnable updateTotalTime = new Runnable() {
|
||||
public void run() {
|
||||
if (isRecording()) {
|
||||
statsUtilities.setTime(R.id.total_time_register, System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A thread that updates the total time field every second.
|
||||
*/
|
||||
private class UiUpdateThread extends Thread {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(TAG, "UI update thread started");
|
||||
while (PreferencesUtils.getRecordingTrackId(getActivity()) != -1L) {
|
||||
getActivity().runOnUiThread(updateTotalTime);
|
||||
try {
|
||||
Thread.sleep(1000L);
|
||||
} catch (InterruptedException e) {
|
||||
Log.d(TAG, "UI update thread caught exception", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "UI update thread finished");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
statsUtilities = new StatsUtilities(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.stats, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
ScrollView scrollView = (ScrollView) getActivity().findViewById(R.id.scrolly);
|
||||
scrollView.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
|
||||
updateLabels();
|
||||
setLocationUnknown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
resumeTrackDataHub();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
pauseTrackDataHub();
|
||||
if (uiUpdateThread != null) {
|
||||
uiUpdateThread.interrupt();
|
||||
uiUpdateThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderStateChange(ProviderState state) {
|
||||
if (state == ProviderState.DISABLED || state == ProviderState.NO_FIX) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setLocationUnknown();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentLocationChanged(final Location location) {
|
||||
if (isRecording()) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (location != null) {
|
||||
setLocation(location);
|
||||
} else {
|
||||
setLocationUnknown();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentHeadingChanged(double heading) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectedTrackChanged(Track track, boolean isRecording) {
|
||||
if (uiUpdateThread == null && isRecording) {
|
||||
uiUpdateThread = new UiUpdateThread();
|
||||
uiUpdateThread.start();
|
||||
} else if (uiUpdateThread != null && !isRecording) {
|
||||
uiUpdateThread.interrupt();
|
||||
uiUpdateThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackUpdated(final Track track) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (track == null || track.getStatistics() == null) {
|
||||
statsUtilities.setAllToUnknown();
|
||||
return;
|
||||
}
|
||||
|
||||
startTime = track.getStatistics().getStartTime();
|
||||
if (!isRecording()) {
|
||||
statsUtilities.setTime(R.id.total_time_register, track.getStatistics().getTotalTime());
|
||||
setLocationUnknown();
|
||||
}
|
||||
statsUtilities.setAllStats(track.getStatistics());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTrackPoints() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPoint(Location loc) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSampledOutTrackPoint(Location loc) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSegmentSplit() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPointsDone() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearWaypoints() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypoint(Waypoint wpt) {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypointsDone() {
|
||||
// We don't care.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUnitsChanged(boolean metric) {
|
||||
if (statsUtilities.isMetricUnits() == metric) {
|
||||
return false;
|
||||
}
|
||||
statsUtilities.setMetricUnits(metric);
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateLabels();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onReportSpeedChanged(boolean speed) {
|
||||
if (statsUtilities.isReportSpeed() == speed) {
|
||||
return false;
|
||||
}
|
||||
statsUtilities.setReportSpeed(speed);
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateLabels();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes the trackDataHub. Needs to be synchronized because trackDataHub can
|
||||
* be accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void resumeTrackDataHub() {
|
||||
trackDataHub = ((MyTracksApplication) getActivity().getApplication()).getTrackDataHub();
|
||||
trackDataHub.registerTrackDataListener(this, EnumSet.of(
|
||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||
ListenerDataType.TRACK_UPDATES,
|
||||
ListenerDataType.LOCATION_UPDATES,
|
||||
ListenerDataType.DISPLAY_PREFERENCES));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the trackDataHub. Needs to be synchronized because trackDataHub can
|
||||
* be accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void pauseTrackDataHub() {
|
||||
trackDataHub.unregisterTrackDataListener(this);
|
||||
trackDataHub = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if recording. Needs to be synchronized because trackDataHub
|
||||
* can be accessed by multiple threads.
|
||||
*/
|
||||
private synchronized boolean isRecording() {
|
||||
return trackDataHub != null && trackDataHub.isRecordingSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the labels.
|
||||
*/
|
||||
private void updateLabels() {
|
||||
statsUtilities.updateUnits();
|
||||
statsUtilities.setSpeedLabel(R.id.speed_label, R.string.stat_speed, R.string.stat_pace);
|
||||
statsUtilities.setSpeedLabels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current location.
|
||||
*
|
||||
* @param location the current location
|
||||
*/
|
||||
private void setLocation(Location location) {
|
||||
statsUtilities.setAltitude(R.id.elevation_register, location.getAltitude());
|
||||
statsUtilities.setLatLong(R.id.latitude_register, location.getLatitude());
|
||||
statsUtilities.setLatLong(R.id.longitude_register, location.getLongitude());
|
||||
statsUtilities.setSpeed(R.id.speed_register, location.getSpeed() * UnitConversions.MS_TO_KMH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current location to unknown.
|
||||
*/
|
||||
private void setLocationUnknown() {
|
||||
statsUtilities.setUnknown(R.id.elevation_register);
|
||||
statsUtilities.setUnknown(R.id.latitude_register);
|
||||
statsUtilities.setUnknown(R.id.longitude_register);
|
||||
statsUtilities.setUnknown(R.id.speed_register);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2012 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.fragments;
|
||||
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* A DialogFrament to show the welcome info.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class WelcomeDialogFragment extends DialogFragment {
|
||||
|
||||
public static final String WELCOME_DIALOG_TAG = "welcomeDialog";
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
View view = getActivity().getLayoutInflater().inflate(R.layout.welcome, null);
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(true)
|
||||
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
checkUnits();
|
||||
}
|
||||
})
|
||||
.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
checkUnits();
|
||||
}
|
||||
})
|
||||
.setTitle(R.string.welcome_title)
|
||||
.setView(view)
|
||||
.create();
|
||||
}
|
||||
|
||||
private void checkUnits() {
|
||||
new CheckUnitsDialogFragment().show(
|
||||
getActivity().getSupportFragmentManager(), CheckUnitsDialogFragment.CHECK_UNITS_DIALOG_TAG);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user