diff --git a/OsmAnd/res/layout/open_bug.xml b/OsmAnd/res/layout/open_bug.xml new file mode 100644 index 0000000000..c7ad4c1773 --- /dev/null +++ b/OsmAnd/res/layout/open_bug.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/OsmAnd/res/menu/map_menu.xml b/OsmAnd/res/menu/map_menu.xml index 970dd94554..3f67971e87 100644 --- a/OsmAnd/res/menu/map_menu.xml +++ b/OsmAnd/res/menu/map_menu.xml @@ -2,7 +2,7 @@ - + diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 9cae2e27cc..ffcb2e221d 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1,5 +1,8 @@ + Input user name to communicate osm + User name + Mark point Show open street bugs on map Show open street bugs List of favourite points diff --git a/OsmAnd/res/xml/settings_pref.xml b/OsmAnd/res/xml/settings_pref.xml index 547b5a01d0..fa1acb1c6d 100644 --- a/OsmAnd/res/xml/settings_pref.xml +++ b/OsmAnd/res/xml/settings_pref.xml @@ -2,6 +2,7 @@ + diff --git a/OsmAnd/src/com/osmand/OsmandSettings.java b/OsmAnd/src/com/osmand/OsmandSettings.java index 92fb509b16..8ad6479dba 100644 --- a/OsmAnd/src/com/osmand/OsmandSettings.java +++ b/OsmAnd/src/com/osmand/OsmandSettings.java @@ -33,6 +33,18 @@ public class OsmandSettings { return prefs.getBoolean(SHOW_POI_OVER_MAP, false); } + // this value string is synchronized with settings_pref.xml preference name + public static final String USER_NAME = "user_name"; + public static String getUserName(Context ctx){ + SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); + return prefs.getString(USER_NAME, "NoName"); + } + + public static boolean setUserName(Context ctx, String name){ + SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE); + return prefs.edit().putString(USER_NAME, name).commit(); + } + // this value string is synchronized with settings_pref.xml preference name public static final String SHOW_OSM_BUGS = "show_osm_bugs"; diff --git a/OsmAnd/src/com/osmand/activities/MapActivity.java b/OsmAnd/src/com/osmand/activities/MapActivity.java index 0dbd0eae9f..40b78214a4 100644 --- a/OsmAnd/src/com/osmand/activities/MapActivity.java +++ b/OsmAnd/src/com/osmand/activities/MapActivity.java @@ -99,7 +99,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat mapView.addLayer(locationLayer); mapInfoLayer = new MapInfoLayer(this); mapView.addLayer(mapInfoLayer); - osmBugsLayer = new OsmBugsLayer(); + osmBugsLayer = new OsmBugsLayer(this); @@ -160,6 +160,7 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat startActivity(newIntent); } }); + } @@ -225,6 +226,13 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat } public void navigateToPoint(LatLon point){ + if(point != null){ + getPreferences(MODE_WORLD_READABLE).edit(). + putFloat(POINT_NAVIGATE_LAT, (float) mapView.getLatitude()). + putFloat(POINT_NAVIGATE_LON, (float) mapView.getLongitude()).commit(); + } else { + getPreferences(MODE_WORLD_READABLE).edit().remove(POINT_NAVIGATE_LAT).remove(POINT_NAVIGATE_LON).commit(); + } navigationLayer.setPointToNavigate(point); } @@ -357,6 +365,23 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat } } + @Override + public void onSensorChanged(SensorEvent event) { + // using that strange technique because sensor produces a lot of events & hangs the system + locationLayer.setHeading(event.values[0], true); + if(!sensorHandler.hasMessages(1) && locationLayer.isLocationVisible(locationLayer.getLastKnownLocation())){ + Message m = Message.obtain(sensorHandler, new Runnable(){ + @Override + public void run() { + mapView.refreshMap(); + } + }); + m.what = 1; + sensorHandler.sendMessage(m); + } + } + + public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.map_menu, menu); @@ -377,29 +402,42 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat final Intent settings = new Intent(MapActivity.this, SettingsActivity.class); startActivity(settings); return true; - } else if (item.getItemId() == R.id.map_add_to_favourite) { - addFavouritePoint(); + } else if (item.getItemId() == R.id.map_mark_point) { + markPoint(); return true; } else if (item.getItemId() == R.id.map_specify_point) { openChangeLocationDialog(); return true; } else if (item.getItemId() == R.id.map_navigate_to_point) { if(navigationLayer.getPointToNavigate() != null){ - getPreferences(MODE_WORLD_READABLE).edit().remove(POINT_NAVIGATE_LAT).remove(POINT_NAVIGATE_LON).commit(); - item.setTitle(R.string.navigate_to_point); navigateToPoint(null); } else { - getPreferences(MODE_WORLD_READABLE).edit(). - putFloat(POINT_NAVIGATE_LAT, (float) mapView.getLatitude()). - putFloat(POINT_NAVIGATE_LON, (float) mapView.getLongitude()).commit(); - item.setTitle(R.string.stop_navigation); navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude())); } } return super.onOptionsItemSelected(item); } - private void addFavouritePoint(){ + protected void markPoint(){ + Builder builder = new AlertDialog.Builder(this); + builder.setItems(new String[]{"Navigate to point", "Add to favourites", "Open osm bug"}, new DialogInterface.OnClickListener(){ + + @Override + public void onClick(DialogInterface dialog, int which) { + if(which == 0){ + navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude())); + } else if(which == 1){ + addFavouritePoint(); + } else if(which == 2){ + osmBugsLayer.openBug(MapActivity.this, getLayoutInflater(), mapView); + } + } + }); + builder.create().show(); + } + + + protected void addFavouritePoint(){ final FavouritePoint p = new FavouritesActivity.FavouritePoint(); p.setLatitude(mapView.getLatitude()); p.setLongitude(mapView.getLongitude()); @@ -435,21 +473,6 @@ public class MapActivity extends Activity implements LocationListener, IMapLocat public void onAccuracyChanged(Sensor sensor, int accuracy) { } - @Override - public void onSensorChanged(SensorEvent event) { - // using that strange technique because sensor produces a lot of events & hangs the system - locationLayer.setHeading(event.values[0], true); - if(!sensorHandler.hasMessages(1) && locationLayer.isLocationVisible(locationLayer.getLastKnownLocation())){ - Message m = Message.obtain(sensorHandler, new Runnable(){ - @Override - public void run() { - mapView.refreshMap(); - } - }); - m.what = 1; - sensorHandler.sendMessage(m); - } - } - + } \ No newline at end of file diff --git a/OsmAnd/src/com/osmand/activities/SettingsActivity.java b/OsmAnd/src/com/osmand/activities/SettingsActivity.java index f512f2269f..deef9db364 100644 --- a/OsmAnd/src/com/osmand/activities/SettingsActivity.java +++ b/OsmAnd/src/com/osmand/activities/SettingsActivity.java @@ -7,6 +7,7 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.preference.CheckBoxPreference; +import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; @@ -28,6 +29,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference private ListPreference positionOnMap; private CheckBoxPreference useEnglishNames; private CheckBoxPreference showOsmBugs; + private EditTextPreference userName; @Override public void onCreate(Bundle savedInstanceState) { @@ -46,6 +48,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference showOsmBugs.setOnPreferenceChangeListener(this); useEnglishNames =(CheckBoxPreference) screen.findPreference(OsmandSettings.USE_ENGLISH_NAMES); useEnglishNames.setOnPreferenceChangeListener(this); + userName = (EditTextPreference) screen.findPreference(OsmandSettings.USER_NAME); + userName.setOnPreferenceChangeListener(this); positionOnMap =(ListPreference) screen.findPreference(OsmandSettings.POSITION_ON_MAP); positionOnMap.setOnPreferenceChangeListener(this); @@ -68,6 +72,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference positionOnMap.setEntryValues(e); positionOnMap.setEntries(e); positionOnMap.setValueIndex(OsmandSettings.getPositionOnMap(this)); + userName.setText(OsmandSettings.getUserName(this)); List list = TileSourceManager.getKnownSourceTemplates(); @@ -100,6 +105,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference } else if(preference == useEnglishNames){ edit.putBoolean(OsmandSettings.USE_ENGLISH_NAMES, (Boolean) newValue); edit.commit(); + } else if(preference == userName){ + edit.putString(OsmandSettings.USER_NAME, (String) newValue); + edit.commit(); } else if(preference == showViewAngle){ edit.putBoolean(OsmandSettings.SHOW_VIEW_ANGLE, (Boolean) newValue); edit.commit(); diff --git a/OsmAnd/src/com/osmand/views/OsmBugsLayer.java b/OsmAnd/src/com/osmand/views/OsmBugsLayer.java index aa7c6f89ef..92b2b5ebc6 100644 --- a/OsmAnd/src/com/osmand/views/OsmBugsLayer.java +++ b/OsmAnd/src/com/osmand/views/OsmBugsLayer.java @@ -5,13 +5,21 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.content.Context; +import android.content.DialogInterface; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -21,9 +29,14 @@ import android.graphics.RectF; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; import android.widget.Toast; import com.osmand.LogUtil; +import com.osmand.OsmandSettings; +import com.osmand.R; import com.osmand.osm.MapUtils; public class OsmBugsLayer implements OsmandMapLayer { @@ -41,14 +54,19 @@ public class OsmBugsLayer implements OsmandMapLayer { private Paint pointClosedUI; private Paint pointOpenedUI; private Pattern patternToParse = Pattern.compile("putAJAXMarker\\((\\d*), ((\\d|\\.)*), ((\\d|\\.)*), '([^']*)', (\\d)\\);"); + private SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy hh:mm aaa", Locale.US); private double cTopLatitude; private double cBottomLatitude; private double cLeftLongitude; private double cRightLongitude; private int czoom; + private final Activity activity; - + public OsmBugsLayer(Activity activity){ + this.activity = activity; + + } @Override public void initLayer(OsmandMapTileView view) { @@ -168,46 +186,36 @@ public class OsmBugsLayer implements OsmandMapLayer { } } - - - protected List loadingBugs(double topLatitude, double leftLongitude, double bottomLatitude,double rightLongitude){ - List bugs = new ArrayList(); - StringBuilder b = new StringBuilder(); - b.append("http://openstreetbugs.schokokeks.org/api/0.1/getBugs?"); - b.append("b=").append(bottomLatitude); - b.append("&t=").append(topLatitude); - b.append("&l=").append(leftLongitude); - b.append("&r=").append(rightLongitude); - try { - URL url = new URL(b.toString()); - URLConnection connection = url.openConnection(); - BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String st = null; - while((st = reader.readLine()) != null){ - Matcher matcher = patternToParse.matcher(st); - if(matcher.find()){ - OpenStreetBug bug = new OpenStreetBug(); - bug.setId(Long.parseLong(matcher.group(1))); - bug.setLongitude(Double.parseDouble(matcher.group(2))); - bug.setLatitude(Double.parseDouble(matcher.group(4))); - bug.setName(matcher.group(6)); - bug.setOpened(matcher.group(7).equals("0")); - bugs.add(bug); - } - } - } catch (IOException e) { - log.warn("Error loading bugs", e); - } catch (NumberFormatException e) { - log.warn("Error loading bugs", e); - } catch (RuntimeException e) { - log.warn("Error loading bugs", e); - } - - return bugs; - } - @Override public boolean onLongPressEvent(PointF point) { + if (objects != null && !objects.isEmpty()) { + int ex = (int) point.x; + int ey = (int) point.y; + int radius = getRadiusBug(view.getZoom()) * 3 / 2; + try { + for (final OpenStreetBug n : objects) { + int x = view.getRotatedMapXForPoint(n.getLatitude(), n.getLongitude()); + int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude()); + if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) { + Builder builder = new AlertDialog.Builder(view.getContext()); + builder.setItems(new String[]{"Add comment", "Close bug"}, new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface dialog, int which) { + if(which == 0){ + commentBug(view.getContext(), activity.getLayoutInflater(), n); + } else if(which == 1){ + closeBug(view.getContext(), activity.getLayoutInflater(), n); + } + } + }); + builder.create().show(); + return true; + } + } + } catch (IndexOutOfBoundsException e) { + // that's really rare case, but is much efficient than introduce synchronized block + } + } return false; } @@ -235,6 +243,182 @@ public class OsmBugsLayer implements OsmandMapLayer { } + + + public void clearCache() { + objects.clear(); + cTopLatitude = 0; + cBottomLatitude = 0; + cLeftLongitude = 0; + cRightLongitude = 0; + } + + public boolean createNewBug(double latitude, double longitude, String text, String authorName){ + StringBuilder b = new StringBuilder(); + b.append("http://openstreetbugs.schokokeks.org/api/0.1/addPOIexec?"); + b.append("lat=").append(latitude); + b.append("&lon=").append(longitude); + text = text + " [" + authorName +" "+ dateFormat.format(new Date())+ "]"; + b.append("&text=").append(text); + b.append("&name=").append(authorName); + return editingPOI(b.toString(), "creating bug"); + } + + public boolean addingComment(long id, String text, String authorName){ + StringBuilder b = new StringBuilder(); + b.append("http://openstreetbugs.schokokeks.org/api/0.1/editPOIexec?"); + b.append("id=").append(id); + text = text + " [" + authorName +" "+ dateFormat.format(new Date())+ "]"; + b.append("&text=").append(text); + b.append("&name=").append(authorName); + return editingPOI(b.toString(), "adding comment"); + } + + public boolean closingBug(long id){ + StringBuilder b = new StringBuilder(); + b.append("http://openstreetbugs.schokokeks.org/api/0.1/closePOIexec?"); + b.append("id=").append(id); + return editingPOI(b.toString(),"closing bug"); + } + + + private boolean editingPOI(String urlStr, String debugAction){ + urlStr = urlStr.replace(" ", "%20"); + try { + URL url = new URL(urlStr); + URLConnection connection = url.openConnection(); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + while(reader.readLine() != null){ + } + log.debug("Action " + debugAction + " successfull"); + return true; + } catch (IOException e) { + log.error("Error " +debugAction, e); + } catch (RuntimeException e) { + log.error("Error "+debugAction, e); + } + return false; + } + + + protected List loadingBugs(double topLatitude, double leftLongitude, double bottomLatitude,double rightLongitude){ + List bugs = new ArrayList(); + StringBuilder b = new StringBuilder(); + b.append("http://openstreetbugs.schokokeks.org/api/0.1/getBugs?"); + b.append("b=").append(bottomLatitude); + b.append("&t=").append(topLatitude); + b.append("&l=").append(leftLongitude); + b.append("&r=").append(rightLongitude); + try { + URL url = new URL(b.toString()); + URLConnection connection = url.openConnection(); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String st = null; + while((st = reader.readLine()) != null){ + Matcher matcher = patternToParse.matcher(st); + if(matcher.find()){ + OpenStreetBug bug = new OpenStreetBug(); + bug.setId(Long.parseLong(matcher.group(1))); + bug.setLongitude(Double.parseDouble(matcher.group(2))); + bug.setLatitude(Double.parseDouble(matcher.group(4))); + bug.setName(matcher.group(6).replace("
", "\n")); + bug.setOpened(matcher.group(7).equals("0")); + bugs.add(bug); + } + } + } catch (IOException e) { + log.warn("Error loading bugs", e); + } catch (NumberFormatException e) { + log.warn("Error loading bugs", e); + } catch (RuntimeException e) { + log.warn("Error loading bugs", e); + } + + return bugs; + } + + + public void openBug(final Context ctx, LayoutInflater layoutInflater, final OsmandMapTileView mapView){ + Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle("Input text of bug"); + final View view = layoutInflater.inflate(R.layout.open_bug, null); + builder.setView(view); + ((EditText)view.findViewById(R.id.AuthorName)).setText(OsmandSettings.getUserName(ctx)); + builder.setNegativeButton("Cancel", null); + builder.setPositiveButton("Add", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String text = ((EditText)view.findViewById(R.id.BugMessage)).getText().toString(); + String author = ((EditText)view.findViewById(R.id.AuthorName)).getText().toString(); + OsmandSettings.setUserName(ctx, author); + boolean bug = createNewBug(mapView.getLatitude(), mapView.getLongitude(), + text, author); + if (bug) { + Toast.makeText(ctx, "Bug was successfully created", Toast.LENGTH_LONG).show(); + clearCache(); + if (mapView.getLayers().contains(OsmBugsLayer.this)) { + mapView.refreshMap(); + } + } else { + Toast.makeText(ctx, "Exception occured : bug was not created", Toast.LENGTH_LONG).show(); + } + } + }); + builder.show(); + } + + public void commentBug(final Context ctx, LayoutInflater layoutInflater, final OpenStreetBug bug){ + Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle("Adding comment to bug"); + final View view = layoutInflater.inflate(R.layout.open_bug, null); + builder.setView(view); + ((EditText)view.findViewById(R.id.AuthorName)).setText(OsmandSettings.getUserName(ctx)); + builder.setNegativeButton("Cancel", null); + builder.setPositiveButton("Add comment", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String text = ((EditText)view.findViewById(R.id.BugMessage)).getText().toString(); + String author = ((EditText)view.findViewById(R.id.AuthorName)).getText().toString(); + OsmandSettings.setUserName(ctx, author); + boolean added = addingComment(bug.getId(), text, author); + if (added) { + Toast.makeText(ctx, "Comment was successfully added", Toast.LENGTH_LONG).show(); + clearCache(); + if (OsmBugsLayer.this.view.getLayers().contains(OsmBugsLayer.this)) { + OsmBugsLayer.this.view.refreshMap(); + } + } else { + Toast.makeText(ctx, "Exception occured : comment was not added", Toast.LENGTH_LONG).show(); + } + } + }); + builder.show(); + } + + public void closeBug(final Context ctx, LayoutInflater layoutInflater, final OpenStreetBug bug){ + Builder builder = new AlertDialog.Builder(ctx); + builder.setTitle("Closing bug"); + builder.setNegativeButton("Cancel", null); + builder.setPositiveButton("Close bug", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + boolean closed = closingBug(bug.getId()); + if (closed) { + Toast.makeText(ctx, "Bug was successfully added", Toast.LENGTH_LONG).show(); + clearCache(); + if (OsmBugsLayer.this.view.getLayers().contains(OsmBugsLayer.this)) { + OsmBugsLayer.this.view.refreshMap(); + } + } else { + Toast.makeText(ctx, "Exception occured : bug was not closed", Toast.LENGTH_LONG).show(); + } + } + }); + builder.show(); + } + + + public static class OpenStreetBug { private double latitude; private double longitude;