diff --git a/android/jni/com/mapswithme/maps/SearchActivity.cpp b/android/jni/com/mapswithme/maps/SearchActivity.cpp index 16ad10e5ff..c93badb90d 100644 --- a/android/jni/com/mapswithme/maps/SearchActivity.cpp +++ b/android/jni/com/mapswithme/maps/SearchActivity.cpp @@ -4,6 +4,9 @@ #include "../../../../../map/measurement_utils.hpp" +#include "../../../../../geometry/angles.hpp" +#include "../../../../../geometry/distance_on_sphere.hpp" + #include "../../../../../base/thread.hpp" #include "../core/jni_helper.hpp" @@ -200,7 +203,8 @@ Java_com_mapswithme_maps_SearchActivity_nativeShowItem(JNIEnv * env, jobject thi JNIEXPORT jobject JNICALL Java_com_mapswithme_maps_SearchActivity_nativeGetResult( - JNIEnv * env, jobject thiz, jint position, jint queryID) + JNIEnv * env, jobject thiz, jint position, jint queryID, + jdouble lat, jdouble lon, jint mode, jdouble north) { search::Result const * res = SearchAdapter::Instance().GetResult(position, queryID); if (res == 0) return 0; @@ -212,20 +216,42 @@ Java_com_mapswithme_maps_SearchActivity_nativeGetResult( { jmethodID methodID = env->GetMethodID( klass, "", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;D)V"); ASSERT ( methodID, () ); string distance; - double const d = res->GetDistanceFromCenter(); - if (d >= 0.0) + double azimut = -1.0; + if (mode >= 2) + { + m2::PointD const center = res->GetFeatureCenter(); + + double const d = ms::DistanceOnEarth(lat, lon, + MercatorBounds::YToLat(center.y), + MercatorBounds::XToLon(center.x)); + CHECK ( MeasurementUtils::FormatDistance(d, distance), () ); + if (north >= 0.0 && d < 25000.0) + { + azimut = ang::AngleTo(m2::PointD(MercatorBounds::LonToX(lon), + MercatorBounds::LatToY(lat)), + center) + north; + + double const pi2 = 2.0*math::pi; + if (azimut < 0.0) + azimut += pi2; + else if (azimut > pi2) + azimut -= pi2; + } + } + return env->NewObject(klass, methodID, jni::ToJavaString(env, res->GetString()), jni::ToJavaString(env, res->GetRegionString()), jni::ToJavaString(env, res->GetFeatureType()), + jni::ToJavaString(env, res->GetRegionFlag()), jni::ToJavaString(env, distance.c_str()), - jni::ToJavaString(env, res->GetRegionFlag())); + static_cast(azimut)); } else { diff --git a/android/res/layout/search_item.xml b/android/res/layout/search_item.xml index 972850363d..66f59b5509 100644 --- a/android/res/layout/search_item.xml +++ b/android/res/layout/search_item.xml @@ -6,6 +6,38 @@ android:minHeight="?android:attr/listPreferredItemHeight" android:paddingRight="?android:attr/scrollbarSize"> + + + + + + + + + + - - - - - - - - diff --git a/android/src/com/mapswithme/maps/ArrowImage.java b/android/src/com/mapswithme/maps/ArrowImage.java new file mode 100644 index 0000000000..a417b35fdb --- /dev/null +++ b/android/src/com/mapswithme/maps/ArrowImage.java @@ -0,0 +1,84 @@ +package com.mapswithme.maps; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.Path; +import android.util.AttributeSet; +import android.util.Log; +import android.widget.ImageView; + +public class ArrowImage extends ImageView +{ + static private String TAG = "ArrowImage"; + + private Paint m_paint; + private boolean m_drawArrow; + private float m_angle; + + public ArrowImage(Context context, AttributeSet attrs) + { + super(context, attrs); + + m_paint = new Paint(); + m_paint.setStyle(Style.FILL); + m_paint.setColor(Color.WHITE); + } + + public void setFlag(Resources res, String flag) + { + m_drawArrow = false; + + // The aapt can't process resources with name "do". Hack with renaming. + if (flag.equals("do")) + flag = "do_hack"; + + final int id = res.getIdentifier(flag, "drawable", "com.mapswithme.maps"); + if (id > 0) + setImageDrawable(res.getDrawable(id)); + else + Log.e(TAG, "Failed to get resource id from: " + flag); + } + + public void setAzimut(double azimut) + { + setImageDrawable(null); + + m_drawArrow = true; + m_angle = (float)(azimut / Math.PI * 180.0); + } + + @Override + protected void onDraw(Canvas canvas) + { + super.onDraw(canvas); + + if (m_drawArrow) + { + final float w = getWidth(); + final float h = getHeight(); + + if (m_angle < 0.0) + { + canvas.drawCircle(w/2, h/2, Math.min(w/2, h/2), m_paint); + } + else + { + Path path = new Path(); + + path.moveTo(w/3, h/2); + path.lineTo(0, h/2 - h/3); + path.lineTo(w, h/2); + path.lineTo(0, h/2 + h/3); + path.lineTo(w/3, h/2); + path.close(); + + canvas.rotate(-m_angle, w/2, h/2); + canvas.drawPath(path, m_paint); + } + } + } +} diff --git a/android/src/com/mapswithme/maps/SearchActivity.java b/android/src/com/mapswithme/maps/SearchActivity.java index b178f84211..ce1457fef6 100644 --- a/android/src/com/mapswithme/maps/SearchActivity.java +++ b/android/src/com/mapswithme/maps/SearchActivity.java @@ -2,7 +2,6 @@ package com.mapswithme.maps; import java.util.Locale; -import android.app.Activity; import android.app.ListActivity; import android.content.Context; import android.os.Bundle; @@ -27,13 +26,13 @@ public class SearchActivity extends ListActivity implements LocationService.List private static class SearchAdapter extends BaseAdapter { - private Activity m_context; + private SearchActivity m_context; private LayoutInflater m_inflater; int m_count = 0; int m_resultID = 0; - public SearchAdapter(Activity context) + public SearchAdapter(SearchActivity context) { m_context = context; m_inflater = (LayoutInflater) m_context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -75,6 +74,7 @@ public class SearchActivity extends ListActivity implements LocationService.List public TextView m_country = null; public TextView m_distance = null; public TextView m_amenity = null; + public ArrowImage m_flag = null; void initFromView(View v) { @@ -82,6 +82,7 @@ public class SearchActivity extends ListActivity implements LocationService.List m_country = (TextView) v.findViewById(R.id.country); m_distance = (TextView) v.findViewById(R.id.distance); m_amenity = (TextView) v.findViewById(R.id.amenity); + m_flag = (ArrowImage) v.findViewById(R.id.country_flag); } } @@ -91,8 +92,10 @@ public class SearchActivity extends ListActivity implements LocationService.List public String m_name; public String m_country; public String m_amenity; - public String m_distance; + public String m_flag; + public String m_distance; + public double m_azimut; /// 0 - suggestion result /// 1 - feature result @@ -105,13 +108,15 @@ public class SearchActivity extends ListActivity implements LocationService.List m_type = 0; } public SearchResult(String name, String country, String amenity, - String distance, String flag) + String flag, String distance, double azimut) { m_name = name; m_country = country; m_amenity = amenity; - m_distance = distance; + m_flag = flag; + m_distance = distance; + m_azimut = azimut; m_type = 1; } @@ -141,13 +146,25 @@ public class SearchActivity extends ListActivity implements LocationService.List holder = (ViewHolder) convertView.getTag(); } - final SearchResult r = SearchActivity.nativeGetResult(position, m_resultID); + final SearchResult r = m_context.getResult(position, m_resultID); if (r != null) { holder.m_name.setText(r.m_name); holder.m_country.setText(r.m_country); holder.m_amenity.setText(r.m_amenity); holder.m_distance.setText(r.m_distance); + + if (r.m_type == 1) + { + holder.m_flag.setVisibility(View.VISIBLE); + + if (r.m_flag.length() > 0 && r.m_azimut < 0.0) + holder.m_flag.setFlag(m_context.getResources(), r.m_flag); + else + holder.m_flag.setAzimut(r.m_azimut); + } + else + holder.m_flag.setVisibility(View.INVISIBLE); } return convertView; @@ -161,10 +178,15 @@ public class SearchActivity extends ListActivity implements LocationService.List notifyDataSetChanged(); } + public void updateDistance() + { + notifyDataSetChanged(); + } + /// Show tapped country or get suggestion. public String showCountry(int position) { - final SearchResult r = SearchActivity.nativeGetResult(position, m_resultID); + final SearchResult r = m_context.getResult(position, m_resultID); if (r != null) { if (r.m_type == 1) @@ -253,6 +275,7 @@ public class SearchActivity extends ListActivity implements LocationService.List // Reset current mode flag - start first search. m_mode = 0; + m_north = -1.0; m_location.startUpdate(this); // do the search immediately after resume @@ -293,11 +316,13 @@ public class SearchActivity extends ListActivity implements LocationService.List /// Current position. private double m_lat; private double m_lon; + private double m_north = -1.0; /// It's should be equal to search::SearchParams::ModeT /// Possible values:\n /// m_mode % 2 == 0 - first search query;\n - int m_mode; + /// m_mode >= 2 - position exists;\n + int m_mode = 0; @Override public void onLocationUpdated(long time, double lat, double lon, float accuracy) @@ -314,6 +339,12 @@ public class SearchActivity extends ListActivity implements LocationService.List @Override public void onCompassUpdated(long time, double magneticNorth, double trueNorth, double accuracy) { + final int orientation = getWindowManager().getDefaultDisplay().getOrientation(); + final double correction = LocationService.getAngleCorrection(orientation); + + m_north = LocationService.correctAngle(trueNorth, correction); + + getSA().updateDistance(); } @Override @@ -386,10 +417,16 @@ public class SearchActivity extends ListActivity implements LocationService.List } } + public SearchAdapter.SearchResult getResult(int position, int queryID) + { + return nativeGetResult(position, queryID, m_lat, m_lon, m_mode, m_north); + } + private native void nativeInitSearch(); private native void nativeFinishSearch(); - private static native SearchAdapter.SearchResult nativeGetResult(int position, int queryID); + private static native SearchAdapter.SearchResult + nativeGetResult(int position, int queryID, double lat, double lon, int mode, double north); private native boolean nativeRunSearch(String s, String lang, double lat, double lon, int mode, int queryID);