/*
* Copyright (C) 2015 Baidu, Inc. All Rights Reserved.
*/
package com.wdkj.housemanager.view;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.util.SparseArray;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
//import com.baidu.mapapi.clusterutil.MarkerManager;
//import com.baidu.mapapi.clusterutil.clustering.Cluster;
//import com.baidu.mapapi.clusterutil.clustering.ClusterItem;
//import com.baidu.mapapi.clusterutil.clustering.ClusterManager;
//import com.baidu.mapapi.clusterutil.projection.Point;
//import com.baidu.mapapi.clusterutil.projection.SphericalMercatorProjection;
//import com.baidu.mapapi.clusterutil.ui.IconGenerator;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.Projection;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;
import com.wdkj.housemanager.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static com.wdkj.housemanager.view.NonHierarchicalDistanceBasedAlgorithm.MAX_DISTANCE_AT_ZOOM;
/**
* The default view for a ClusterManager. Markers are animated in and out of clusters.
*/
public class DefaultClusterRenderer<T extends ClusterItem> implements
com.wdkj.housemanager.view.ClusterRenderer<T> {
private static final boolean SHOULD_ANIMATE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
private final BaiduMap mMap;
private final IconGenerator mIconGenerator;
private final ClusterManager<T> mClusterManager;
private final float mDensity;
private static final int[] BUCKETS = {10, 20, 50, 100, 200, 500, 1000};
private ShapeDrawable mColoredCircleBackground;
/**
* Markers that are currently on the map.
*/
private Set<MarkerWithPosition> mMarkers = Collections.newSetFromMap(
new ConcurrentHashMap<MarkerWithPosition, Boolean>());
/**
* Icons for each bucket.
*/
private SparseArray<BitmapDescriptor> mIcons = new SparseArray<BitmapDescriptor>();
/**
* Markers for single ClusterItems.
*/
private MarkerCache<T> mMarkerCache = new MarkerCache<T>();
/**
* If cluster size is less than this size, display individual markers.
*/
private static final int MIN_CLUSTER_SIZE = 4;
/**
* The currently displayed set of clusters.
*/
private Set<? extends Cluster<T>> mClusters;
/**
* Lookup between markers and the associated cluster.
*/
private Map<Marker, Cluster<T>> mMarkerToCluster = new HashMap<Marker, Cluster<T>>();
private Map<Cluster<T>, Marker> mClusterToMarker = new HashMap<Cluster<T>, Marker>();
/**
* The target zoom level for the current set of clusters.
*/
private float mZoom;
private final ViewModifier mViewModifier = new ViewModifier();
private ClusterManager.OnClusterClickListener<T> mClickListener;
private ClusterManager.OnClusterInfoWindowClickListener<T> mInfoWindowClickListener;
private ClusterManager.OnClusterItemClickListener<T> mItemClickListener;
private ClusterManager.OnClusterItemInfoWindowClickListener<T> mItemInfoWindowClickListener;
public DefaultClusterRenderer(Context context, BaiduMap map, ClusterManager<T> clusterManager) {
mMap = map;
mDensity = context.getResources().getDisplayMetrics().density;
mIconGenerator = new IconGenerator(context);
mIconGenerator.setContentView(makeSquareTextView(context));
mIconGenerator.setTextAppearance(R.style.ClusterIcon_TextAppearance);
mIconGenerator.setBackground(makeClusterBackground());
mClusterManager = clusterManager;
}
@Override
public void onAdd() {
mClusterManager.getMarkerCollection().setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
return mItemClickListener != null && mItemClickListener.onClusterItemClick(mMarkerCache.get(marker));
}
});
mClusterManager.getClusterMarkerCollection().setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
return mClickListener != null && mClickListener.onClusterClick(mMarkerToCluster.get(marker));
}
});
}
@Override
public void onRemove() {
mClusterManager.getMarkerCollection().setOnMarkerClickListener(null);
mClusterManager.getClusterMarkerCollection().setOnMarkerClickListener(null);
}
private LayerDrawable makeClusterBackground() {
mColoredCircleBackground = new ShapeDrawable(new OvalShape());
ShapeDrawable outline = new ShapeDrawable(new OvalShape());
outline.getPaint().setColor(0x80ffffff); // Transparent white.
LayerDrawable background = new LayerDrawable(new Drawable[]{outline, mColoredCircleBackground});
int strokeWidth = (int) (mDensity * 3);
background.setLayerInset(1, strokeWidth, strokeWidth, strokeWidth, strokeWidth);
return background;
}
private com.wdkj.housemanager.view.SquareTextView makeSquareTextView(Context context) {
com.wdkj.housemanager.view.SquareTextView squareTextView =
new com.wdkj.housemanager.view.SquareTextView(context);
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
squareTextView.setLayoutParams(layoutParams);
squareTextView.setId(R.id.text);
int twelveDpi = (int) (12 * mDensity);
squareTextView.setPadding(twelveDpi, twelveDpi, twelveDpi, twelveDpi);
return squareTextView;
}
private int getColor(int clusterSize) {
final float hueRange = 220;
final float sizeRange = 300;
final float size = Math.min(clusterSize, sizeRange);
final float hue = (sizeRange - size) * (sizeRange - size) / (sizeRange * sizeRange) * hueRange;
return Color.HSVToColor(new float[]{
hue, 1f, .6f
});
}
protected String getClusterText(int bucket) {
if (bucket < BUCKETS[0]) {
return String.valueOf(bucket);
}
return String.valueOf(bucket) + "+";
}
/**
* Gets the "bucket" for a particular cluster. By default, uses the number of points within the
* cluster, bucketed to some set points.
*/
protected int getBucket(Cluster<T> cluster) {
int size = cluster.getSize();
if (size <= BUCKETS[0]) {
return size;
}
for (int i = 0; i < BUCKETS.length - 1; i++) {
if (size < BUCKETS[i + 1]) {
return BUCKETS[i];
}
}
return BUCKETS[BUCKETS.length - 1];
}
/**
* ViewModifier ensures only one