requests = addressLookupRequestsMap.get(latLon);
+ return requests != null && requests.size() > 0;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void execute(AsyncTask
task, P... requests) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, requests);
+ } else {
+ task.execute(requests);
+ }
+ }
+
+ private boolean geocode(final LatLon latLon) {
+ Location loc = new Location("");
+ loc.setLatitude(latLon.getLatitude());
+ loc.setLongitude(latLon.getLongitude());
+ return app.getLocationProvider()
+ .getGeocodingResult(loc, new ResultMatcher() {
+
+ @Override
+ public boolean publish(GeocodingResult object) {
+ String result = null;
+ if (object != null) {
+ String lang = SampleApplication.LANGUAGE;
+ boolean transliterate = SampleApplication.TRANSLITERATE;
+
+ String geocodingResult = "";
+ double relevantDistance = -1;
+
+ if (object.building != null) {
+ String bldName = object.building.getName(lang, transliterate);
+ if (!Algorithms.isEmpty(object.buildingInterpolation)) {
+ bldName = object.buildingInterpolation;
+ }
+ geocodingResult = object.street.getName(lang, transliterate) + " " + bldName + ", "
+ + object.city.getName(lang, transliterate);
+ } else if (object.street != null) {
+ geocodingResult = object.street.getName(lang, transliterate) + ", " + object.city.getName(lang, transliterate);
+ relevantDistance = object.getDistanceP();
+ } else if (object.city != null) {
+ geocodingResult = object.city.getName(lang, transliterate);
+ } else if (object.point != null) {
+ RouteDataObject rd = object.point.getRoad();
+ String sname = rd.getName(lang, transliterate);
+ if (Algorithms.isEmpty(sname)) {
+ sname = "";
+ }
+ String ref = rd.getRef(true);
+ if (!Algorithms.isEmpty(ref)) {
+ if (!Algorithms.isEmpty(sname)) {
+ sname += ", ";
+ }
+ sname += ref;
+ }
+ geocodingResult = sname;
+ relevantDistance = object.getDistanceP();
+ }
+
+ result = geocodingResult;
+ if (relevantDistance == -1) {
+ relevantDistance = object.getDistance();
+ }
+
+ if (!Algorithms.isEmpty(result) && relevantDistance > 100) {
+ result = app.getString("shared_string_near") + " " + result;
+ }
+ }
+
+ lastFoundAddress = result;
+ searchDone = true;
+
+ return true;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return !hasAnyRequest(latLon);
+ }
+
+ });
+ }
+
+ private class AddressLookupRequestsAsyncTask extends AsyncTask {
+
+ private SampleApplication app;
+
+ public AddressLookupRequestsAsyncTask(SampleApplication app) {
+ super();
+ this.app = app;
+ }
+
+ @Override
+ protected Void doInBackground(AddressLookupRequest... addressLookupRequests) {
+ for (;;) {
+ try {
+ while (!lookupLocations.isEmpty()) {
+ final LatLon latLon;
+ synchronized (GeocodingLookupService.this) {
+ latLon = lookupLocations.poll();
+ currentRequestedLocation = latLon;
+ List requests = addressLookupRequestsMap.get(latLon);
+ if (requests == null || requests.size() == 0) {
+ addressLookupRequestsMap.remove(latLon);
+ continue;
+ }
+ }
+
+ // geocode
+ searchDone = false;
+ while (!geocode(latLon)) {
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ long counter = 0;
+ while (!searchDone) {
+ try {
+ Thread.sleep(50);
+ counter++;
+ // call progress every 500 ms
+ if (counter == 10) {
+ counter = 0;
+ synchronized (GeocodingLookupService.this) {
+ List requests = addressLookupRequestsMap.get(latLon);
+ for (final AddressLookupRequest request : requests) {
+ if (request.uiProgressCallback != null) {
+ app.runInUIThread(new Runnable() {
+ @Override
+ public void run() {
+ request.uiProgressCallback.geocodingInProgress();
+ }
+ });
+ }
+ }
+ }
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ synchronized (GeocodingLookupService.this) {
+ List requests = addressLookupRequestsMap.get(latLon);
+ for (final AddressLookupRequest request : requests) {
+ if (request.uiResultCallback != null) {
+ app.runInUIThread(new Runnable() {
+ @Override
+ public void run() {
+ request.uiResultCallback.geocodingDone(lastFoundAddress);
+ }
+ });
+ }
+ }
+ addressLookupRequestsMap.remove(latLon);
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ synchronized (GeocodingLookupService.this) {
+ currentRequestedLocation = null;
+ if (lookupLocations.isEmpty()) {
+ break;
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/IconsCache.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/IconsCache.java
index f627008a3e..4e07729c18 100644
--- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/IconsCache.java
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/IconsCache.java
@@ -101,7 +101,7 @@ public class IconsCache {
long hash = ((long)resId << 31L) + clrId;
Drawable d = osmandDrawable.get(hash);
if (d == null) {
- d = OsmandResources.getDrawable(resId);
+ d = OsmandResources.getDrawableNonCached(resId);
if (d != null) {
d = DrawableCompat.wrap(d);
d.mutate();
@@ -118,7 +118,7 @@ public class IconsCache {
long hash = ((long)resId << 31L) + color;
Drawable d = osmandDrawable.get(hash);
if(d == null) {
- d = OsmandResources.getDrawable(resId);
+ d = OsmandResources.getDrawableNonCached(resId);
if (d != null) {
d = DrawableCompat.wrap(d);
d.mutate();
@@ -129,6 +129,10 @@ public class IconsCache {
return d;
}
+ public Drawable getPaintedOsmandIcon(int resId, @ColorInt int color){
+ return getPaintedOsmandDrawable(resId, color);
+ }
+
public Drawable getPaintedIcon(String osmandId, @ColorInt int color){
int id = OsmandResources.getDrawableId(osmandId);
if (id != 0) {
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/MainActivity.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/MainActivity.java
index a095be8602..fc59c14cbb 100644
--- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/MainActivity.java
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/MainActivity.java
@@ -8,6 +8,8 @@ import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.graphics.PointF;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
@@ -40,8 +42,12 @@ import net.osmand.core.jni.ResolvedMapStyle;
import net.osmand.core.jni.RoadLocator;
import net.osmand.core.jni.Utilities;
import net.osmand.core.samples.android.sample1.MultiTouchSupport.MultiTouchZoomListener;
+import net.osmand.core.samples.android.sample1.data.PointDescription;
+import net.osmand.core.samples.android.sample1.mapcontextmenu.MapContextMenu;
+import net.osmand.core.samples.android.sample1.mapcontextmenu.MapMultiSelectionMenu;
import net.osmand.core.samples.android.sample1.search.QuickSearchDialogFragment;
import net.osmand.data.LatLon;
+import net.osmand.data.RotatedTileBox;
import net.osmand.util.MapUtils;
import java.io.File;
@@ -77,6 +83,9 @@ public class MainActivity extends AppCompatActivity {
private float elevationAngle;
private MultiTouchSupport multiTouchSupport;
+ private MapContextMenu menu;
+ private MapMultiSelectionMenu multiMenu;
+
private boolean noMapsFound;
// Germany
@@ -224,6 +233,11 @@ public class MainActivity extends AppCompatActivity {
app.getIconsCache().setDisplayDensityFactor(displayDensityFactor);
+ menu = new MapContextMenu();
+ menu.setMainActivity(this);
+
+ multiMenu = new MapMultiSelectionMenu(this);
+
if (!InstallOsmandAppDialog.showIfNeeded(getSupportFragmentManager(), this)
&& externalStoragePermissionGranted) {
checkMapsInstalled();
@@ -280,6 +294,10 @@ public class MainActivity extends AppCompatActivity {
return (SampleApplication) getApplication();
}
+ public AtlasMapRendererView getMapView() {
+ return mapView;
+ }
+
public void showOnMap(LatLon latLon, int zoom) {
if (latLon != null) {
PointI target = Utilities.convertLatLonTo31(
@@ -289,6 +307,38 @@ public class MainActivity extends AppCompatActivity {
}
}
+ public void refreshMap() {
+ //todo
+ }
+
+ public MapContextMenu getContextMenu() {
+ return menu;
+ }
+
+ public boolean showContextMenu(@NonNull LatLon latLon,
+ @Nullable PointDescription pointDescription,
+ @Nullable Object object) {
+ if (multiMenu.isVisible()) {
+ multiMenu.hide();
+ }
+ if (!getBox().containsLatLon(latLon)) {
+ menu.setMapCenter(latLon);
+ menu.setCenterMarker(true);
+ }
+ menu.show(latLon, pointDescription, object);
+ return true;
+ }
+
+ public RotatedTileBox getBox() {
+ RotatedTileBox.RotatedTileBoxBuilder boxBuilder = new RotatedTileBox.RotatedTileBoxBuilder();
+ LatLon screenCenter = getScreenCenter();
+ boxBuilder.setLocation(screenCenter.getLatitude(), screenCenter.getLongitude());
+ boxBuilder.setPixelDimensions(mapView.getWidth(), mapView.getHeight(), 0.5f, 0.5f);
+ boxBuilder.setZoom((int)getZoom());
+ boxBuilder.setRotate(mapView.getRotation());
+ return boxBuilder.build();
+ }
+
public PointI getScreenCenter31() {
PointI point = new PointI();
mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2, mapView.getHeight() / 2), point);
@@ -302,6 +352,10 @@ public class MainActivity extends AppCompatActivity {
return new LatLon(jniLatLon.getLatitude(), jniLatLon.getLongitude());
}
+ public float getZoom() {
+ return zoom;
+ }
+
public void saveMapState() {
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
Editor edit = prefs.edit();
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/OsmandResources.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/OsmandResources.java
index f9882a6291..dc1c2cf9c3 100644
--- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/OsmandResources.java
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/OsmandResources.java
@@ -4,11 +4,23 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.support.v4.graphics.drawable.DrawableCompat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import gnu.trove.map.hash.TLongObjectHashMap;
public class OsmandResources {
+ public static final String BIG_ICON_PREFIX = "mx_";
+
private static Resources osmandResources;
private static String packageName;
+ private static Map stringIds = new HashMap<>();
+ private static Map drawableIds = new HashMap<>();
+ private static TLongObjectHashMap drawable = new TLongObjectHashMap<>();
+ private static TLongObjectHashMap string = new TLongObjectHashMap<>();
public static void init(Context ctx) {
String packageName = "net.osmand";
@@ -43,40 +55,104 @@ public class OsmandResources {
}
public static String getString(String id) {
- if (osmandResources != null) {
- int resolvedId = osmandResources.getIdentifier(id, "string", packageName);
- return osmandResources.getString(resolvedId);
- }
- return null;
+ return getStringInternal(resolveStringId(id));
}
public static String getString(String id, Object... formatArgs) {
- if (osmandResources != null) {
- int resolvedId = osmandResources.getIdentifier(id, "string", packageName);
+ int resolvedId = resolveStringId(id);
+ if (resolvedId != 0) {
return osmandResources.getString(resolvedId, formatArgs);
}
return null;
}
public static Drawable getDrawable(String id) {
- if (osmandResources != null) {
- int resolvedId = osmandResources.getIdentifier(id, "drawable", packageName);
- return osmandResources.getDrawable(resolvedId);
- }
- return null;
+ return getDrawableInternal(resolveDrawableId(id));
+ }
+
+ public static Drawable getBigDrawable(String id) {
+ return getDrawableInternal(resolveDrawableId(BIG_ICON_PREFIX + id));
}
public static Drawable getDrawable(int id) {
- if (osmandResources != null) {
- return osmandResources.getDrawable(id);
+ return getDrawableInternal(id);
+ }
+
+ public static Drawable getDrawableNonCached(int id) {
+ if (osmandResources != null && id != 0) {
+ Drawable d = osmandResources.getDrawable(id);
+ if (d != null) {
+ d = DrawableCompat.wrap(d);
+ d.mutate();
+ }
+ return d;
}
return null;
}
public static int getDrawableId(String id) {
+ return resolveDrawableId(id);
+ }
+
+ public static int getBigDrawableId(String id) {
+ return resolveDrawableId(BIG_ICON_PREFIX + id);
+ }
+
+ private static Drawable getDrawableInternal(int resId) {
+ if (osmandResources != null && resId != 0) {
+ long hash = getResIdHash(resId);
+ Drawable d = drawable.get(hash);
+ if (d == null) {
+ d = osmandResources.getDrawable(resId);
+ if (d != null) {
+ d = DrawableCompat.wrap(d);
+ d.mutate();
+ drawable.put(hash, d);
+ }
+ }
+ return d;
+ }
+ return null;
+ }
+
+ private static String getStringInternal(int resId) {
+ if (osmandResources != null && resId != 0) {
+ long hash = getResIdHash(resId);
+ String s = string.get(hash);
+ if (s == null) {
+ s = osmandResources.getString(resId);
+ string.put(hash, s);
+ }
+ return s;
+ }
+ return null;
+ }
+
+ private static int resolveStringId(String id) {
if (osmandResources != null) {
- return osmandResources.getIdentifier(id, "drawable", packageName);
+ Integer resolvedId = stringIds.get(id);
+ if (resolvedId == null) {
+ resolvedId = osmandResources.getIdentifier(id, "string", packageName);
+ stringIds.put(id, resolvedId);
+ }
+ return resolvedId;
}
return 0;
}
+
+ private static int resolveDrawableId(String id) {
+ if (osmandResources != null) {
+ Integer resolvedId = drawableIds.get(id);
+ if (resolvedId == null) {
+ resolvedId = osmandResources.getIdentifier(id, "drawable", packageName);
+ drawableIds.put(id, resolvedId);
+ }
+ return resolvedId;
+ }
+ return 0;
+ }
+
+ private static long getResIdHash(int resId) {
+ return ((long)resId << 31L);
+ }
}
\ No newline at end of file
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleApplication.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleApplication.java
index 4f09174dda..1178caca31 100644
--- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleApplication.java
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleApplication.java
@@ -41,8 +41,10 @@ public class SampleApplication extends Application {
private SampleLocationProvider locationProvider;
private QuickSearchHelper searchUICore;
+ private GeocodingLookupService geocodingLookupService;
- public static final String LANGUAGE;
+ public static String LANGUAGE;
+ public static boolean TRANSLITERATE = false;
static {
String langCode = Locale.getDefault().getLanguage();
@@ -58,6 +60,7 @@ public class SampleApplication extends Application {
OsmandResources.init(this);
locationProvider = new SampleLocationProvider(this);
searchUICore = new QuickSearchHelper(this);
+ geocodingLookupService = new GeocodingLookupService(this);
uiHandler = new Handler();
poiTypes = MapPoiTypes.getDefaultNoInit();
@@ -76,6 +79,10 @@ public class SampleApplication extends Application {
iconsCache = new IconsCache(assetsCustom, this);
}
+ public GeocodingLookupService getGeocodingLookupService() {
+ return geocodingLookupService;
+ }
+
public int getCoordinatesFormat() {
return coordinatesFormat;
}
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleLocationProvider.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleLocationProvider.java
index 3ec84c2bc5..73205a131f 100644
--- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleLocationProvider.java
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleLocationProvider.java
@@ -23,6 +23,10 @@ import android.support.v7.app.AlertDialog;
import android.util.Log;
import net.osmand.PlatformUtil;
+import net.osmand.ResultMatcher;
+import net.osmand.binary.GeocodingUtilities;
+import net.osmand.binary.GeocodingUtilities.GeocodingResult;
+import net.osmand.data.LatLon;
import net.osmand.util.MapUtils;
import java.util.ArrayList;
@@ -513,16 +517,24 @@ public class SampleLocationProvider implements SensorEventListener {
public boolean getRouteSegment(net.osmand.Location loc, ResultMatcher result) {
return currentPositionHelper.getRouteSegment(loc, result);
}
+ */
public boolean getGeocodingResult(net.osmand.Location loc, ResultMatcher result) {
- return currentPositionHelper.getGeocodingResult(loc, result);
+ return false; //currentPositionHelper.getGeocodingResult(loc, result); todo
}
- */
+
public net.osmand.Location getLastKnownLocation() {
return location;
}
+ public LatLon getLastKnownLocationLatLon() {
+ if (location != null) {
+ return new LatLon(location.getLatitude(), location.getLongitude());
+ } else {
+ return null;
+ }
+ }
public static class GPSInfo {
public int foundSatellites = 0;
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleUtils.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleUtils.java
index c257cac907..3e9e6406b6 100644
--- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleUtils.java
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/SampleUtils.java
@@ -5,10 +5,13 @@ import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-import android.view.WindowManager;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Surface;
+
+import net.osmand.PlatformUtil;
public class SampleUtils {
@@ -69,6 +72,7 @@ public class SampleUtils {
return installed;
}
+ /*
public static int getScreenOrientation(Activity a) {
int screenOrientation = ((WindowManager) a.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
switch (screenOrientation) {
@@ -92,4 +96,75 @@ public class SampleUtils {
}
return screenOrientation;
}
+ */
+
+ public static int getScreenOrientation(Activity activity) {
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ DisplayMetrics dm = new DisplayMetrics();
+ activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
+ int width = dm.widthPixels;
+ int height = dm.heightPixels;
+ int orientation;
+ // if the device's natural orientation is portrait:
+ if ((rotation == Surface.ROTATION_0
+ || rotation == Surface.ROTATION_180) && height > width ||
+ (rotation == Surface.ROTATION_90
+ || rotation == Surface.ROTATION_270) && width > height) {
+ switch(rotation) {
+ case Surface.ROTATION_0:
+ orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+ break;
+ case Surface.ROTATION_90:
+ orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+ break;
+ case Surface.ROTATION_180:
+ orientation =
+ ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+ break;
+ case Surface.ROTATION_270:
+ orientation =
+ ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+ break;
+ default:
+ Log.e(PlatformUtil.TAG, "Unknown screen orientation. Defaulting to " +
+ "portrait.");
+ orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+ break;
+ }
+ }
+ // if the device's natural orientation is landscape or if the device
+ // is square:
+ else {
+ switch(rotation) {
+ case Surface.ROTATION_0:
+ orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+ break;
+ case Surface.ROTATION_90:
+ orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+ break;
+ case Surface.ROTATION_180:
+ orientation =
+ ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+ break;
+ case Surface.ROTATION_270:
+ orientation =
+ ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+ break;
+ default:
+ Log.e(PlatformUtil.TAG, "Unknown screen orientation. Defaulting to " +
+ "landscape.");
+ orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+ break;
+ }
+ }
+
+ return orientation;
+ }
+
+ public static boolean isOrientationPortrait(Activity ctx) {
+ int orientation = getScreenOrientation(ctx);
+ return orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
+ orientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+ }
+
}
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/data/PointDescription.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/data/PointDescription.java
index 0a988c2f67..7067963db8 100644
--- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/data/PointDescription.java
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/data/PointDescription.java
@@ -8,6 +8,7 @@ import com.jwetherell.openmap.common.LatLonPoint;
import com.jwetherell.openmap.common.UTMPoint;
import net.osmand.LocationConvert;
+import net.osmand.core.samples.android.sample1.OsmandResources;
import net.osmand.core.samples.android.sample1.SampleApplication;
import net.osmand.data.LatLon;
import net.osmand.util.Algorithms;
@@ -354,4 +355,27 @@ public class PointDescription {
}
}
+ public int getIconId() {
+ int iconId;
+ if (isAddress()) {
+ iconId = OsmandResources.getDrawableId("ic_type_address");
+ } else if (isFavorite()) {
+ iconId = OsmandResources.getDrawableId("ic_type_favorites");
+ } else if (isLocation()) {
+ iconId = OsmandResources.getDrawableId("ic_type_coordinates");
+ } else if (isPoi()) {
+ iconId = OsmandResources.getDrawableId("ic_type_info");
+ } else if (isWpt()) {
+ iconId = OsmandResources.getDrawableId("ic_type_waypoint");
+ } else if (isAudioNote()) {
+ iconId = OsmandResources.getDrawableId("ic_type_audio");
+ } else if (isVideoNote()) {
+ iconId = OsmandResources.getDrawableId("ic_type_video");
+ }else if (isPhotoNote()) {
+ iconId = OsmandResources.getDrawableId("ic_type_img");
+ } else {
+ iconId = OsmandResources.getDrawableId("ic_type_address");
+ }
+ return iconId;
+ }
}
\ No newline at end of file
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/BaseMenuController.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/BaseMenuController.java
new file mode 100644
index 0000000000..ca59afad33
--- /dev/null
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/BaseMenuController.java
@@ -0,0 +1,96 @@
+package net.osmand.core.samples.android.sample1.mapcontextmenu;
+
+import android.graphics.drawable.Drawable;
+
+import net.osmand.core.samples.android.sample1.IconsCache;
+import net.osmand.core.samples.android.sample1.MainActivity;
+import net.osmand.core.samples.android.sample1.R;
+import net.osmand.core.samples.android.sample1.SampleUtils;
+
+public abstract class BaseMenuController {
+
+ private MainActivity mainActivity;
+ private boolean portraitMode;
+ private boolean nightMode;
+ private int landscapeWidthPx;
+
+ public BaseMenuController(MainActivity mainActivity) {
+ this.mainActivity = mainActivity;
+ init();
+ }
+
+ private void init() {
+ portraitMode = SampleUtils.isOrientationPortrait(mainActivity);
+ landscapeWidthPx = mainActivity.getResources().getDimensionPixelSize(R.dimen.dashboard_land_width);
+ updateNightMode();
+ }
+
+ public MainActivity getMainActivity() {
+ return mainActivity;
+ }
+
+ public void setMainActivity(MainActivity mainActivity) {
+ this.mainActivity = mainActivity;
+ init();
+ }
+
+ public boolean isLight() {
+ return !nightMode;
+ }
+
+ public void updateNightMode() {
+ //nightMode = mainActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls();
+ }
+
+ public boolean isLandscapeLayout() {
+ return !portraitMode;
+ }
+
+ public int getLandscapeWidthPx() {
+ return landscapeWidthPx;
+ }
+
+ public float getHalfScreenMaxHeightKoef() {
+ return .7f;
+ }
+
+ public int getSlideInAnimation() {
+ if (isLandscapeLayout()) {
+ return R.anim.slide_in_left;
+ } else {
+ return R.anim.slide_in_bottom;
+ }
+ }
+
+ public int getSlideOutAnimation() {
+ if (isLandscapeLayout()) {
+ return R.anim.slide_out_left;
+ } else {
+ return R.anim.slide_out_bottom;
+ }
+ }
+
+ protected Drawable getIconOrig(int osmandIconId) {
+ IconsCache iconsCache = getMainActivity().getMyApplication().getIconsCache();
+ return iconsCache.getOsmandIcon(osmandIconId, 0);
+ }
+
+ protected Drawable getIcon(int osmandIconId) {
+ return getIcon(osmandIconId, isLight() ? R.color.icon_color : R.color.icon_color_light);
+ }
+
+ protected Drawable getIcon(int osmandIconId, int colorId) {
+ IconsCache iconsCache = getMainActivity().getMyApplication().getIconsCache();
+ return iconsCache.getOsmandIcon(osmandIconId, colorId);
+ }
+
+ protected Drawable getPaintedIcon(int osmandIconId, int color) {
+ IconsCache iconsCache = getMainActivity().getMyApplication().getIconsCache();
+ return iconsCache.getPaintedOsmandIcon(osmandIconId, color);
+ }
+
+ protected Drawable getIcon(int osmandIconId, int colorLightId, int colorDarkId) {
+ IconsCache iconsCache = getMainActivity().getMyApplication().getIconsCache();
+ return iconsCache.getOsmandIcon(osmandIconId, isLight() ? colorLightId : colorDarkId);
+ }
+}
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/ContextMenuHelper.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/ContextMenuHelper.java
new file mode 100644
index 0000000000..ce1cdb884b
--- /dev/null
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/ContextMenuHelper.java
@@ -0,0 +1,242 @@
+package net.osmand.core.samples.android.sample1.mapcontextmenu;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.PopupMenu;
+import android.support.v7.widget.Toolbar;
+import android.text.util.Linkify;
+import android.view.Gravity;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import net.osmand.AndroidUtils;
+import net.osmand.core.samples.android.sample1.OsmandResources;
+import net.osmand.core.samples.android.sample1.R;
+import net.osmand.core.samples.android.sample1.SampleApplication;
+import net.osmand.core.samples.android.sample1.data.PointDescription;
+import net.osmand.data.Amenity;
+import net.osmand.util.Algorithms;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+public class ContextMenuHelper {
+
+ public static void showDescriptionDialog(Context ctx, SampleApplication app, String text, String title) {
+ showText(ctx, app, text, title);
+ }
+
+ public static void showWikipediaDialog(Context ctx, SampleApplication app, Amenity a) {
+ if (a.getType().isWiki()) {
+ showWiki(ctx, app, a, SampleApplication.LANGUAGE);
+ }
+ }
+
+ private static void showWiki(final Context ctx, final SampleApplication app, final Amenity a, final String lang) {
+ String preferredLang = lang;
+ if (Algorithms.isEmpty(preferredLang)) {
+ preferredLang = SampleApplication.LANGUAGE;
+ }
+ final Dialog dialog = new Dialog(ctx);
+ final String title = Algorithms.isEmpty(lang) ? a.getName() : a.getName(lang);
+ LinearLayout ll = new LinearLayout(ctx);
+ ll.setOrientation(LinearLayout.VERTICAL);
+
+ final Toolbar topBar = new Toolbar(ctx);
+ topBar.setClickable(true);
+ Drawable back = app.getIconsCache().getIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
+ topBar.setNavigationIcon(back);
+ topBar.setNavigationContentDescription(app.getString("access_shared_string_navigate_up"));
+ topBar.setTitle(title);
+ topBar.setBackgroundColor(ContextCompat.getColor(ctx, R.color.osmand_orange));
+ topBar.setTitleTextColor(ContextCompat.getColor(ctx, R.color.color_white));
+
+ String lng = a.getContentSelected("content", preferredLang, "en");
+ if (Algorithms.isEmpty(lng)) {
+ lng = "en";
+ }
+
+ final String langSelected = lng;
+ String content = a.getDescription(langSelected);
+ final Button bottomBar = new Button(ctx);
+ bottomBar.setText(app.getString("read_full_article"));
+ bottomBar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String article = "https://" + langSelected.toLowerCase() + ".wikipedia.org/wiki/" + title.replace(' ', '_');
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setData(Uri.parse(article));
+ ctx.startActivity(i);
+ }
+ });
+ MenuItem mi = topBar.getMenu().add(langSelected.toUpperCase()).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(final MenuItem item) {
+ showPopupLangMenu(ctx, topBar, app, a, dialog, langSelected);
+ return true;
+ }
+ });
+ MenuItemCompat.setShowAsAction(mi, MenuItem.SHOW_AS_ACTION_ALWAYS);
+ topBar.setNavigationOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ dialog.dismiss();
+ }
+ });
+ final WebView wv = new WebView(ctx);
+ WebSettings settings = wv.getSettings();
+ settings.setDefaultTextEncodingName("utf-8");
+ settings.setBuiltInZoomControls(true);
+ settings.setDisplayZoomControls(false);
+ settings.setSupportZoom(true);
+
+ wv.loadDataWithBaseURL(null, content, "text/html", "UTF-8", null);
+// wv.loadUrl(OsMoService.SIGN_IN_URL + app.getSettings().OSMO_DEVICE_KEY.get());
+ ScrollView scrollView = new ScrollView(ctx);
+ ll.addView(topBar);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
+ lp.weight = 1;
+ ll.addView(scrollView, lp);
+ ll.addView(bottomBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ scrollView.addView(wv);
+ dialog.setContentView(ll);
+ wv.setFocusable(true);
+ wv.setFocusableInTouchMode(true);
+ wv.requestFocus(View.FOCUS_DOWN);
+ wv.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_UP:
+ if (!v.hasFocus()) {
+ v.requestFocus();
+ }
+ break;
+ }
+ return false;
+ }
+ });
+
+ dialog.setCancelable(true);
+ dialog.show();
+ }
+
+ protected static void showPopupLangMenu(final Context ctx, Toolbar tb,
+ final SampleApplication app, final Amenity a,
+ final Dialog dialog, final String langSelected) {
+ final PopupMenu optionsMenu = new PopupMenu(ctx, tb, Gravity.RIGHT);
+ Set namesSet = new TreeSet<>();
+ namesSet.addAll(a.getNames("content", "en"));
+ namesSet.addAll(a.getNames("description", "en"));
+
+ Map names = new HashMap<>();
+ for (String n : namesSet) {
+ names.put(n, getLangName(ctx, n));
+ }
+ String selectedLangName = names.get(langSelected);
+ if (selectedLangName != null) {
+ names.remove(langSelected);
+ }
+ Map sortedNames = AndroidUtils.sortByValue(names);
+
+ if (selectedLangName != null) {
+ MenuItem item = optionsMenu.getMenu().add(selectedLangName);
+ item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ dialog.dismiss();
+ showWiki(ctx, app, a, langSelected);
+ return true;
+ }
+ });
+ }
+ for (final Map.Entry e : sortedNames.entrySet()) {
+ MenuItem item = optionsMenu.getMenu().add(e.getValue());
+ item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ dialog.dismiss();
+ showWiki(ctx, app, a, e.getKey());
+ return true;
+ }
+ });
+ }
+ optionsMenu.show();
+ }
+
+ public static String getLangName(Context ctx, String basename) {
+ try {
+ String nm = basename.replace('-', '_').replace(' ', '_');
+ Field f = R.string.class.getField("lang_"+nm);
+ if (f != null) {
+ Integer in = (Integer) f.get(null);
+ return ctx.getString(in);
+ }
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ }
+ return basename;
+ }
+
+ private static void showText(final Context ctx, final SampleApplication app, final String text, String title) {
+ final Dialog dialog = new Dialog(ctx);
+
+ LinearLayout ll = new LinearLayout(ctx);
+ ll.setOrientation(LinearLayout.VERTICAL);
+
+ final Toolbar topBar = new Toolbar(ctx);
+ topBar.setClickable(true);
+ Drawable back = app.getIconsCache().getIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
+ topBar.setNavigationIcon(back);
+ topBar.setNavigationContentDescription(app.getString("access_shared_string_navigate_up"));
+ topBar.setTitle(title);
+ topBar.setBackgroundColor(ContextCompat.getColor(ctx, R.color.osmand_orange));
+ topBar.setTitleTextColor(ContextCompat.getColor(ctx, R.color.color_white));
+ topBar.setNavigationOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ dialog.dismiss();
+ }
+ });
+
+ final TextView textView = new TextView(ctx);
+ LinearLayout.LayoutParams llTextParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ int textMargin = AndroidUtils.dpToPx(app, 10f);
+ boolean light = true;
+ textView.setLayoutParams(llTextParams);
+ textView.setPadding(textMargin, textMargin, textMargin, textMargin);
+ textView.setTextSize(16);
+ textView.setTextColor(ContextCompat.getColor(app, light ? R.color.ctx_menu_info_text_light : R.color.ctx_menu_info_text_dark));
+ textView.setAutoLinkMask(Linkify.ALL);
+ textView.setLinksClickable(true);
+ textView.setText(text);
+
+ ScrollView scrollView = new ScrollView(ctx);
+ ll.addView(topBar);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
+ lp.weight = 1;
+ ll.addView(scrollView, lp);
+ scrollView.addView(textView);
+
+ dialog.setContentView(ll);
+ dialog.setCancelable(true);
+ dialog.show();
+ }
+}
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapContextMenu.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapContextMenu.java
new file mode 100644
index 0000000000..ea0f61c247
--- /dev/null
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapContextMenu.java
@@ -0,0 +1,556 @@
+package net.osmand.core.samples.android.sample1.mapcontextmenu;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import net.osmand.core.samples.android.sample1.MainActivity;
+import net.osmand.core.samples.android.sample1.data.PointDescription;
+import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController.MenuState;
+import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController.MenuType;
+import net.osmand.data.LatLon;
+import net.osmand.util.MapUtils;
+
+import java.lang.ref.WeakReference;
+
+public class MapContextMenu extends MenuTitleController {
+
+ private MainActivity mainActivity;
+ private MapMultiSelectionMenu mapMultiSelectionMenu;
+
+ private boolean active;
+ private LatLon latLon;
+ private PointDescription pointDescription;
+ private Object object;
+ private MenuController menuController;
+
+ private LatLon mapCenter;
+ private boolean centerMarker;
+ private int mapZoom;
+
+ private LatLon myLocation;
+ private Float heading;
+ private boolean inLocationUpdate = false;
+ private boolean autoHide;
+
+ private MenuAction searchDoneAction;
+
+ public MapContextMenu() {
+ }
+
+ @Override
+ public MainActivity getMainActivity() {
+ return mainActivity;
+ }
+
+ public void setMainActivity(MainActivity mainActivity) {
+ this.mainActivity = mainActivity;
+
+ if (mapMultiSelectionMenu == null) {
+ mapMultiSelectionMenu = new MapMultiSelectionMenu(mainActivity);
+ } else {
+ mapMultiSelectionMenu.setMainActivity(mainActivity);
+ }
+
+ if (active) {
+ acquireMenuController(false);
+ if (menuController != null) {
+ menuController.addPlainMenuItems(typeStr, this.pointDescription, this.latLon);
+ }
+ if (searchDoneAction != null && searchDoneAction.dlg != null && searchDoneAction.dlg.getOwnerActivity() != mainActivity) {
+ searchDoneAction.dlg = buildSearchActionDialog();
+ searchDoneAction.dlg.show();
+ }
+ } else {
+ menuController = null;
+ }
+ }
+
+ public MapMultiSelectionMenu getMultiSelectionMenu() {
+ return mapMultiSelectionMenu;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public boolean isVisible() {
+ return findMenuFragment() != null;
+ }
+
+ public void hideMenues() {
+ if (isVisible()) {
+ hide();
+ } else if (mapMultiSelectionMenu.isVisible()) {
+ mapMultiSelectionMenu.hide();
+ }
+ }
+
+ @Override
+ public LatLon getLatLon() {
+ return latLon;
+ }
+
+ public LatLon getMapCenter() {
+ return mapCenter;
+ }
+
+ public void setMapCenter(LatLon mapCenter) {
+ this.mapCenter = mapCenter;
+ }
+
+ public void setCenterMarker(boolean centerMarker) {
+ this.centerMarker = centerMarker;
+ }
+
+ public int getMapZoom() {
+ return mapZoom;
+ }
+
+ public void setMapZoom(int mapZoom) {
+ this.mapZoom = mapZoom;
+ }
+
+ public void updateMapCenter(LatLon mapCenter) {
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null) {
+ fragmentRef.get().updateMapCenter(mapCenter);
+ }
+ }
+
+ @Override
+ public PointDescription getPointDescription() {
+ return pointDescription;
+ }
+
+ @Override
+ public Object getObject() {
+ return object;
+ }
+
+ public boolean isExtended() {
+ return menuController != null;
+ }
+
+ @Override
+ public MenuController getMenuController() {
+ return menuController;
+ }
+
+ public boolean init(@NonNull LatLon latLon,
+ @Nullable PointDescription pointDescription,
+ @Nullable Object object) {
+ return init(latLon, pointDescription, object, false, false);
+ }
+
+ public boolean init(@NonNull LatLon latLon,
+ @Nullable PointDescription pointDescription,
+ @Nullable Object object,
+ boolean update, boolean restorePrevious) {
+
+ if (myLocation == null) {
+ myLocation = mainActivity.getMyApplication().getLocationProvider().getLastKnownLocationLatLon();
+ }
+
+ if (!update && isVisible()) {
+ if (this.object == null || !this.object.equals(object)) {
+ hide();
+ } else {
+ return false;
+ }
+ }
+
+ if (pointDescription == null) {
+ this.pointDescription = new PointDescription(latLon.getLatitude(), latLon.getLongitude());
+ } else {
+ this.pointDescription = pointDescription;
+ }
+
+ boolean needAcquireMenuController = menuController == null
+ || !update
+ || this.object == null && object != null
+ || this.object != null && object == null
+ || (this.object != null && object != null && !this.object.getClass().equals(object.getClass()));
+
+ this.latLon = latLon;
+ this.object = object;
+
+ active = true;
+
+ if (needAcquireMenuController) {
+ acquireMenuController(restorePrevious);
+ } else {
+ menuController.update(pointDescription, object);
+ }
+ initTitle();
+
+ if (menuController != null) {
+ menuController.clearPlainMenuItems();
+ menuController.addPlainMenuItems(typeStr, this.pointDescription, this.latLon);
+ }
+
+ mainActivity.refreshMap();
+
+ return true;
+ }
+
+ public void show() {
+ if (!isVisible()) {
+ if (!MapContextMenuFragment.showInstance(this, mainActivity, true)) {
+ active = false;
+ }
+ } else {
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null) {
+ fragmentRef.get().centerMarkerLocation();
+ }
+ }
+ }
+
+ public void show(@NonNull LatLon latLon,
+ @Nullable PointDescription pointDescription,
+ @Nullable Object object) {
+ if (init(latLon, pointDescription, object)) {
+ showInternal();
+ }
+ }
+
+ private void showInternal() {
+ if (!MapContextMenuFragment.showInstance(this, mainActivity, centerMarker)) {
+ active = false;
+ } else {
+ if (menuController != null) {
+ menuController.onShow();
+ }
+ }
+ centerMarker = false;
+ autoHide = false;
+ }
+
+ public void update(LatLon latLon, PointDescription pointDescription, Object object) {
+ WeakReference fragmentRef = findMenuFragment();
+ init(latLon, pointDescription, object, true, false);
+ if (fragmentRef != null) {
+ fragmentRef.get().rebuildMenu();
+ }
+ }
+
+ public void showOrUpdate(LatLon latLon, PointDescription pointDescription, Object object) {
+ if (isVisible() && this.object != null && this.object.equals(object)) {
+ update(latLon, pointDescription, object);
+ } else {
+ show(latLon, pointDescription, object);
+ }
+ }
+
+ public void showMinimized(LatLon latLon, PointDescription pointDescription, Object object) {
+ init(latLon, pointDescription, object);
+ }
+
+ public void close() {
+ if (active) {
+ active = false;
+ if (menuController != null) {
+ menuController.onClose();
+ }
+ hide();
+ if (menuController != null) {
+ menuController.setActive(false);
+ }
+ mainActivity.refreshMap();
+ }
+ }
+
+ public void hide() {
+ if (menuController != null) {
+ menuController.onHide();
+ }
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null) {
+ fragmentRef.get().dismissMenu();
+ }
+ }
+
+ // timeout in msec
+ public void hideWithTimeout(long timeout) {
+ autoHide = true;
+ mainActivity.getMyApplication().runInUIThread(new Runnable() {
+ @Override
+ public void run() {
+ if (autoHide) {
+ hide();
+ }
+ }
+ }, timeout);
+ }
+
+ public void updateMenuUI() {
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null) {
+ fragmentRef.get().updateMenu();
+ }
+ }
+
+ private void updateTitle(String address) {
+ nameStr = address;
+ pointDescription.setName(address);
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null)
+ fragmentRef.get().refreshTitle();
+ }
+
+ private void acquireMenuController(boolean restorePrevious) {
+ if (menuController != null) {
+ menuController.onAcquireNewController(pointDescription, object);
+ }
+ menuController = MenuController.getMenuController(mainActivity, latLon, pointDescription, object, MenuType.STANDARD);
+ menuController.setActive(true);
+ }
+
+ public void onSingleTapOnMap() {
+ if (menuController == null || !menuController.handleSingleTapOnMap()) {
+ hide();
+ }
+ }
+
+ @Override
+ public void onSearchAddressDone() {
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null)
+ fragmentRef.get().refreshTitle();
+
+ if (searchDoneAction != null) {
+ if (searchDoneAction.dlg != null) {
+ try {
+ searchDoneAction.dlg.dismiss();
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ searchDoneAction.dlg = null;
+ }
+ }
+ searchDoneAction.run();
+ searchDoneAction = null;
+ }
+ }
+
+ public WeakReference findMenuFragment() {
+ Fragment fragment = mainActivity.getSupportFragmentManager().findFragmentByTag(MapContextMenuFragment.TAG);
+ if (fragment != null && !fragment.isDetached()) {
+ return new WeakReference<>((MapContextMenuFragment) fragment);
+ } else {
+ return null;
+ }
+ }
+
+ private void callMenuAction(boolean waitForAddressLookup, MenuAction menuAction) {
+ if (searchingAddress() && waitForAddressLookup) {
+ menuAction.dlg = buildSearchActionDialog();
+ menuAction.dlg.show();
+ searchDoneAction = menuAction;
+ } else {
+ menuAction.run();
+ }
+ }
+
+ private ProgressDialog buildSearchActionDialog() {
+ ProgressDialog dlg = new ProgressDialog(mainActivity);
+ dlg.setTitle("");
+ dlg.setMessage(searchAddressStr);
+ dlg.setButton(Dialog.BUTTON_NEGATIVE, mainActivity.getMyApplication().getString("shared_string_skip"), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ cancelSearchAddress();
+ }
+ });
+ return dlg;
+ }
+
+ public void setBaseFragmentVisibility(boolean visible) {
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null) {
+ fragmentRef.get().setFragmentVisibility(visible);
+ }
+ }
+
+ public boolean isLandscapeLayout() {
+ return menuController != null && menuController.isLandscapeLayout();
+ }
+
+ public int getLandscapeWidthPx() {
+ if (menuController != null) {
+ return menuController.getLandscapeWidthPx();
+ } else {
+ return 0;
+ }
+ }
+
+ public void openMenuFullScreen() {
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null)
+ fragmentRef.get().openMenuFullScreen();
+ }
+
+ public boolean slideUp() {
+ return menuController != null && menuController.slideUp();
+ }
+
+ public boolean slideDown() {
+ return menuController != null && menuController.slideDown();
+ }
+
+ public void build(View rootView) {
+ if (menuController != null) {
+ menuController.build(rootView);
+ }
+ }
+
+ public int getCurrentMenuState() {
+ if (menuController != null) {
+ return menuController.getCurrentMenuState();
+ } else {
+ return MenuState.HEADER_ONLY;
+ }
+ }
+
+ public float getHalfScreenMaxHeightKoef() {
+ if (menuController != null) {
+ return menuController.getHalfScreenMaxHeightKoef();
+ } else {
+ return 0f;
+ }
+ }
+
+ public int getSlideInAnimation() {
+ if (menuController != null) {
+ return menuController.getSlideInAnimation();
+ } else {
+ return 0;
+ }
+ }
+
+ public int getSlideOutAnimation() {
+ if (menuController != null) {
+ return menuController.getSlideOutAnimation();
+ } else {
+ return 0;
+ }
+ }
+
+ public MenuController.TitleButtonController getLeftTitleButtonController() {
+ if (menuController != null) {
+ return menuController.getLeftTitleButtonController();
+ } else {
+ return null;
+ }
+ }
+
+ public MenuController.TitleButtonController getRightTitleButtonController() {
+ if (menuController != null) {
+ return menuController.getRightTitleButtonController();
+ } else {
+ return null;
+ }
+ }
+
+ public MenuController.TitleButtonController getTopRightTitleButtonController() {
+ if (menuController != null) {
+ return menuController.getTopRightTitleButtonController();
+ } else {
+ return null;
+ }
+ }
+
+ public boolean supportZoomIn() {
+ return menuController == null || menuController.supportZoomIn();
+ }
+
+ public boolean fabVisible() {
+ return menuController == null || menuController.fabVisible();
+ }
+
+ public boolean buttonsVisible() {
+ return menuController == null || menuController.buttonsVisible();
+ }
+
+ public boolean displayDistanceDirection() {
+ return menuController != null && menuController.displayDistanceDirection();
+ }
+
+ public boolean hasCustomAddressLine() {
+ return menuController != null && menuController.hasCustomAddressLine();
+ }
+
+ public void buildCustomAddressLine(LinearLayout ll) {
+ if (menuController != null) {
+ menuController.buildCustomAddressLine(ll);
+ }
+ }
+
+ public boolean isNightMode() {
+ if (menuController != null) {
+ return !menuController.isLight();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean hasHiddenBottomInfo() {
+ return getCurrentMenuState() == MenuState.HEADER_ONLY;
+ }
+
+ public LatLon getMyLocation() {
+ return myLocation;
+ }
+
+ public Float getHeading() {
+ return heading;
+ }
+
+ public void updateMyLocation(net.osmand.Location location) {
+ if (location != null && active && displayDistanceDirection()) {
+ myLocation = new LatLon(location.getLatitude(), location.getLongitude());
+ updateLocation(false, true, false);
+ }
+ }
+
+ public void updateCompassValue(float value) {
+ if (active && displayDistanceDirection()) {
+ // 99 in next line used to one-time initialize arrows (with reference vs. fixed-north direction)
+ // on non-compass devices
+ float lastHeading = heading != null ? heading : 99;
+ heading = value;
+ if (Math.abs(MapUtils.degreesDiff(lastHeading, heading)) > 5) {
+ updateLocation(false, false, true);
+ } else {
+ heading = lastHeading;
+ }
+ }
+ }
+
+ public void updateLocation(final boolean centerChanged, final boolean locationChanged,
+ final boolean compassChanged) {
+ if (inLocationUpdate) {
+ return;
+ }
+ inLocationUpdate = true;
+ mainActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ inLocationUpdate = false;
+ WeakReference fragmentRef = findMenuFragment();
+ if (fragmentRef != null) {
+ fragmentRef.get().updateLocation(centerChanged, locationChanged, compassChanged);
+ }
+ }
+ });
+ }
+
+ private abstract class MenuAction implements Runnable {
+ protected ProgressDialog dlg;
+ }
+}
\ No newline at end of file
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapContextMenuFragment.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapContextMenuFragment.java
new file mode 100644
index 0000000000..4fd07442c5
--- /dev/null
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapContextMenuFragment.java
@@ -0,0 +1,1045 @@
+package net.osmand.core.samples.android.sample1.mapcontextmenu;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.TargetApi;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import net.osmand.AndroidUtils;
+import net.osmand.Location;
+import net.osmand.core.android.AtlasMapRendererView;
+import net.osmand.core.jni.PointI;
+import net.osmand.core.jni.Utilities;
+import net.osmand.core.samples.android.sample1.IconsCache;
+import net.osmand.core.samples.android.sample1.MainActivity;
+import net.osmand.core.samples.android.sample1.R;
+import net.osmand.core.samples.android.sample1.SampleApplication;
+import net.osmand.core.samples.android.sample1.SampleUtils;
+import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController.MenuState;
+import net.osmand.core.samples.android.sample1.search.QuickSearchListAdapter;
+import net.osmand.core.samples.android.sample1.view.SingleTapConfirm;
+import net.osmand.data.LatLon;
+import net.osmand.data.QuadPoint;
+import net.osmand.data.RotatedTileBox;
+import net.osmand.util.Algorithms;
+
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static net.osmand.core.samples.android.sample1.mapcontextmenu.MenuBuilder.SHADOW_HEIGHT_TOP_DP;
+
+
+public class MapContextMenuFragment extends Fragment {
+ public static final String TAG = "MapContextMenuFragment";
+
+ public static final float FAB_PADDING_TOP_DP = 4f;
+ public static final float MARKER_PADDING_DP = 20f;
+ public static final float MARKER_PADDING_X_DP = 50f;
+ public static final float SKIP_HALF_SCREEN_STATE_KOEF = .21f;
+ public static final int ZOOM_IN_STANDARD = 16;
+
+ private View view;
+ private View mainView;
+
+ private MapContextMenu menu;
+ private MenuController.TitleButtonController leftTitleButtonController;
+ private MenuController.TitleButtonController rightTitleButtonController;
+ private MenuController.TitleButtonController topRightTitleButtonController;
+
+ private int menuTopViewHeight;
+ private int menuTopShadowHeight;
+ private int menuTopShadowAllHeight;
+ private int menuTitleHeight;
+ private int menuBottomViewHeight;
+ private int menuFullHeight;
+ private int menuFullHeightMax;
+ private int menuTopViewHeightExcludingTitle;
+ private int menuTitleTopBottomPadding;
+
+ private int screenHeight;
+ private int viewHeight;
+
+ private int fabPaddingTopPx;
+ private int markerPaddingPx;
+ private int markerPaddingXPx;
+
+ private AtlasMapRendererView map;
+ private LatLon mapCenter;
+ private int origMarkerX;
+ private int origMarkerY;
+ private boolean customMapCenter;
+ private boolean moving;
+ private boolean nightMode;
+ private boolean centered;
+ private boolean initLayout = true;
+ private boolean zoomIn;
+
+ private float skipHalfScreenStateLimit;
+
+ private int screenOrientation;
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ screenHeight = AndroidUtils.getScreenHeight(getActivity());
+ skipHalfScreenStateLimit = screenHeight * SKIP_HALF_SCREEN_STATE_KOEF;
+
+ viewHeight = screenHeight - AndroidUtils.getStatusBarHeight(getMainActivity());
+
+ fabPaddingTopPx = dpToPx(FAB_PADDING_TOP_DP);
+ markerPaddingPx = dpToPx(MARKER_PADDING_DP);
+ markerPaddingXPx = dpToPx(MARKER_PADDING_X_DP);
+
+ menu = getMainActivity().getContextMenu();
+ view = inflater.inflate(R.layout.map_context_menu_fragment, container, false);
+ if (!menu.isActive()) {
+ return view;
+ }
+ nightMode = menu.isNightMode();
+ mainView = view.findViewById(R.id.context_menu_main);
+
+ leftTitleButtonController = menu.getLeftTitleButtonController();
+ rightTitleButtonController = menu.getRightTitleButtonController();
+ topRightTitleButtonController = menu.getTopRightTitleButtonController();
+
+ map = getMainActivity().getMapView();
+
+ RotatedTileBox box = getBox();
+ customMapCenter = menu.getMapCenter() != null;
+ if (!customMapCenter) {
+ mapCenter = box.getCenterLatLon();
+ menu.setMapCenter(mapCenter);
+ double markerLat = menu.getLatLon().getLatitude();
+ double markerLon = menu.getLatLon().getLongitude();
+ origMarkerX = (int) box.getPixXFromLatLon(markerLat, markerLon);
+ origMarkerY = (int) box.getPixYFromLatLon(markerLat, markerLon);
+ } else {
+ mapCenter = menu.getMapCenter();
+ origMarkerX = box.getCenterPixelX();
+ origMarkerY = box.getCenterPixelY();
+ }
+
+ // Left title button
+ final Button leftTitleButton = (Button) view.findViewById(R.id.title_button);
+ if (leftTitleButtonController != null) {
+ leftTitleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ leftTitleButtonController.buttonPressed();
+ }
+ });
+ }
+
+ // Right title button
+ final Button rightTitleButton = (Button) view.findViewById(R.id.title_button_right);
+ if (rightTitleButtonController != null) {
+ rightTitleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ rightTitleButtonController.buttonPressed();
+ }
+ });
+ }
+
+ // Top Right title button
+ final Button topRightTitleButton = (Button) view.findViewById(R.id.title_button_top_right);
+ if (topRightTitleButtonController != null) {
+ topRightTitleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ topRightTitleButtonController.buttonPressed();
+ }
+ });
+ }
+
+ updateButtonsAndProgress();
+
+ if (menu.isLandscapeLayout()) {
+ final TypedValue typedValueAttr = new TypedValue();
+ getMainActivity().getTheme().resolveAttribute(R.attr.left_menu_view_bg, typedValueAttr, true);
+ mainView.setBackgroundResource(typedValueAttr.resourceId);
+ mainView.setLayoutParams(new FrameLayout.LayoutParams(menu.getLandscapeWidthPx(),
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ View fabContainer = view.findViewById(R.id.context_menu_fab_container);
+ fabContainer.setLayoutParams(new FrameLayout.LayoutParams(menu.getLandscapeWidthPx(),
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ }
+
+ runLayoutListener();
+
+ final GestureDetector singleTapDetector = new GestureDetector(view.getContext(), new SingleTapConfirm());
+
+ final View.OnTouchListener slideTouchListener = new View.OnTouchListener() {
+ private float dy;
+ private float dyMain;
+ private VelocityTracker velocity;
+ private boolean slidingUp;
+ private boolean slidingDown;
+
+ private float velocityY;
+ private float maxVelocityY;
+
+ private boolean hasMoved;
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+
+ if (singleTapDetector.onTouchEvent(event)) {
+ moving = false;
+ int posY = getViewY();
+ if (!centered) {
+ if (!zoomIn && menu.supportZoomIn()) {
+ LatLon centerLatLon = getMainActivity().getScreenCenter();
+ if (centerLatLon.equals(menu.getLatLon())) {
+ zoomIn = true;
+ }
+ }
+ centerMarkerLocation();
+ } else if (!zoomIn && menu.supportZoomIn()) {
+ int fZoom = getZoom();
+ zoomIn = true;
+ if (fZoom < ZOOM_IN_STANDARD) {
+ /* todo animation
+ AnimateDraggingMapThread thread = map.getAnimatedDraggingThread();
+ thread.startZooming(ZOOM_IN_STANDARD,
+ map.getZoomFractionalPart(), true);
+ */
+ map.setZoom(ZOOM_IN_STANDARD);
+ }
+ }
+ if (hasMoved) {
+ applyPosY(posY, false, false, 0, 0);
+ }
+ openMenuHalfScreen();
+ return true;
+ }
+
+ if (menu.isLandscapeLayout()) {
+ return true;
+ }
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ hasMoved = false;
+ dy = event.getY();
+ dyMain = getViewY();
+ velocity = VelocityTracker.obtain();
+ velocityY = 0;
+ maxVelocityY = 0;
+ velocity.addMovement(event);
+ moving = true;
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (moving) {
+ hasMoved = true;
+ float y = event.getY();
+ float newY = getViewY() + (y - dy);
+ setViewY((int) newY, false, false);
+
+ menuFullHeight = view.getHeight() - (int) newY + 10;
+ if (!oldAndroid()) {
+ ViewGroup.LayoutParams lp = mainView.getLayoutParams();
+ lp.height = Math.max(menuFullHeight, menuTitleHeight);
+ mainView.setLayoutParams(lp);
+ mainView.requestLayout();
+ }
+
+ velocity.addMovement(event);
+ velocity.computeCurrentVelocity(1000);
+ velocityY = Math.abs(velocity.getYVelocity());
+ if (velocityY > maxVelocityY)
+ maxVelocityY = velocityY;
+ }
+
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ if (moving) {
+ moving = false;
+ int currentY = getViewY();
+
+ slidingUp = Math.abs(maxVelocityY) > 500 && (currentY - dyMain) < -50;
+ slidingDown = Math.abs(maxVelocityY) > 500 && (currentY - dyMain) > 50;
+
+ velocity.recycle();
+
+ boolean skipHalfScreenState = Math.abs(currentY - dyMain) > skipHalfScreenStateLimit;
+ changeMenuState(currentY, skipHalfScreenState, slidingUp, slidingDown);
+ }
+ break;
+
+ }
+ return true;
+ }
+ };
+
+ View topView = view.findViewById(R.id.context_menu_top_view);
+ topView.setOnTouchListener(slideTouchListener);
+ View topShadowView = view.findViewById(R.id.context_menu_top_shadow);
+ topShadowView.setOnTouchListener(slideTouchListener);
+ View topShadowAllView = view.findViewById(R.id.context_menu_top_shadow_all);
+ //AndroidUtils.setBackground(getMainActivity(), topShadowAllView, nightMode, R.drawable.bg_map_context_menu_light,
+ // R.drawable.bg_map_context_menu_dark);
+ topShadowAllView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getY() <= dpToPx(SHADOW_HEIGHT_TOP_DP) || event.getAction() != MotionEvent.ACTION_DOWN)
+ return slideTouchListener.onTouch(v, event);
+ else
+ return false;
+ }
+ });
+
+ buildHeader();
+
+ AndroidUtils.setTextPrimaryColor(getMainActivity(),
+ (TextView) view.findViewById(R.id.context_menu_line1), nightMode);
+ View menuLine2 = view.findViewById(R.id.context_menu_line2);
+ if (menuLine2 != null) {
+ AndroidUtils.setTextSecondaryColor(getMainActivity(), (TextView) menuLine2, nightMode);
+ }
+ ((Button) view.findViewById(R.id.title_button_top_right))
+ .setTextColor(!nightMode ? getResources().getColor(R.color.map_widget_blue) : getResources().getColor(R.color.osmand_orange));
+ AndroidUtils.setTextSecondaryColor(getMainActivity(),
+ (TextView) view.findViewById(R.id.distance), nightMode);
+
+ ((Button) view.findViewById(R.id.title_button))
+ .setTextColor(!nightMode ? getResources().getColor(R.color.map_widget_blue) : getResources().getColor(R.color.osmand_orange));
+ AndroidUtils.setTextSecondaryColor(getMainActivity(),
+ (TextView) view.findViewById(R.id.title_button_right_text), nightMode);
+ ((Button) view.findViewById(R.id.title_button_right))
+ .setTextColor(!nightMode ? getResources().getColor(R.color.map_widget_blue) : getResources().getColor(R.color.osmand_orange));
+
+ // FAB
+ /*
+ fabView = (ImageView) view.findViewById(R.id.context_menu_fab_view);
+ if (menu.fabVisible()) {
+ fabView.setImageDrawable(iconsCache.getIcon(menu.getFabIconId(), 0));
+ if (menu.isLandscapeLayout()) {
+ FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) fabView.getLayoutParams();
+ params.setMargins(0, 0, dpToPx(28f), 0);
+ fabView.setLayoutParams(params);
+ }
+ fabView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ menu.fabPressed();
+ }
+ });
+ } else {
+ fabView.setVisibility(View.GONE);
+ }
+ */
+
+ buildBottomView();
+
+ view.findViewById(R.id.context_menu_bottom_scroll).setBackgroundColor(nightMode ?
+ getResources().getColor(R.color.ctx_menu_info_view_bg_dark) : getResources().getColor(R.color.ctx_menu_info_view_bg_light));
+ view.findViewById(R.id.context_menu_bottom_view).setBackgroundColor(nightMode ?
+ getResources().getColor(R.color.ctx_menu_info_view_bg_dark) : getResources().getColor(R.color.ctx_menu_info_view_bg_light));
+
+ return view;
+ }
+
+ public RotatedTileBox getBox() {
+ return getMainActivity().getBox();
+ }
+
+ public void openMenuFullScreen() {
+ changeMenuState(getViewY(), true, true, false);
+ }
+
+ public void openMenuHalfScreen() {
+ int oldMenuState = menu.getCurrentMenuState();
+ if (oldMenuState == MenuState.HEADER_ONLY) {
+ changeMenuState(getViewY(), false, true, false);
+ } else if (oldMenuState == MenuState.FULL_SCREEN && !menu.isLandscapeLayout()) {
+ changeMenuState(getViewY(), false, false, true);
+ }
+ }
+
+ private void changeMenuState(int currentY, boolean skipHalfScreenState,
+ boolean slidingUp, boolean slidingDown) {
+ boolean needCloseMenu = false;
+
+ int oldMenuState = menu.getCurrentMenuState();
+ if (menuBottomViewHeight > 0 && slidingUp) {
+ menu.slideUp();
+ if (skipHalfScreenState) {
+ menu.slideUp();
+ }
+ } else if (slidingDown) {
+ needCloseMenu = !menu.slideDown();
+ if (!needCloseMenu && skipHalfScreenState) {
+ menu.slideDown();
+ }
+ }
+ int newMenuState = menu.getCurrentMenuState();
+ boolean needMapAdjust = oldMenuState != newMenuState && newMenuState != MenuState.FULL_SCREEN;
+
+ if (newMenuState != oldMenuState) {
+ doBeforeMenuStateChange(oldMenuState, newMenuState);
+ }
+
+ applyPosY(currentY, needCloseMenu, needMapAdjust, oldMenuState, newMenuState);
+ }
+
+ private void applyPosY(final int currentY, final boolean needCloseMenu, boolean needMapAdjust,
+ final int previousMenuState, final int newMenuState) {
+ final int posY = getPosY(needCloseMenu);
+ if (currentY != posY) {
+ if (posY < currentY) {
+ updateMainViewLayout(posY);
+ }
+
+ if (!oldAndroid()) {
+ mainView.animate().y(posY)
+ .setDuration(200)
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(new AnimatorListenerAdapter() {
+
+ boolean canceled = false;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ canceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!canceled) {
+ if (needCloseMenu) {
+ menu.close();
+ } else {
+ updateMainViewLayout(posY);
+ if (previousMenuState != 0 && newMenuState != 0 && previousMenuState != newMenuState) {
+ doAfterMenuStateChange(previousMenuState, newMenuState);
+ }
+ }
+ }
+ }
+ })
+ .start();
+
+ /*
+ fabView.animate().y(getFabY(posY))
+ .setDuration(200)
+ .setInterpolator(new DecelerateInterpolator())
+ .start();
+ */
+
+ if (needMapAdjust) {
+ adjustMapPosition(posY, true, centered);
+ }
+ } else {
+ setViewY(posY, false, needMapAdjust);
+ if (needCloseMenu) {
+ menu.close();
+ } else {
+ updateMainViewLayout(posY);
+ if (previousMenuState != 0 && newMenuState != 0 && previousMenuState != newMenuState) {
+ doAfterMenuStateChange(previousMenuState, newMenuState);
+ }
+ }
+ }
+ }
+ }
+
+ public void updateMapCenter(LatLon mapCenter) {
+ customMapCenter = true;
+ menu.setMapCenter(mapCenter);
+ this.mapCenter = mapCenter;
+ origMarkerX = mainView.getWidth() / 2;
+ origMarkerY = mainView.getHeight() / 2;
+ }
+
+ private void updateButtonsAndProgress() {
+ // Title buttons
+ boolean showTitleButtonsContainer = (leftTitleButtonController != null || rightTitleButtonController != null);
+ final View titleButtonsContainer = view.findViewById(R.id.title_button_container);
+ titleButtonsContainer.setVisibility(showTitleButtonsContainer ? View.VISIBLE : View.GONE);
+
+ // Left title button
+ final Button leftTitleButton = (Button) view.findViewById(R.id.title_button);
+ final TextView titleButtonRightText = (TextView) view.findViewById(R.id.title_button_right_text);
+ if (leftTitleButtonController != null) {
+ leftTitleButton.setText(leftTitleButtonController.caption);
+ leftTitleButton.setVisibility(leftTitleButtonController.visible ? View.VISIBLE : View.GONE);
+
+ Drawable leftIcon = leftTitleButtonController.getLeftIcon();
+ if (leftIcon != null) {
+ leftTitleButton.setCompoundDrawablesWithIntrinsicBounds(leftIcon, null, null, null);
+ leftTitleButton.setCompoundDrawablePadding(dpToPx(4f));
+ }
+
+ if (leftTitleButtonController.needRightText) {
+ titleButtonRightText.setText(leftTitleButtonController.rightTextCaption);
+ titleButtonRightText.setVisibility(View.VISIBLE);
+ } else {
+ titleButtonRightText.setVisibility(View.GONE);
+ }
+ } else {
+ leftTitleButton.setVisibility(View.GONE);
+ titleButtonRightText.setVisibility(View.GONE);
+ }
+
+ // Right title button
+ final Button rightTitleButton = (Button) view.findViewById(R.id.title_button_right);
+ if (rightTitleButtonController != null) {
+ rightTitleButton.setText(rightTitleButtonController.caption);
+ rightTitleButton.setVisibility(rightTitleButtonController.visible ? View.VISIBLE : View.GONE);
+
+ Drawable leftIcon = rightTitleButtonController.getLeftIcon();
+ rightTitleButton.setCompoundDrawablesWithIntrinsicBounds(leftIcon, null, null, null);
+ rightTitleButton.setCompoundDrawablePadding(dpToPx(4f));
+ } else {
+ rightTitleButton.setVisibility(View.GONE);
+ }
+
+ // Top Right title button
+ final Button topRightTitleButton = (Button) view.findViewById(R.id.title_button_top_right);
+ if (topRightTitleButtonController != null) {
+ topRightTitleButton.setText(topRightTitleButtonController.caption);
+ topRightTitleButton.setVisibility(topRightTitleButtonController.visible ? View.VISIBLE : View.INVISIBLE);
+
+ Drawable leftIcon = topRightTitleButtonController.getLeftIcon();
+ topRightTitleButton.setCompoundDrawablesWithIntrinsicBounds(leftIcon, null, null, null);
+ topRightTitleButton.setCompoundDrawablePadding(dpToPx(4f));
+ } else {
+ topRightTitleButton.setVisibility(View.GONE);
+ }
+ }
+
+ private void buildHeader() {
+ IconsCache iconsCache = getMyApplication().getIconsCache();
+
+ final View iconLayout = view.findViewById(R.id.context_menu_icon_layout);
+ final ImageView iconView = (ImageView) view.findViewById(R.id.context_menu_icon_view);
+ Drawable icon = menu.getLeftIcon();
+ int iconId = menu.getLeftIconId();
+ if (icon != null) {
+ iconView.setImageDrawable(icon);
+ iconLayout.setVisibility(View.VISIBLE);
+ } else if (iconId != 0) {
+ iconView.setImageDrawable(iconsCache.getOsmandIcon(iconId,
+ !nightMode ? R.color.osmand_orange : R.color.osmand_orange_dark));
+ iconLayout.setVisibility(View.VISIBLE);
+ } else {
+ iconLayout.setVisibility(View.GONE);
+ }
+ setAddressLocation();
+ }
+
+ private void buildBottomView() {
+ View bottomView = view.findViewById(R.id.context_menu_bottom_view);
+ if (menu.isExtended()) {
+ bottomView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return true;
+ }
+ });
+ menu.build(bottomView);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (!menu.isActive()) {
+ dismissMenu();
+ return;
+ }
+ screenOrientation = SampleUtils.getScreenOrientation(getActivity());
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (mapCenter != null) {
+ PointI centerI = Utilities.convertLatLonTo31(
+ new net.osmand.core.jni.LatLon(mapCenter.getLatitude(), mapCenter.getLongitude()));
+ map.setTarget(centerI);
+ }
+ menu.setMapCenter(null);
+ menu.setMapZoom(0);
+ }
+
+ public void rebuildMenu() {
+ buildHeader();
+
+ LinearLayout bottomLayout = (LinearLayout) view.findViewById(R.id.context_menu_bottom_view);
+ bottomLayout.removeAllViews();
+ buildBottomView();
+
+ runLayoutListener();
+ }
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ private void runLayoutListener() {
+ ViewTreeObserver vto = view.getViewTreeObserver();
+ vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+
+ @Override
+ public void onGlobalLayout() {
+
+ ViewTreeObserver obs = view.getViewTreeObserver();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ obs.removeOnGlobalLayoutListener(this);
+ } else {
+ obs.removeGlobalOnLayoutListener(this);
+ }
+
+ if (getActivity() == null) {
+ return;
+ }
+
+ int newMenuTopViewHeight = view.findViewById(R.id.context_menu_top_view).getHeight();
+ menuTopShadowHeight = view.findViewById(R.id.context_menu_top_shadow).getHeight();
+ int newMenuTopShadowAllHeight = view.findViewById(R.id.context_menu_top_shadow_all).getHeight();
+ menuFullHeight = view.findViewById(R.id.context_menu_main).getHeight();
+
+ int dy = 0;
+ if (!menu.isLandscapeLayout()) {
+ TextView line1 = (TextView) view.findViewById(R.id.context_menu_line1);
+ TextView line2 = (TextView) view.findViewById(R.id.context_menu_line2);
+ int line2LineCount = 0;
+ int line2LineHeight = 0;
+ int line2MeasuredHeight = 0;
+ if (line2 != null) {
+ line2LineCount = line2.getLineCount();
+ line2LineHeight = line2.getLineHeight();
+ line2MeasuredHeight = line2.getMeasuredHeight();
+ }
+ if (menuTopViewHeight != 0) {
+ int titleHeight = line1.getLineCount() * line1.getLineHeight() + line2LineCount * line2LineHeight + menuTitleTopBottomPadding;
+ if (titleHeight < line1.getMeasuredHeight() + line2MeasuredHeight) {
+ titleHeight = line1.getMeasuredHeight() + line2MeasuredHeight;
+ }
+ newMenuTopViewHeight = menuTopViewHeightExcludingTitle + titleHeight;
+ dy = Math.max(0, newMenuTopViewHeight - menuTopViewHeight - (newMenuTopShadowAllHeight - menuTopShadowAllHeight));
+ } else {
+ menuTopViewHeightExcludingTitle = newMenuTopViewHeight - line1.getMeasuredHeight() - line2MeasuredHeight;
+ menuTitleTopBottomPadding = (line1.getMeasuredHeight() - line1.getLineCount() * line1.getLineHeight())
+ + (line2MeasuredHeight - line2LineCount * line2LineHeight);
+ }
+ }
+ menuTopViewHeight = newMenuTopViewHeight;
+ menuTopShadowAllHeight = newMenuTopShadowAllHeight;
+ menuTitleHeight = menuTopShadowHeight + menuTopShadowAllHeight + dy;
+ menuBottomViewHeight = view.findViewById(R.id.context_menu_bottom_view).getHeight();
+
+ menuFullHeightMax = menuTitleHeight + menuBottomViewHeight;
+
+ if (origMarkerX == 0 && origMarkerY == 0) {
+ origMarkerX = view.getWidth() / 2;
+ origMarkerY = view.getHeight() / 2;
+ }
+
+ if (initLayout && centered) {
+ centerMarkerLocation();
+ }
+ if (!moving) {
+ doLayoutMenu();
+ }
+ initLayout = false;
+ }
+
+ });
+ }
+
+ public void centerMarkerLocation() {
+ centered = true;
+ showOnMap(menu.getLatLon(), true, true, false);
+ }
+
+ private int getZoom() {
+ int zoom;
+ if (zoomIn) {
+ zoom = ZOOM_IN_STANDARD;
+ } else {
+ zoom = menu.getMapZoom();
+ }
+ if (zoom == 0) {
+ zoom = (int)getMainActivity().getZoom();
+ }
+ return zoom;
+ }
+
+ private void showOnMap(LatLon latLon, boolean updateCoords, boolean needMove, boolean alreadyAdjusted) {
+ //AnimateDraggingMapThread thread = map.getAnimatedDraggingThread(); todo amimation
+ int fZoom = getZoom();
+ double flat = latLon.getLatitude();
+ double flon = latLon.getLongitude();
+
+ RotatedTileBox cp = getBox();
+ //cp.setCenterLocation(0.5f, map.getMapPosition() == OsmandSettings.BOTTOM_CONSTANT ? 0.15f : 0.5f);
+ cp.setLatLonCenter(flat, flon);
+ cp.setZoom(fZoom);
+ flat = cp.getLatFromPixel(cp.getPixWidth() / 2, cp.getPixHeight() / 2);
+ flon = cp.getLonFromPixel(cp.getPixWidth() / 2, cp.getPixHeight() / 2);
+
+ if (updateCoords) {
+ mapCenter = new LatLon(flat, flon);
+ menu.setMapCenter(mapCenter);
+ origMarkerX = cp.getCenterPixelX();
+ origMarkerY = cp.getCenterPixelY();
+ }
+
+ if (!alreadyAdjusted) {
+ LatLon adjustedLatLon = getAdjustedMarkerLocation(getPosY(), new LatLon(flat, flon), true, fZoom);
+ flat = adjustedLatLon.getLatitude();
+ flon = adjustedLatLon.getLongitude();
+ }
+
+ if (needMove) {
+ //thread.startMoving(flat, flon, fZoom, true); todo animation
+ PointI targetI = Utilities.convertLatLonTo31(new net.osmand.core.jni.LatLon(flat, flon));
+ map.setTarget(targetI);
+ map.setZoom(fZoom);
+ }
+ }
+
+ private void setAddressLocation() {
+ // Text line 1
+ TextView line1 = (TextView) view.findViewById(R.id.context_menu_line1);
+ line1.setText(menu.getTitleStr());
+
+ // Text line 2
+ LinearLayout line2layout = (LinearLayout) view.findViewById(R.id.context_menu_line2_layout);
+ TextView line2 = (TextView) view.findViewById(R.id.context_menu_line2);
+ if (menu.hasCustomAddressLine()) {
+ line2layout.removeAllViews();
+ menu.buildCustomAddressLine(line2layout);
+ } else {
+ String typeStr = menu.getTypeStr();
+ String streetStr = menu.getStreetStr();
+ StringBuilder line2Str = new StringBuilder();
+ if (!Algorithms.isEmpty(typeStr)) {
+ line2Str.append(typeStr);
+ Drawable icon = menu.getTypeIcon();
+ line2.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
+ line2.setCompoundDrawablePadding(dpToPx(5f));
+ }
+ if (!Algorithms.isEmpty(streetStr) && !menu.displayStreetNameInTitle()) {
+ if (line2Str.length() > 0) {
+ line2Str.append(": ");
+ }
+ line2Str.append(streetStr);
+ }
+ line2.setText(line2Str.toString());
+ }
+
+ updateCompassVisibility();
+ }
+
+ private void updateCompassVisibility() {
+ View compassView = view.findViewById(R.id.compass_layout);
+ Location ll = getMyApplication().getLocationProvider().getLastKnownLocation();
+ boolean gpsFixed = ll != null && System.currentTimeMillis() - ll.getTime() < 1000 * 60 * 60 * 20;
+ if (gpsFixed && menu.displayDistanceDirection() && menu.getCurrentMenuState() != MenuState.FULL_SCREEN) {
+ updateDistanceDirection();
+ compassView.setVisibility(View.VISIBLE);
+ } else {
+ if (!menu.displayDistanceDirection()) {
+ compassView.setVisibility(View.GONE);
+ } else {
+ compassView.setVisibility(View.INVISIBLE);
+ }
+ }
+ }
+
+ private void updateDistanceDirection() {
+ TextView distanceText = (TextView) view.findViewById(R.id.distance);
+ ImageView direction = (ImageView) view.findViewById(R.id.direction);
+
+ float myHeading = menu.getHeading() == null ? 0f : menu.getHeading();
+ QuickSearchListAdapter.updateLocationView(false, menu.getMyLocation(), myHeading, direction, distanceText,
+ menu.getLatLon().getLatitude(), menu.getLatLon().getLongitude(), screenOrientation, getMyApplication(), getActivity());
+ }
+
+ private int getPosY() {
+ return getPosY(false);
+ }
+
+ private int getPosY(boolean needCloseMenu) {
+ if (needCloseMenu) {
+ return screenHeight;
+ }
+
+ int destinationState;
+ int minHalfY;
+ if (menu.isExtended()) {
+ destinationState = menu.getCurrentMenuState();
+ minHalfY = viewHeight - (int) (viewHeight * menu.getHalfScreenMaxHeightKoef());
+ } else {
+ destinationState = MenuState.HEADER_ONLY;
+ minHalfY = viewHeight;
+ }
+
+ int posY = 0;
+ switch (destinationState) {
+ case MenuState.HEADER_ONLY:
+ posY = viewHeight - menuTitleHeight;
+ break;
+ case MenuState.HALF_SCREEN:
+ posY = viewHeight - menuFullHeightMax;
+ posY = Math.max(posY, minHalfY);
+ break;
+ case MenuState.FULL_SCREEN:
+ posY = -menuTopShadowHeight - dpToPx(SHADOW_HEIGHT_TOP_DP);
+ break;
+ default:
+ break;
+ }
+ return posY;
+ }
+
+ private void updateMainViewLayout(int posY) {
+ menuFullHeight = view.getHeight() - posY;
+ if (!oldAndroid()) {
+ ViewGroup.LayoutParams lp = mainView.getLayoutParams();
+ lp.height = Math.max(menuFullHeight, menuTitleHeight);
+ mainView.setLayoutParams(lp);
+ mainView.requestLayout();
+ }
+ }
+
+ private int getViewY() {
+ if (!oldAndroid()) {
+ return (int) mainView.getY();
+ } else {
+ return mainView.getPaddingTop();
+ }
+ }
+
+ private void setViewY(int y, boolean animated, boolean adjustMapPos) {
+ if (!oldAndroid()) {
+ mainView.setY(y);
+ //fabView.setY(getFabY(y));
+ } else {
+ mainView.setPadding(0, y, 0, 0);
+ //fabView.setPadding(0, getFabY(y), 0, 0);
+ }
+ if (!customMapCenter) {
+ if (adjustMapPos) {
+ adjustMapPosition(y, animated, centered);
+ }
+ } else {
+ customMapCenter = false;
+ }
+ }
+
+ private void adjustMapPosition(int y, boolean animated, boolean center) {
+ //map.getAnimatedDraggingThread().stopAnimatingSync(); todo animation
+ LatLon latlon = getAdjustedMarkerLocation(y, menu.getLatLon(), center, getZoom());
+
+ LatLon mapLatLon = getMainActivity().getScreenCenter();
+ if (mapLatLon.getLatitude() == latlon.getLatitude() && mapLatLon.getLongitude() == latlon.getLongitude()) {
+ return;
+ }
+
+ if (animated) {
+ showOnMap(latlon, false, true, true);
+ } else {
+ PointI targetI = Utilities.convertLatLonTo31(
+ new net.osmand.core.jni.LatLon(latlon.getLatitude(), latlon.getLongitude()));
+ map.setTarget(targetI);
+ }
+ }
+
+ private LatLon getAdjustedMarkerLocation(int y, LatLon reqMarkerLocation, boolean center, int zoom) {
+ double markerLat = reqMarkerLocation.getLatitude();
+ double markerLon = reqMarkerLocation.getLongitude();
+ RotatedTileBox box = getBox();
+ //box.setCenterLocation(0.5f, map.getMapPosition() == OsmandSettings.BOTTOM_CONSTANT ? 0.15f : 0.5f);
+ box.setZoom(zoom);
+ int markerMapCenterX = (int) box.getPixXFromLatLon(mapCenter.getLatitude(), mapCenter.getLongitude());
+ int markerMapCenterY = (int) box.getPixYFromLatLon(mapCenter.getLatitude(), mapCenter.getLongitude());
+ float cpyOrig = box.getCenterPixelPoint().y;
+
+ box.setCenterLocation(0.5f, 0.5f);
+ int markerX = (int) box.getPixXFromLatLon(markerLat, markerLon);
+ int markerY = (int) box.getPixYFromLatLon(markerLat, markerLon);
+ QuadPoint cp = box.getCenterPixelPoint();
+ float cpx = cp.x;
+ float cpy = cp.y;
+
+ float cpyDelta = menu.isLandscapeLayout() ? 0 : cpyOrig - cpy;
+
+ markerY += cpyDelta;
+ y += cpyDelta;
+ float origMarkerY = this.origMarkerY + cpyDelta;
+
+ LatLon latlon;
+ if (center) {
+ latlon = reqMarkerLocation;
+ } else {
+ latlon = box.getLatLonFromPixel(markerMapCenterX, markerMapCenterY);
+ }
+ if (menu.isLandscapeLayout()) {
+ int x = menu.getLandscapeWidthPx();
+ if (markerX - markerPaddingXPx < x || markerX > origMarkerX) {
+ int dx = (x + markerPaddingXPx) - markerX;
+ int dy = 0;
+ if (center) {
+ dy = (int) cpy - markerY;
+ } else {
+ cpy = cpyOrig;
+ }
+ if (dx >= 0 || center) {
+ latlon = box.getLatLonFromPixel(cpx - dx, cpy - dy);
+ }
+ }
+ } else {
+ if (markerY + markerPaddingPx > y || markerY < origMarkerY) {
+ int dx = 0;
+ int dy = markerY - (y - markerPaddingPx);
+ if (markerY - dy <= origMarkerY) {
+ if (center) {
+ dx = markerX - (int) cpx;
+ }
+ latlon = box.getLatLonFromPixel(cpx + dx, cpy + dy);
+ }
+ }
+ }
+ return latlon;
+ }
+
+ private int getFabY(int y) {
+ int fabY = y + fabPaddingTopPx;
+ if (fabY < fabPaddingTopPx) {
+ fabY = fabPaddingTopPx;
+ }
+ return fabY;
+ }
+
+ private boolean oldAndroid() {
+ return (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH);
+ }
+
+ private void doLayoutMenu() {
+ final int posY = getPosY();
+ setViewY(posY, true, !initLayout || !centered);
+ updateMainViewLayout(posY);
+ }
+
+ public void dismissMenu() {
+ FragmentActivity activity = getActivity();
+ if (activity != null) {
+ try {
+ activity.getSupportFragmentManager().popBackStack(TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ }
+
+ public void refreshTitle() {
+ setAddressLocation();
+ runLayoutListener();
+ }
+
+ public void setFragmentVisibility(boolean visible) {
+ if (visible) {
+ view.setVisibility(View.VISIBLE);
+ if (mapCenter != null) {
+ PointI targetI = Utilities.convertLatLonTo31(
+ new net.osmand.core.jni.LatLon(mapCenter.getLatitude(), mapCenter.getLongitude()));
+ map.setTarget(targetI);
+ }
+ adjustMapPosition(getPosY(), true, false);
+ } else {
+ view.setVisibility(View.GONE);
+ }
+ }
+
+ public SampleApplication getMyApplication() {
+ if (getActivity() == null) {
+ return null;
+ }
+ return (SampleApplication) getActivity().getApplication();
+ }
+
+ public static boolean showInstance(final MapContextMenu menu, final MainActivity mainActivity,
+ final boolean centered) {
+ try {
+
+ if (menu.getLatLon() == null) {
+ return false;
+ }
+
+ int slideInAnim = R.anim.slide_in_bottom;
+ int slideOutAnim = R.anim.slide_out_bottom;
+
+ if (menu.isExtended()) {
+ slideInAnim = menu.getSlideInAnimation();
+ slideOutAnim = menu.getSlideOutAnimation();
+ }
+
+ MapContextMenuFragment fragment = new MapContextMenuFragment();
+ fragment.centered = centered;
+ mainActivity.getSupportFragmentManager().beginTransaction()
+ .setCustomAnimations(slideInAnim, slideOutAnim, slideInAnim, slideOutAnim)
+ .add(R.id.fragmentContainer, fragment, TAG)
+ .addToBackStack(TAG).commitAllowingStateLoss();
+
+ return true;
+
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ public void updateMenu() {
+ updateButtonsAndProgress();
+ runLayoutListener();
+ }
+
+ private MainActivity getMainActivity() {
+ return (MainActivity) getActivity();
+ }
+
+ private int dpToPx(float dp) {
+ Resources r = getActivity().getResources();
+ return (int) TypedValue.applyDimension(
+ COMPLEX_UNIT_DIP,
+ dp,
+ r.getDisplayMetrics()
+ );
+ }
+
+ public void updateLocation(boolean centerChanged, boolean locationChanged, boolean compassChanged) {
+ updateDistanceDirection();
+ }
+
+ private void doBeforeMenuStateChange(int previousState, int newState) {
+ }
+
+ private void doAfterMenuStateChange(int previousState, int newState) {
+ updateCompassVisibility();
+ }
+}
+
diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapMultiSelectionMenu.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapMultiSelectionMenu.java
new file mode 100644
index 0000000000..befe36b2f7
--- /dev/null
+++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/mapcontextmenu/MapMultiSelectionMenu.java
@@ -0,0 +1,165 @@
+package net.osmand.core.samples.android.sample1.mapcontextmenu;
+
+import android.support.annotation.NonNull;
+import android.support.v4.app.Fragment;
+
+import net.osmand.core.samples.android.sample1.MainActivity;
+import net.osmand.core.samples.android.sample1.data.PointDescription;
+import net.osmand.data.LatLon;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+
+public class MapMultiSelectionMenu extends BaseMenuController {
+
+ private LatLon latLon;
+ private LinkedList objects = new LinkedList<>();
+
+ public static class MenuObject extends MenuTitleController {
+
+ private LatLon latLon;
+ private PointDescription pointDescription;
+ private Object object;
+ private int order;
+
+ private MainActivity mainActivity;
+ private MenuController controller;
+
+ public MenuObject(LatLon latLon, PointDescription pointDescription, Object object, MainActivity mainActivity) {
+ this.latLon = latLon;
+ this.pointDescription = pointDescription;
+ this.object = object;
+ this.mainActivity = mainActivity;
+ init();
+ }
+
+ protected void init() {
+ controller = MenuController.getMenuController(mainActivity, latLon, pointDescription, object, MenuController.MenuType.MULTI_LINE);
+ controller.setActive(true);
+ initTitle();
+ }
+
+ @Override
+ public LatLon getLatLon() {
+ return latLon;
+ }
+
+ @Override
+ public PointDescription getPointDescription() {
+ return pointDescription;
+ }
+
+ @Override
+ public Object getObject() {
+ return object;
+ }
+
+ @Override
+ public MainActivity getMainActivity() {
+ return mainActivity;
+ }
+
+ @Override
+ public MenuController getMenuController() {
+ return controller;
+ }
+
+ @Override
+ protected boolean needStreetName() {
+ return false;
+ }
+ }
+
+ public MapMultiSelectionMenu(MainActivity mainActivity) {
+ super(mainActivity);
+ }
+
+ public void setMainActivity(MainActivity mainActivity) {
+ super.setMainActivity(mainActivity);
+ for (MenuObject o : objects) {
+ o.mainActivity = mainActivity;
+ o.init();
+ }
+ }
+
+ public List getObjects() {
+ return objects;
+ }
+
+ @Override
+ public float getHalfScreenMaxHeightKoef() {
+ return 0.5f;
+ }
+
+ private void createCollection(List