package net.osmand.plus.activities;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.StringTokenizer;
import net.osmand.LogUtil;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.views.OsmandMapTileView;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
public class NavigatePointActivity extends Activity {
Dialog dlg;
MapActivity activity;
int currentFormat = Location.FORMAT_DEGREES;
// dialog constructor
public NavigatePointActivity(MapActivity activity){
this.activity = activity;
dlg = new Dialog(activity);
}
// activity constructor
public NavigatePointActivity() {
}
public void showDialog(){
dlg.setContentView(R.layout.navigate_point);
dlg.setTitle(R.string.map_specify_point);
LatLon loc = activity.getMapLocation();
initUI(loc.getLatitude(), loc.getLongitude());
dlg.show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LatLon loc = OsmandSettings.getLastKnownMapLocation(OsmandSettings.getPrefs(this));
setContentView(R.layout.navigate_point);
setTitle(R.string.map_specify_point);
initUI(loc.getLatitude(), loc.getLongitude());
((Button) findViewById(R.id.Cancel)).setText(getString(R.string.navigate_to));
}
@Override
public View findViewById(int id) {
if(dlg != null){
return dlg.findViewById(id);
}
return super.findViewById(id);
}
public void close(){
if(dlg != null){
dlg.dismiss();
} else {
Intent newIntent = new Intent(this, MapActivity.class);
startActivity(newIntent);
}
}
public void initUI(double latitude, double longitude){
latitude = MapUtils.checkLatitude(latitude);
longitude = MapUtils.checkLongitude(longitude);
((TextView)findViewById(R.id.LatitudeEdit)).setText(convert(latitude, Location.FORMAT_DEGREES));
((TextView)findViewById(R.id.LongitudeEdit)).setText(convert(longitude, Location.FORMAT_DEGREES));
((RadioButton)findViewById(R.id.Format1)).setChecked(true);
((RadioGroup)findViewById(R.id.RadioGroup)).setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
int newFormat = currentFormat;
if(checkedId == R.id.Format1){
newFormat = Location.FORMAT_DEGREES;
} else if(checkedId == R.id.Format2){
newFormat = Location.FORMAT_MINUTES;
} else if(checkedId == R.id.Format3){
newFormat = Location.FORMAT_SECONDS;
}
try {
double lat = convert(((TextView) findViewById(R.id.LatitudeEdit)).getText().toString());
double lon = convert(((TextView) findViewById(R.id.LongitudeEdit)).getText().toString());
((TextView) findViewById(R.id.ValidateTextView)).setVisibility(View.INVISIBLE);
((TextView)findViewById(R.id.LatitudeEdit)).setText(convert(lat, newFormat));
((TextView)findViewById(R.id.LongitudeEdit)).setText(convert(lon, newFormat));
} catch (RuntimeException e) {
((TextView) findViewById(R.id.ValidateTextView)).setVisibility(View.VISIBLE);
((TextView) findViewById(R.id.ValidateTextView)).setText(R.string.invalid_locations);
Log.w(LogUtil.TAG, "Convertion failed", e); //$NON-NLS-1$
}
}
});
((Button) findViewById(R.id.Cancel)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(dlg == null){
showOnMap(true);
} else {
close();
}
}
});
((Button) findViewById(R.id.ShowOnMap)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showOnMap(false);
}
});
}
public void showOnMap(boolean navigate){
try {
double lat = convert(((TextView) findViewById(R.id.LatitudeEdit)).getText().toString());
double lon = convert(((TextView) findViewById(R.id.LongitudeEdit)).getText().toString());
if(navigate){
OsmandSettings.setPointToNavigate(this, lat, lon);
} else {
// in case when it is dialog
if(activity != null) {
OsmandMapTileView v = activity.getMapView();
activity.getMapView().getAnimatedDraggingThread().startMoving(v.getLatitude(), v.getLongitude(),
lat, lon, v.getZoom(), v.getZoom(), v.getSourceTileSize(), v.getRotate(), true);
} else {
OsmandSettings.setMapLocationToShow(this, lat, lon, MessageFormat.format(getString(R.string.search_history_navigate_to), lat, lon));
}
}
close();
} catch (RuntimeException e) {
((TextView) findViewById(R.id.ValidateTextView)).setVisibility(View.VISIBLE);
((TextView) findViewById(R.id.ValidateTextView)).setText(R.string.invalid_locations);
Log.w(LogUtil.TAG, "Convertion failed", e); //$NON-NLS-1$
}
}
////////////////////////////////////////////////////////////////////////////
// THIS code is copied from Location.convert() in order to change locale
// and to fix bug in android implementation : doesn't convert if min = 59.23 or sec = 59.32 or deg=179.3
public static final int FORMAT_DEGREES = 0;
public static final int FORMAT_MINUTES = 1;
public static final int FORMAT_SECONDS = 2;
private static final char DELIM = ':';
/**
* Converts a String in one of the formats described by
* FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS into a
* double.
*
* @throws NullPointerException if coordinate is null
* @throws IllegalArgumentException if the coordinate is not
* in one of the valid formats.
*/
public static double convert(String coordinate) {
coordinate = coordinate.replace(' ', ':');
if (coordinate == null) {
throw new NullPointerException("coordinate");
}
boolean negative = false;
if (coordinate.charAt(0) == '-') {
coordinate = coordinate.substring(1);
negative = true;
}
StringTokenizer st = new StringTokenizer(coordinate, ":");
int tokens = st.countTokens();
if (tokens < 1) {
throw new IllegalArgumentException("coordinate=" + coordinate);
}
try {
String degrees = st.nextToken();
double val;
if (tokens == 1) {
val = Double.parseDouble(degrees);
return negative ? -val : val;
}
String minutes = st.nextToken();
int deg = Integer.parseInt(degrees);
double min;
double sec = 0.0;
if (st.hasMoreTokens()) {
min = Integer.parseInt(minutes);
String seconds = st.nextToken();
sec = Double.parseDouble(seconds);
} else {
min = Double.parseDouble(minutes);
}
boolean isNegative180 = negative && (deg == 180) &&
(min == 0) && (sec == 0);
// deg must be in [0, 179] except for the case of -180 degrees
if ((deg < 0.0) || (deg > 180 && !isNegative180)) {
throw new IllegalArgumentException("coordinate=" + coordinate);
}
if (min < 0 || min > 60d) {
throw new IllegalArgumentException("coordinate=" +
coordinate);
}
if (sec < 0 || sec > 60d) {
throw new IllegalArgumentException("coordinate=" +
coordinate);
}
val = deg*3600.0 + min*60.0 + sec;
val /= 3600.0;
return negative ? -val : val;
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("coordinate=" + coordinate);
}
}
public static String convert(double coordinate, int outputType) {
if (coordinate < -180.0 || coordinate > 180.0 || Double.isNaN(coordinate)) {
throw new IllegalArgumentException("coordinate=" + coordinate); //$NON-NLS-1$
}
if ((outputType != FORMAT_DEGREES) && (outputType != FORMAT_MINUTES) && (outputType != FORMAT_SECONDS)) {
throw new IllegalArgumentException("outputType=" + outputType); //$NON-NLS-1$
}
StringBuilder sb = new StringBuilder();
// Handle negative values
if (coordinate < 0) {
sb.append('-');
coordinate = -coordinate;
}
DecimalFormat df = new DecimalFormat("###.#####", new DecimalFormatSymbols(Locale.US)); //$NON-NLS-1$
if (outputType == FORMAT_MINUTES || outputType == FORMAT_SECONDS) {
int degrees = (int) Math.floor(coordinate);
sb.append(degrees);
sb.append(DELIM);
coordinate -= degrees;
coordinate *= 60.0;
if (outputType == FORMAT_SECONDS) {
int minutes = (int) Math.floor(coordinate);
sb.append(minutes);
sb.append(DELIM);
coordinate -= minutes;
coordinate *= 60.0;
}
}
sb.append(df.format(coordinate));
return sb.toString();
}
}