package net.osmand.plus.mapcontextmenu.builders.cards; import android.content.res.ColorStateList; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.support.annotation.NonNull; import android.support.v7.widget.AppCompatButton; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import net.osmand.AndroidNetworkUtils; import net.osmand.Location; import net.osmand.data.LatLon; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapillary.MapillaryContributeCard; import net.osmand.plus.mapillary.MapillaryImageCard; import net.osmand.util.Algorithms; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import static java.text.DateFormat.FULL; public abstract class ImageCard extends AbstractCard { private String type; // Image location private LatLon location; // (optional) Image's camera angle in range [0, 360]. private double ca = Double.NaN; // Date When bitmap was captured. private Date timestamp; // Image key. private String key; // User name private String userName; // Image viewer url private String url; // Image bitmap url private String imageUrl; // Image high resolution bitmap url private String imageHiresUrl; // true if external browser should to be opened, open webview otherwise private boolean externalLink; protected int topIconId; protected int buttonIconId; protected String buttonText; protected int buttonIconColor; protected int buttonColor; protected int buttonTextColor; private int defaultCardLayoutId = R.layout.context_menu_card_image; protected Drawable icon; protected Drawable buttonIcon; protected OnClickListener onClickListener; protected OnClickListener onButtonClickListener; private static final DateFormat DATE_FORMAT = SimpleDateFormat.getDateTimeInstance(FULL, FULL, Locale.US); //"yyyy-MM-dd'T'HH:mm:ss"); private boolean downloading; private boolean downloaded; private Bitmap bitmap; private float bearingDiff = Float.NaN; private float distance = Float.NaN; public ImageCard(MapActivity mapActivity, JSONObject imageObject) { super(mapActivity); try { if (imageObject.has("type")) { this.type = imageObject.getString("type"); } if (imageObject.has("ca") && !imageObject.isNull("ca")) { this.ca = imageObject.getDouble("ca"); } if (imageObject.has("lat") && imageObject.has("lon")) { double latitude = imageObject.getDouble("lat"); double longitude = imageObject.getDouble("lon"); this.location = new LatLon(latitude, longitude); } if (imageObject.has("timestamp")) { try { this.timestamp = DATE_FORMAT.parse(imageObject.getString("timestamp")); } catch (ParseException e) { e.printStackTrace(); } } if (imageObject.has("key")) { this.key = imageObject.getString("key"); } if (imageObject.has("username")) { this.userName = imageObject.getString("username"); } if (imageObject.has("url")) { this.url = imageObject.getString("url"); } if (imageObject.has("imageUrl")) { this.imageUrl = imageObject.getString("imageUrl"); } if (imageObject.has("imageHiresUrl")) { this.imageHiresUrl = imageObject.getString("imageHiresUrl"); } if (imageObject.has("externalLink") && !imageObject.isNull("externalLink")) { this.externalLink = imageObject.getBoolean("externalLink"); } if (imageObject.has("topIcon") && !imageObject.isNull("topIcon")) { this.topIconId = getDrawableId(imageObject.getString("topIcon")); } if (imageObject.has("buttonIcon") && !imageObject.isNull("buttonIcon")) { this.buttonIconId = getDrawableId(imageObject.getString("buttonIcon")); } if (imageObject.has("buttonText") && !imageObject.isNull("buttonText")) { this.buttonText = imageObject.getString("buttonText"); } if (imageObject.has("buttonIconColor") && !imageObject.isNull("buttonIconColor")) { try { this.buttonIconColor = Algorithms.parseColor(imageObject.getString("buttonIconColor")); } catch (IllegalArgumentException e) { e.printStackTrace(); } } if (imageObject.has("buttonColor") && !imageObject.isNull("buttonColor")) { try { this.buttonColor = Algorithms.parseColor(imageObject.getString("buttonColor")); } catch (IllegalArgumentException e) { e.printStackTrace(); } } if (imageObject.has("buttonTextColor") && !imageObject.isNull("buttonTextColor")) { try { this.buttonTextColor = Algorithms.parseColor(imageObject.getString("buttonTextColor")); } catch (IllegalArgumentException e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } } private int getDrawableId(String id) { if (Algorithms.isEmpty(id)) { return 0; } else { return getMyApplication().getResources().getIdentifier(id, "drawable", getMyApplication().getPackageName()); } } private static ImageCard createCard(MapActivity mapActivity, JSONObject imageObject) { ImageCard imageCard = null; try { if (imageObject.has("type")) { String type = imageObject.getString("type"); if ("mapillary-photo".equals(type)) { imageCard = new MapillaryImageCard(mapActivity, imageObject); } else if ("mapillary-contribute".equals(type)) { imageCard = new MapillaryContributeCard(mapActivity, imageObject); } else { imageCard = new UrlImageCard(mapActivity, imageObject); } } } catch (JSONException e) { e.printStackTrace(); } return imageCard; } public double getCa() { return ca; } public String getKey() { return key; } public String getType() { return type; } public LatLon getLocation() { return location; } public Date getTimestamp() { return timestamp; } public String getUserName() { return userName; } public String getUrl() { return url; } public String getImageUrl() { return imageUrl; } public String getImageHiresUrl() { return imageHiresUrl; } public boolean isExternalLink() { return externalLink; } public int getTopIconId() { return topIconId; } public int getButtonIconId() { return buttonIconId; } public String getButtonText() { return buttonText; } public int getButtonIconColor() { return buttonIconColor; } public int getButtonColor() { return buttonColor; } public int getButtonTextColor() { return buttonTextColor; } public int getDefaultCardLayoutId() { return defaultCardLayoutId; } @Override public int getCardLayoutId() { return defaultCardLayoutId; } public Drawable getIcon() { return icon; } public OnClickListener getOnClickListener() { return onClickListener; } public boolean isDownloading() { return downloading; } public void setDownloading(boolean downloading) { this.downloading = downloading; } public Bitmap getBitmap() { return bitmap; } public void setBitmap(Bitmap bitmap) { this.bitmap = bitmap; } public float getBearingDiff() { return bearingDiff; } public void setBearingDiff(float bearingDiff) { this.bearingDiff = bearingDiff; } public float getDistance() { return distance; } public void setDistance(float distance) { this.distance = distance; } public void update() { if (view != null) { ImageView image = (ImageView) view.findViewById(R.id.image); ImageView iconImageView = (ImageView) view.findViewById(R.id.icon); TextView watermarkTextView = (TextView) view.findViewById(R.id.watermark); ProgressBar progress = (ProgressBar) view.findViewById(R.id.progress); AppCompatButton button = (AppCompatButton) view.findViewById(R.id.button); if (icon == null && topIconId != 0) { icon = getMyApplication().getIconsCache().getIcon(topIconId); } if (icon == null) { iconImageView.setVisibility(View.GONE); } else { iconImageView.setImageDrawable(icon); iconImageView.setVisibility(View.VISIBLE); } if (Algorithms.isEmpty(userName)) { watermarkTextView.setVisibility(View.GONE); } else { watermarkTextView.setText("@" + userName); watermarkTextView.setVisibility(View.VISIBLE); } if (downloading) { progress.setVisibility(View.VISIBLE); image.setImageBitmap(null); } else if (!downloaded) { MenuBuilder.execute(new DownloadImageTask()); } else { progress.setVisibility(View.GONE); image.setImageBitmap(bitmap); } if (onClickListener != null) { view.findViewById(R.id.image_card).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onClickListener.onClick(v); } }); } else { view.findViewById(R.id.image_card).setOnClickListener(null); } if (!Algorithms.isEmpty(buttonText)) { button.setText(buttonText); } if (buttonIcon == null && buttonIconId != 0) { if (buttonIconColor != 0) { buttonIcon = getMyApplication().getIconsCache().getPaintedIcon(buttonIconId, buttonIconColor); } else { buttonIcon = getMyApplication().getIconsCache().getIcon(buttonIconId); } } button.setCompoundDrawablesWithIntrinsicBounds(buttonIcon, null, null, null); if (buttonColor != 0) { button.setSupportBackgroundTintList(ColorStateList.valueOf(buttonColor)); } if (buttonTextColor != 0) { button.setTextColor(buttonTextColor); } if (onButtonClickListener != null) { button.setVisibility(View.VISIBLE); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onButtonClickListener.onClick(v); } }); } else { button.setVisibility(View.GONE); button.setOnClickListener(null); } } } public static class GetImageCardsTask extends AsyncTask<Void, Void, List<ImageCard>> { private MapActivity mapActivity; private OsmandApplication app; private LatLon latLon; private GetImageCardsListener listener; private List<ImageCard> result; public interface GetImageCardsListener { void onFinish(List<ImageCard> cardList); } public GetImageCardsTask(@NonNull MapActivity mapActivity, LatLon latLon, GetImageCardsListener listener) { this.mapActivity = mapActivity; this.app = mapActivity.getMyApplication(); this.latLon = latLon; this.listener = listener; } @Override protected List<ImageCard> doInBackground(Void... params) { List<ImageCard> result = new ArrayList<>(); try { final Map<String, String> pms = new LinkedHashMap<>(); pms.put("lat", "" + latLon.getLatitude()); pms.put("lon", "" + latLon.getLongitude()); Location myLocation = app.getLocationProvider().getLastKnownLocation(); if (myLocation != null) { pms.put("myLocation", "" + myLocation.getLatitude() + "," + myLocation.getLongitude()); } pms.put("app", Version.isPaidVersion(app) ? "paid" : "free"); String preferredLang = app.getSettings().MAP_PREFERRED_LOCALE.get(); if (Algorithms.isEmpty(preferredLang)) { preferredLang = app.getLanguage(); } if (!Algorithms.isEmpty(preferredLang)) { pms.put("lang", preferredLang); } String response = AndroidNetworkUtils.sendRequest(app, "http://osmand.net/api/cm_place.php", pms, "Requesting location images...", false, false); if (!Algorithms.isEmpty(response)) { JSONObject obj = new JSONObject(response); JSONArray images = obj.getJSONArray("features"); if (images.length() > 0) { for (int i = 0; i < images.length(); i++) { try { JSONObject imageObject = (JSONObject) images.get(i); if (imageObject != JSONObject.NULL) { ImageCard imageCard = ImageCard.createCard(mapActivity, imageObject); if (imageCard != null) { result.add(imageCard); } } } catch (JSONException e) { e.printStackTrace(); } } } } } catch (Exception e) { e.printStackTrace(); } return result; } @Override protected void onPostExecute(List<ImageCard> cardList) { result = cardList; if (listener != null) { listener.onFinish(result); } } } private class DownloadImageTask extends AsyncTask<Void, Void, Bitmap> { @Override protected void onPreExecute() { downloading = true; update(); } @Override protected Bitmap doInBackground(Void... params) { return AndroidNetworkUtils.downloadImage(getMyApplication(), imageUrl); } @Override protected void onPostExecute(Bitmap bitmap) { downloading = false; downloaded = true; ImageCard.this.bitmap = bitmap; update(); } } }