Initial version -- added millennium read funcionality
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.google.maps.android.clustering;
|
||||
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import java.util.Collection;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public interface Cluster<T extends ClusterItem> {
|
||||
Collection<T> getItems();
|
||||
|
||||
LatLng getPosition();
|
||||
|
||||
int getSize();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.google.maps.android.clustering;
|
||||
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public interface ClusterItem {
|
||||
LatLng getPosition();
|
||||
|
||||
String getSnippet();
|
||||
|
||||
String getTitle();
|
||||
|
||||
Float getZIndex();
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
package com.google.maps.android.clustering;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
import com.google.android.gms.maps.model.CameraPosition;
|
||||
import com.google.android.gms.maps.model.Marker;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import com.google.maps.android.clustering.algo.Algorithm;
|
||||
import com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm;
|
||||
import com.google.maps.android.clustering.algo.PreCachingAlgorithmDecorator;
|
||||
import com.google.maps.android.clustering.algo.ScreenBasedAlgorithm;
|
||||
import com.google.maps.android.clustering.algo.ScreenBasedAlgorithmAdapter;
|
||||
import com.google.maps.android.clustering.view.ClusterRenderer;
|
||||
import com.google.maps.android.clustering.view.DefaultClusterRenderer;
|
||||
import com.google.maps.android.collections.MarkerManager;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class ClusterManager<T extends ClusterItem> implements GoogleMap.OnCameraIdleListener, GoogleMap.OnMarkerClickListener, GoogleMap.OnInfoWindowClickListener {
|
||||
private ScreenBasedAlgorithm<T> mAlgorithm;
|
||||
private final MarkerManager.Collection mClusterMarkers;
|
||||
private ClusterManager<T>.ClusterTask mClusterTask;
|
||||
private final ReadWriteLock mClusterTaskLock;
|
||||
private GoogleMap mMap;
|
||||
private final MarkerManager mMarkerManager;
|
||||
private final MarkerManager.Collection mMarkers;
|
||||
private OnClusterClickListener<T> mOnClusterClickListener;
|
||||
private OnClusterInfoWindowClickListener<T> mOnClusterInfoWindowClickListener;
|
||||
private OnClusterInfoWindowLongClickListener<T> mOnClusterInfoWindowLongClickListener;
|
||||
private OnClusterItemClickListener<T> mOnClusterItemClickListener;
|
||||
private OnClusterItemInfoWindowClickListener<T> mOnClusterItemInfoWindowClickListener;
|
||||
private OnClusterItemInfoWindowLongClickListener<T> mOnClusterItemInfoWindowLongClickListener;
|
||||
private CameraPosition mPreviousCameraPosition;
|
||||
private ClusterRenderer<T> mRenderer;
|
||||
|
||||
public interface OnClusterClickListener<T extends ClusterItem> {
|
||||
boolean onClusterClick(Cluster<T> cluster);
|
||||
}
|
||||
|
||||
public interface OnClusterInfoWindowClickListener<T extends ClusterItem> {
|
||||
void onClusterInfoWindowClick(Cluster<T> cluster);
|
||||
}
|
||||
|
||||
public interface OnClusterInfoWindowLongClickListener<T extends ClusterItem> {
|
||||
void onClusterInfoWindowLongClick(Cluster<T> cluster);
|
||||
}
|
||||
|
||||
public interface OnClusterItemClickListener<T extends ClusterItem> {
|
||||
boolean onClusterItemClick(T t);
|
||||
}
|
||||
|
||||
public interface OnClusterItemInfoWindowClickListener<T extends ClusterItem> {
|
||||
void onClusterItemInfoWindowClick(T t);
|
||||
}
|
||||
|
||||
public interface OnClusterItemInfoWindowLongClickListener<T extends ClusterItem> {
|
||||
void onClusterItemInfoWindowLongClick(T t);
|
||||
}
|
||||
|
||||
public ClusterManager(Context context, GoogleMap googleMap) {
|
||||
this(context, googleMap, new MarkerManager(googleMap));
|
||||
}
|
||||
|
||||
public ClusterManager(Context context, GoogleMap googleMap, MarkerManager markerManager) {
|
||||
this.mClusterTaskLock = new ReentrantReadWriteLock();
|
||||
this.mMap = googleMap;
|
||||
this.mMarkerManager = markerManager;
|
||||
this.mClusterMarkers = markerManager.newCollection();
|
||||
this.mMarkers = markerManager.newCollection();
|
||||
this.mRenderer = new DefaultClusterRenderer(context, googleMap, this);
|
||||
this.mAlgorithm = new ScreenBasedAlgorithmAdapter(new PreCachingAlgorithmDecorator(new NonHierarchicalDistanceBasedAlgorithm()));
|
||||
this.mClusterTask = new ClusterTask();
|
||||
this.mRenderer.onAdd();
|
||||
}
|
||||
|
||||
public MarkerManager.Collection getMarkerCollection() {
|
||||
return this.mMarkers;
|
||||
}
|
||||
|
||||
public MarkerManager.Collection getClusterMarkerCollection() {
|
||||
return this.mClusterMarkers;
|
||||
}
|
||||
|
||||
public MarkerManager getMarkerManager() {
|
||||
return this.mMarkerManager;
|
||||
}
|
||||
|
||||
public void setRenderer(ClusterRenderer<T> clusterRenderer) {
|
||||
this.mRenderer.setOnClusterClickListener(null);
|
||||
this.mRenderer.setOnClusterItemClickListener(null);
|
||||
this.mClusterMarkers.clear();
|
||||
this.mMarkers.clear();
|
||||
this.mRenderer.onRemove();
|
||||
this.mRenderer = clusterRenderer;
|
||||
clusterRenderer.onAdd();
|
||||
this.mRenderer.setOnClusterClickListener(this.mOnClusterClickListener);
|
||||
this.mRenderer.setOnClusterInfoWindowClickListener(this.mOnClusterInfoWindowClickListener);
|
||||
this.mRenderer.setOnClusterInfoWindowLongClickListener(this.mOnClusterInfoWindowLongClickListener);
|
||||
this.mRenderer.setOnClusterItemClickListener(this.mOnClusterItemClickListener);
|
||||
this.mRenderer.setOnClusterItemInfoWindowClickListener(this.mOnClusterItemInfoWindowClickListener);
|
||||
this.mRenderer.setOnClusterItemInfoWindowLongClickListener(this.mOnClusterItemInfoWindowLongClickListener);
|
||||
cluster();
|
||||
}
|
||||
|
||||
public void setAlgorithm(Algorithm<T> algorithm) {
|
||||
if (algorithm instanceof ScreenBasedAlgorithm) {
|
||||
setAlgorithm((ScreenBasedAlgorithm) algorithm);
|
||||
} else {
|
||||
setAlgorithm((ScreenBasedAlgorithm) new ScreenBasedAlgorithmAdapter(algorithm));
|
||||
}
|
||||
}
|
||||
|
||||
public void setAlgorithm(ScreenBasedAlgorithm<T> screenBasedAlgorithm) {
|
||||
screenBasedAlgorithm.lock();
|
||||
try {
|
||||
Algorithm<T> algorithm = getAlgorithm();
|
||||
this.mAlgorithm = screenBasedAlgorithm;
|
||||
if (algorithm != null) {
|
||||
algorithm.lock();
|
||||
try {
|
||||
screenBasedAlgorithm.addItems(algorithm.getItems());
|
||||
algorithm.unlock();
|
||||
} catch (Throwable th) {
|
||||
algorithm.unlock();
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
screenBasedAlgorithm.unlock();
|
||||
if (this.mAlgorithm.shouldReclusterOnMapMovement()) {
|
||||
this.mAlgorithm.onCameraChange(this.mMap.getCameraPosition());
|
||||
}
|
||||
cluster();
|
||||
} catch (Throwable th2) {
|
||||
screenBasedAlgorithm.unlock();
|
||||
throw th2;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimation(boolean z) {
|
||||
this.mRenderer.setAnimation(z);
|
||||
}
|
||||
|
||||
public ClusterRenderer<T> getRenderer() {
|
||||
return this.mRenderer;
|
||||
}
|
||||
|
||||
public Algorithm<T> getAlgorithm() {
|
||||
return this.mAlgorithm;
|
||||
}
|
||||
|
||||
public void clearItems() {
|
||||
Algorithm<T> algorithm = getAlgorithm();
|
||||
algorithm.lock();
|
||||
try {
|
||||
algorithm.clearItems();
|
||||
} finally {
|
||||
algorithm.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addItems(Collection<T> collection) {
|
||||
Algorithm<T> algorithm = getAlgorithm();
|
||||
algorithm.lock();
|
||||
try {
|
||||
return algorithm.addItems(collection);
|
||||
} finally {
|
||||
algorithm.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addItem(T t) {
|
||||
Algorithm<T> algorithm = getAlgorithm();
|
||||
algorithm.lock();
|
||||
try {
|
||||
return algorithm.addItem(t);
|
||||
} finally {
|
||||
algorithm.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeItems(Collection<T> collection) {
|
||||
Algorithm<T> algorithm = getAlgorithm();
|
||||
algorithm.lock();
|
||||
try {
|
||||
return algorithm.removeItems(collection);
|
||||
} finally {
|
||||
algorithm.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeItem(T t) {
|
||||
Algorithm<T> algorithm = getAlgorithm();
|
||||
algorithm.lock();
|
||||
try {
|
||||
return algorithm.removeItem(t);
|
||||
} finally {
|
||||
algorithm.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateItem(T t) {
|
||||
Algorithm<T> algorithm = getAlgorithm();
|
||||
algorithm.lock();
|
||||
try {
|
||||
return algorithm.updateItem(t);
|
||||
} finally {
|
||||
algorithm.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void cluster() {
|
||||
this.mClusterTaskLock.writeLock().lock();
|
||||
try {
|
||||
this.mClusterTask.cancel(true);
|
||||
ClusterManager<T>.ClusterTask clusterTask = new ClusterTask();
|
||||
this.mClusterTask = clusterTask;
|
||||
clusterTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Float.valueOf(this.mMap.getCameraPosition().zoom));
|
||||
} finally {
|
||||
this.mClusterTaskLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnCameraIdleListener
|
||||
public void onCameraIdle() {
|
||||
ClusterRenderer<T> clusterRenderer = this.mRenderer;
|
||||
if (clusterRenderer instanceof GoogleMap.OnCameraIdleListener) {
|
||||
((GoogleMap.OnCameraIdleListener) clusterRenderer).onCameraIdle();
|
||||
}
|
||||
this.mAlgorithm.onCameraChange(this.mMap.getCameraPosition());
|
||||
if (this.mAlgorithm.shouldReclusterOnMapMovement()) {
|
||||
cluster();
|
||||
return;
|
||||
}
|
||||
CameraPosition cameraPosition = this.mPreviousCameraPosition;
|
||||
if (cameraPosition == null || cameraPosition.zoom != this.mMap.getCameraPosition().zoom) {
|
||||
this.mPreviousCameraPosition = this.mMap.getCameraPosition();
|
||||
cluster();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnMarkerClickListener
|
||||
public boolean onMarkerClick(Marker marker) {
|
||||
return getMarkerManager().onMarkerClick(marker);
|
||||
}
|
||||
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener
|
||||
public void onInfoWindowClick(Marker marker) {
|
||||
getMarkerManager().onInfoWindowClick(marker);
|
||||
}
|
||||
|
||||
private class ClusterTask extends AsyncTask<Float, Void, Set<? extends Cluster<T>>> {
|
||||
private ClusterTask() {
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: protected */
|
||||
@Override // android.os.AsyncTask
|
||||
public Set<? extends Cluster<T>> doInBackground(Float... fArr) {
|
||||
Algorithm<T> algorithm = ClusterManager.this.getAlgorithm();
|
||||
algorithm.lock();
|
||||
try {
|
||||
return algorithm.getClusters(fArr[0].floatValue());
|
||||
} finally {
|
||||
algorithm.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: protected */
|
||||
@Override // android.os.AsyncTask
|
||||
public void onPostExecute(Set<? extends Cluster<T>> set) {
|
||||
ClusterManager.this.mRenderer.onClustersChanged(set);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnClusterClickListener(OnClusterClickListener<T> onClusterClickListener) {
|
||||
this.mOnClusterClickListener = onClusterClickListener;
|
||||
this.mRenderer.setOnClusterClickListener(onClusterClickListener);
|
||||
}
|
||||
|
||||
public void setOnClusterInfoWindowClickListener(OnClusterInfoWindowClickListener<T> onClusterInfoWindowClickListener) {
|
||||
this.mOnClusterInfoWindowClickListener = onClusterInfoWindowClickListener;
|
||||
this.mRenderer.setOnClusterInfoWindowClickListener(onClusterInfoWindowClickListener);
|
||||
}
|
||||
|
||||
public void setOnClusterInfoWindowLongClickListener(OnClusterInfoWindowLongClickListener<T> onClusterInfoWindowLongClickListener) {
|
||||
this.mOnClusterInfoWindowLongClickListener = onClusterInfoWindowLongClickListener;
|
||||
this.mRenderer.setOnClusterInfoWindowLongClickListener(onClusterInfoWindowLongClickListener);
|
||||
}
|
||||
|
||||
public void setOnClusterItemClickListener(OnClusterItemClickListener<T> onClusterItemClickListener) {
|
||||
this.mOnClusterItemClickListener = onClusterItemClickListener;
|
||||
this.mRenderer.setOnClusterItemClickListener(onClusterItemClickListener);
|
||||
}
|
||||
|
||||
public void setOnClusterItemInfoWindowClickListener(OnClusterItemInfoWindowClickListener<T> onClusterItemInfoWindowClickListener) {
|
||||
this.mOnClusterItemInfoWindowClickListener = onClusterItemInfoWindowClickListener;
|
||||
this.mRenderer.setOnClusterItemInfoWindowClickListener(onClusterItemInfoWindowClickListener);
|
||||
}
|
||||
|
||||
public void setOnClusterItemInfoWindowLongClickListener(OnClusterItemInfoWindowLongClickListener<T> onClusterItemInfoWindowLongClickListener) {
|
||||
this.mOnClusterItemInfoWindowLongClickListener = onClusterItemInfoWindowLongClickListener;
|
||||
this.mRenderer.setOnClusterItemInfoWindowLongClickListener(onClusterItemInfoWindowLongClickListener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public abstract class AbstractAlgorithm<T extends ClusterItem> implements Algorithm<T> {
|
||||
private final ReadWriteLock mLock = new ReentrantReadWriteLock();
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void lock() {
|
||||
this.mLock.writeLock().lock();
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void unlock() {
|
||||
this.mLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public interface Algorithm<T extends ClusterItem> {
|
||||
boolean addItem(T t);
|
||||
|
||||
boolean addItems(Collection<T> collection);
|
||||
|
||||
void clearItems();
|
||||
|
||||
Set<? extends Cluster<T>> getClusters(float f);
|
||||
|
||||
Collection<T> getItems();
|
||||
|
||||
int getMaxDistanceBetweenClusteredItems();
|
||||
|
||||
void lock();
|
||||
|
||||
boolean removeItem(T t);
|
||||
|
||||
boolean removeItems(Collection<T> collection);
|
||||
|
||||
void setMaxDistanceBetweenClusteredItems(int i);
|
||||
|
||||
void unlock();
|
||||
|
||||
boolean updateItem(T t);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import androidx.collection.LongSparseArray;
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import com.google.maps.android.projection.Point;
|
||||
import com.google.maps.android.projection.SphericalMercatorProjection;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class GridBasedAlgorithm<T extends ClusterItem> extends AbstractAlgorithm<T> {
|
||||
private static final int DEFAULT_GRID_SIZE = 100;
|
||||
private int mGridSize = 100;
|
||||
private final Set<T> mItems = Collections.synchronizedSet(new HashSet());
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean addItem(T t) {
|
||||
return this.mItems.add(t);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean addItems(Collection<T> collection) {
|
||||
return this.mItems.addAll(collection);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void clearItems() {
|
||||
this.mItems.clear();
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean removeItem(T t) {
|
||||
return this.mItems.remove(t);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean removeItems(Collection<T> collection) {
|
||||
return this.mItems.removeAll(collection);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean updateItem(T t) {
|
||||
boolean zRemoveItem;
|
||||
synchronized (this.mItems) {
|
||||
zRemoveItem = removeItem(t);
|
||||
if (zRemoveItem) {
|
||||
zRemoveItem = addItem(t);
|
||||
}
|
||||
}
|
||||
return zRemoveItem;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void setMaxDistanceBetweenClusteredItems(int i) {
|
||||
this.mGridSize = i;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public int getMaxDistanceBetweenClusteredItems() {
|
||||
return this.mGridSize;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public Set<? extends Cluster<T>> getClusters(float f) {
|
||||
long j;
|
||||
long jCeil = (long) Math.ceil((Math.pow(2.0d, f) * 256.0d) / ((double) this.mGridSize));
|
||||
SphericalMercatorProjection sphericalMercatorProjection = new SphericalMercatorProjection(jCeil);
|
||||
HashSet hashSet = new HashSet();
|
||||
LongSparseArray longSparseArray = new LongSparseArray();
|
||||
synchronized (this.mItems) {
|
||||
for (T t : this.mItems) {
|
||||
Point point = sphericalMercatorProjection.toPoint(t.getPosition());
|
||||
long coord = getCoord(jCeil, point.x, point.y);
|
||||
StaticCluster staticCluster = (StaticCluster) longSparseArray.get(coord);
|
||||
if (staticCluster == null) {
|
||||
j = jCeil;
|
||||
staticCluster = new StaticCluster(sphericalMercatorProjection.toLatLng(new com.google.maps.android.geometry.Point(Math.floor(point.x) + 0.5d, Math.floor(point.y) + 0.5d)));
|
||||
longSparseArray.put(coord, staticCluster);
|
||||
hashSet.add(staticCluster);
|
||||
} else {
|
||||
j = jCeil;
|
||||
}
|
||||
staticCluster.add(t);
|
||||
jCeil = j;
|
||||
}
|
||||
}
|
||||
return hashSet;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public Collection<T> getItems() {
|
||||
return this.mItems;
|
||||
}
|
||||
|
||||
private static long getCoord(long j, double d, double d2) {
|
||||
return (long) ((j * Math.floor(d)) + Math.floor(d2));
|
||||
}
|
||||
}
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import com.google.maps.android.geometry.Bounds;
|
||||
import com.google.maps.android.geometry.Point;
|
||||
import com.google.maps.android.projection.SphericalMercatorProjection;
|
||||
import com.google.maps.android.quadtree.PointQuadTree;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class NonHierarchicalDistanceBasedAlgorithm<T extends ClusterItem> extends AbstractAlgorithm<T> {
|
||||
private static final int DEFAULT_MAX_DISTANCE_AT_ZOOM = 100;
|
||||
private static final SphericalMercatorProjection PROJECTION = new SphericalMercatorProjection(1.0d);
|
||||
private int mMaxDistance = 100;
|
||||
private final Collection<QuadItem<T>> mItems = new LinkedHashSet();
|
||||
private final PointQuadTree<QuadItem<T>> mQuadTree = new PointQuadTree<>(0.0d, 1.0d, 0.0d, 1.0d);
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean addItem(T t) {
|
||||
boolean zAdd;
|
||||
QuadItem<T> quadItem = new QuadItem<>(t);
|
||||
synchronized (this.mQuadTree) {
|
||||
zAdd = this.mItems.add(quadItem);
|
||||
if (zAdd) {
|
||||
this.mQuadTree.add(quadItem);
|
||||
}
|
||||
}
|
||||
return zAdd;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean addItems(Collection<T> collection) {
|
||||
Iterator<T> it = collection.iterator();
|
||||
boolean z = false;
|
||||
while (it.hasNext()) {
|
||||
if (addItem(it.next())) {
|
||||
z = true;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void clearItems() {
|
||||
synchronized (this.mQuadTree) {
|
||||
this.mItems.clear();
|
||||
this.mQuadTree.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean removeItem(T t) {
|
||||
boolean zRemove;
|
||||
QuadItem quadItem = new QuadItem(t);
|
||||
synchronized (this.mQuadTree) {
|
||||
zRemove = this.mItems.remove(quadItem);
|
||||
if (zRemove) {
|
||||
this.mQuadTree.remove(quadItem);
|
||||
}
|
||||
}
|
||||
return zRemove;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean removeItems(Collection<T> collection) {
|
||||
boolean z;
|
||||
synchronized (this.mQuadTree) {
|
||||
Iterator<T> it = collection.iterator();
|
||||
z = false;
|
||||
while (it.hasNext()) {
|
||||
QuadItem quadItem = new QuadItem(it.next());
|
||||
if (this.mItems.remove(quadItem)) {
|
||||
this.mQuadTree.remove(quadItem);
|
||||
z = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean updateItem(T t) {
|
||||
boolean zRemoveItem;
|
||||
synchronized (this.mQuadTree) {
|
||||
zRemoveItem = removeItem(t);
|
||||
if (zRemoveItem) {
|
||||
zRemoveItem = addItem(t);
|
||||
}
|
||||
}
|
||||
return zRemoveItem;
|
||||
}
|
||||
|
||||
/* JADX WARN: Multi-variable type inference failed */
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public Set<? extends Cluster<T>> getClusters(float f) {
|
||||
double dPow = (((double) this.mMaxDistance) / Math.pow(2.0d, (int) f)) / 256.0d;
|
||||
HashSet hashSet = new HashSet();
|
||||
HashSet hashSet2 = new HashSet();
|
||||
HashMap map = new HashMap();
|
||||
HashMap map2 = new HashMap();
|
||||
synchronized (this.mQuadTree) {
|
||||
Iterator<QuadItem<T>> it = getClusteringItems(this.mQuadTree, f).iterator();
|
||||
while (it.hasNext()) {
|
||||
QuadItem<T> next = it.next();
|
||||
if (!hashSet.contains(next)) {
|
||||
Collection<T> collectionSearch = this.mQuadTree.search(createBoundsFromSpan(next.getPoint(), dPow));
|
||||
if (collectionSearch.size() == 1) {
|
||||
hashSet2.add(next);
|
||||
hashSet.add(next);
|
||||
map.put(next, Double.valueOf(0.0d));
|
||||
} else {
|
||||
StaticCluster staticCluster = new StaticCluster(((QuadItem) next).mClusterItem.getPosition());
|
||||
hashSet2.add(staticCluster);
|
||||
for (T t : collectionSearch) {
|
||||
Double d = (Double) map.get(t);
|
||||
Iterator<QuadItem<T>> it2 = it;
|
||||
double dDistanceSquared = distanceSquared(t.getPoint(), next.getPoint());
|
||||
if (d == null) {
|
||||
map.put(t, Double.valueOf(dDistanceSquared));
|
||||
staticCluster.add(t.mClusterItem);
|
||||
map2.put(t, staticCluster);
|
||||
} else if (d.doubleValue() >= dDistanceSquared) {
|
||||
((StaticCluster) map2.get(t)).remove(t.mClusterItem);
|
||||
map.put(t, Double.valueOf(dDistanceSquared));
|
||||
staticCluster.add(t.mClusterItem);
|
||||
map2.put(t, staticCluster);
|
||||
}
|
||||
it = it2;
|
||||
}
|
||||
hashSet.addAll(collectionSearch);
|
||||
it = it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hashSet2;
|
||||
}
|
||||
|
||||
protected Collection<QuadItem<T>> getClusteringItems(PointQuadTree<QuadItem<T>> pointQuadTree, float f) {
|
||||
return this.mItems;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public Collection<T> getItems() {
|
||||
LinkedHashSet linkedHashSet = new LinkedHashSet();
|
||||
synchronized (this.mQuadTree) {
|
||||
Iterator<QuadItem<T>> it = this.mItems.iterator();
|
||||
while (it.hasNext()) {
|
||||
linkedHashSet.add(((QuadItem) it.next()).mClusterItem);
|
||||
}
|
||||
}
|
||||
return linkedHashSet;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void setMaxDistanceBetweenClusteredItems(int i) {
|
||||
this.mMaxDistance = i;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public int getMaxDistanceBetweenClusteredItems() {
|
||||
return this.mMaxDistance;
|
||||
}
|
||||
|
||||
private double distanceSquared(Point point, Point point2) {
|
||||
return ((point.x - point2.x) * (point.x - point2.x)) + ((point.y - point2.y) * (point.y - point2.y));
|
||||
}
|
||||
|
||||
private Bounds createBoundsFromSpan(Point point, double d) {
|
||||
double d2 = d / 2.0d;
|
||||
return new Bounds(point.x - d2, point.x + d2, point.y - d2, point.y + d2);
|
||||
}
|
||||
|
||||
protected static class QuadItem<T extends ClusterItem> implements PointQuadTree.Item, Cluster<T> {
|
||||
private final T mClusterItem;
|
||||
private final Point mPoint;
|
||||
private final LatLng mPosition;
|
||||
private Set<T> singletonSet;
|
||||
|
||||
@Override // com.google.maps.android.clustering.Cluster
|
||||
public int getSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
private QuadItem(T t) {
|
||||
this.mClusterItem = t;
|
||||
LatLng position = t.getPosition();
|
||||
this.mPosition = position;
|
||||
this.mPoint = NonHierarchicalDistanceBasedAlgorithm.PROJECTION.toPoint(position);
|
||||
this.singletonSet = Collections.singleton(t);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.quadtree.PointQuadTree.Item
|
||||
public Point getPoint() {
|
||||
return this.mPoint;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.Cluster
|
||||
public LatLng getPosition() {
|
||||
return this.mPosition;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.Cluster
|
||||
public Set<T> getItems() {
|
||||
return this.singletonSet;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.mClusterItem.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof QuadItem) {
|
||||
return ((QuadItem) obj).mClusterItem.equals(this.mClusterItem);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import com.google.android.gms.maps.model.CameraPosition;
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm;
|
||||
import com.google.maps.android.geometry.Bounds;
|
||||
import com.google.maps.android.projection.Point;
|
||||
import com.google.maps.android.projection.SphericalMercatorProjection;
|
||||
import com.google.maps.android.quadtree.PointQuadTree;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class NonHierarchicalViewBasedAlgorithm<T extends ClusterItem> extends NonHierarchicalDistanceBasedAlgorithm<T> implements ScreenBasedAlgorithm<T> {
|
||||
private static final SphericalMercatorProjection PROJECTION = new SphericalMercatorProjection(1.0d);
|
||||
private LatLng mMapCenter;
|
||||
private int mViewHeight;
|
||||
private int mViewWidth;
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.ScreenBasedAlgorithm
|
||||
public boolean shouldReclusterOnMapMovement() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public NonHierarchicalViewBasedAlgorithm(int i, int i2) {
|
||||
this.mViewWidth = i;
|
||||
this.mViewHeight = i2;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.ScreenBasedAlgorithm
|
||||
public void onCameraChange(CameraPosition cameraPosition) {
|
||||
this.mMapCenter = cameraPosition.target;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm
|
||||
protected Collection<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> getClusteringItems(PointQuadTree<NonHierarchicalDistanceBasedAlgorithm.QuadItem<T>> pointQuadTree, float f) {
|
||||
Bounds visibleBounds = getVisibleBounds(f);
|
||||
ArrayList arrayList = new ArrayList();
|
||||
if (visibleBounds.minX < 0.0d) {
|
||||
arrayList.addAll(pointQuadTree.search(new Bounds(visibleBounds.minX + 1.0d, 1.0d, visibleBounds.minY, visibleBounds.maxY)));
|
||||
visibleBounds = new Bounds(0.0d, visibleBounds.maxX, visibleBounds.minY, visibleBounds.maxY);
|
||||
}
|
||||
if (visibleBounds.maxX > 1.0d) {
|
||||
arrayList.addAll(pointQuadTree.search(new Bounds(0.0d, visibleBounds.maxX - 1.0d, visibleBounds.minY, visibleBounds.maxY)));
|
||||
visibleBounds = new Bounds(visibleBounds.minX, 1.0d, visibleBounds.minY, visibleBounds.maxY);
|
||||
}
|
||||
arrayList.addAll(pointQuadTree.search(visibleBounds));
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
public void updateViewSize(int i, int i2) {
|
||||
this.mViewWidth = i;
|
||||
this.mViewHeight = i2;
|
||||
}
|
||||
|
||||
private Bounds getVisibleBounds(float f) {
|
||||
LatLng latLng = this.mMapCenter;
|
||||
if (latLng == null) {
|
||||
return new Bounds(0.0d, 0.0d, 0.0d, 0.0d);
|
||||
}
|
||||
Point point = PROJECTION.toPoint(latLng);
|
||||
double d = f;
|
||||
double dPow = ((((double) this.mViewWidth) / Math.pow(2.0d, d)) / 256.0d) / 2.0d;
|
||||
double dPow2 = ((((double) this.mViewHeight) / Math.pow(2.0d, d)) / 256.0d) / 2.0d;
|
||||
return new Bounds(point.x - dPow, point.x + dPow, point.y - dPow2, point.y + dPow2);
|
||||
}
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import androidx.collection.LruCache;
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class PreCachingAlgorithmDecorator<T extends ClusterItem> extends AbstractAlgorithm<T> {
|
||||
private final Algorithm<T> mAlgorithm;
|
||||
private final LruCache<Integer, Set<? extends Cluster<T>>> mCache = new LruCache<>(5);
|
||||
private final ReadWriteLock mCacheLock = new ReentrantReadWriteLock();
|
||||
private final Executor mExecutor = Executors.newCachedThreadPool();
|
||||
|
||||
public PreCachingAlgorithmDecorator(Algorithm<T> algorithm) {
|
||||
this.mAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean addItem(T t) {
|
||||
boolean zAddItem = this.mAlgorithm.addItem(t);
|
||||
if (zAddItem) {
|
||||
clearCache();
|
||||
}
|
||||
return zAddItem;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean addItems(Collection<T> collection) {
|
||||
boolean zAddItems = this.mAlgorithm.addItems(collection);
|
||||
if (zAddItems) {
|
||||
clearCache();
|
||||
}
|
||||
return zAddItems;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void clearItems() {
|
||||
this.mAlgorithm.clearItems();
|
||||
clearCache();
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean removeItem(T t) {
|
||||
boolean zRemoveItem = this.mAlgorithm.removeItem(t);
|
||||
if (zRemoveItem) {
|
||||
clearCache();
|
||||
}
|
||||
return zRemoveItem;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean removeItems(Collection<T> collection) {
|
||||
boolean zRemoveItems = this.mAlgorithm.removeItems(collection);
|
||||
if (zRemoveItems) {
|
||||
clearCache();
|
||||
}
|
||||
return zRemoveItems;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean updateItem(T t) {
|
||||
boolean zUpdateItem = this.mAlgorithm.updateItem(t);
|
||||
if (zUpdateItem) {
|
||||
clearCache();
|
||||
}
|
||||
return zUpdateItem;
|
||||
}
|
||||
|
||||
private void clearCache() {
|
||||
this.mCache.evictAll();
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public Set<? extends Cluster<T>> getClusters(float f) {
|
||||
int i = (int) f;
|
||||
Set<? extends Cluster<T>> clustersInternal = getClustersInternal(i);
|
||||
int i2 = i + 1;
|
||||
if (this.mCache.get(Integer.valueOf(i2)) == null) {
|
||||
this.mExecutor.execute(new PrecacheRunnable(i2));
|
||||
}
|
||||
int i3 = i - 1;
|
||||
if (this.mCache.get(Integer.valueOf(i3)) == null) {
|
||||
this.mExecutor.execute(new PrecacheRunnable(i3));
|
||||
}
|
||||
return clustersInternal;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public Collection<T> getItems() {
|
||||
return this.mAlgorithm.getItems();
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void setMaxDistanceBetweenClusteredItems(int i) {
|
||||
this.mAlgorithm.setMaxDistanceBetweenClusteredItems(i);
|
||||
clearCache();
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public int getMaxDistanceBetweenClusteredItems() {
|
||||
return this.mAlgorithm.getMaxDistanceBetweenClusteredItems();
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public Set<? extends Cluster<T>> getClustersInternal(int i) {
|
||||
this.mCacheLock.readLock().lock();
|
||||
Set<? extends Cluster<T>> clusters = this.mCache.get(Integer.valueOf(i));
|
||||
this.mCacheLock.readLock().unlock();
|
||||
if (clusters == null) {
|
||||
this.mCacheLock.writeLock().lock();
|
||||
clusters = this.mCache.get(Integer.valueOf(i));
|
||||
if (clusters == null) {
|
||||
clusters = this.mAlgorithm.getClusters(i);
|
||||
this.mCache.put(Integer.valueOf(i), clusters);
|
||||
}
|
||||
this.mCacheLock.writeLock().unlock();
|
||||
}
|
||||
return clusters;
|
||||
}
|
||||
|
||||
private class PrecacheRunnable implements Runnable {
|
||||
private final int mZoom;
|
||||
|
||||
public PrecacheRunnable(int i) {
|
||||
this.mZoom = i;
|
||||
}
|
||||
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep((long) ((Math.random() * 500.0d) + 500.0d));
|
||||
} catch (InterruptedException unused) {
|
||||
}
|
||||
PreCachingAlgorithmDecorator.this.getClustersInternal(this.mZoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import com.google.android.gms.maps.model.CameraPosition;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public interface ScreenBasedAlgorithm<T extends ClusterItem> extends Algorithm<T> {
|
||||
void onCameraChange(CameraPosition cameraPosition);
|
||||
|
||||
boolean shouldReclusterOnMapMovement();
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import com.google.android.gms.maps.model.CameraPosition;
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class ScreenBasedAlgorithmAdapter<T extends ClusterItem> extends AbstractAlgorithm<T> implements ScreenBasedAlgorithm<T> {
|
||||
private Algorithm<T> mAlgorithm;
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.ScreenBasedAlgorithm
|
||||
public void onCameraChange(CameraPosition cameraPosition) {
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.ScreenBasedAlgorithm
|
||||
public boolean shouldReclusterOnMapMovement() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ScreenBasedAlgorithmAdapter(Algorithm<T> algorithm) {
|
||||
this.mAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean addItem(T t) {
|
||||
return this.mAlgorithm.addItem(t);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean addItems(Collection<T> collection) {
|
||||
return this.mAlgorithm.addItems(collection);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void clearItems() {
|
||||
this.mAlgorithm.clearItems();
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean removeItem(T t) {
|
||||
return this.mAlgorithm.removeItem(t);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean removeItems(Collection<T> collection) {
|
||||
return this.mAlgorithm.removeItems(collection);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public boolean updateItem(T t) {
|
||||
return this.mAlgorithm.updateItem(t);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public Set<? extends Cluster<T>> getClusters(float f) {
|
||||
return this.mAlgorithm.getClusters(f);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public Collection<T> getItems() {
|
||||
return this.mAlgorithm.getItems();
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public void setMaxDistanceBetweenClusteredItems(int i) {
|
||||
this.mAlgorithm.setMaxDistanceBetweenClusteredItems(i);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.algo.Algorithm
|
||||
public int getMaxDistanceBetweenClusteredItems() {
|
||||
return this.mAlgorithm.getMaxDistanceBetweenClusteredItems();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.google.maps.android.clustering.algo;
|
||||
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import kotlinx.serialization.json.internal.AbstractJsonLexerKt;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class StaticCluster<T extends ClusterItem> implements Cluster<T> {
|
||||
private final LatLng mCenter;
|
||||
private final Collection<T> mItems = new LinkedHashSet();
|
||||
|
||||
public StaticCluster(LatLng latLng) {
|
||||
this.mCenter = latLng;
|
||||
}
|
||||
|
||||
public boolean add(T t) {
|
||||
return this.mItems.add(t);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.Cluster
|
||||
public LatLng getPosition() {
|
||||
return this.mCenter;
|
||||
}
|
||||
|
||||
public boolean remove(T t) {
|
||||
return this.mItems.remove(t);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.Cluster
|
||||
public Collection<T> getItems() {
|
||||
return this.mItems;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.Cluster
|
||||
public int getSize() {
|
||||
return this.mItems.size();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "StaticCluster{mCenter=" + this.mCenter + ", mItems.size=" + this.mItems.size() + AbstractJsonLexerKt.END_OBJ;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.mCenter.hashCode() + this.mItems.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof StaticCluster)) {
|
||||
return false;
|
||||
}
|
||||
StaticCluster staticCluster = (StaticCluster) obj;
|
||||
return staticCluster.mCenter.equals(this.mCenter) && staticCluster.mItems.equals(this.mItems);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.google.maps.android.clustering.view;
|
||||
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import com.google.maps.android.clustering.ClusterManager;
|
||||
import java.util.Set;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public interface ClusterRenderer<T extends ClusterItem> {
|
||||
int getClusterTextAppearance(int i);
|
||||
|
||||
int getColor(int i);
|
||||
|
||||
void onAdd();
|
||||
|
||||
void onClustersChanged(Set<? extends Cluster<T>> set);
|
||||
|
||||
void onRemove();
|
||||
|
||||
void setAnimation(boolean z);
|
||||
|
||||
void setAnimationDuration(long j);
|
||||
|
||||
void setOnClusterClickListener(ClusterManager.OnClusterClickListener<T> onClusterClickListener);
|
||||
|
||||
void setOnClusterInfoWindowClickListener(ClusterManager.OnClusterInfoWindowClickListener<T> onClusterInfoWindowClickListener);
|
||||
|
||||
void setOnClusterInfoWindowLongClickListener(ClusterManager.OnClusterInfoWindowLongClickListener<T> onClusterInfoWindowLongClickListener);
|
||||
|
||||
void setOnClusterItemClickListener(ClusterManager.OnClusterItemClickListener<T> onClusterItemClickListener);
|
||||
|
||||
void setOnClusterItemInfoWindowClickListener(ClusterManager.OnClusterItemInfoWindowClickListener<T> onClusterItemInfoWindowClickListener);
|
||||
|
||||
void setOnClusterItemInfoWindowLongClickListener(ClusterManager.OnClusterItemInfoWindowLongClickListener<T> onClusterItemInfoWindowLongClickListener);
|
||||
}
|
||||
+919
@@ -0,0 +1,919 @@
|
||||
package com.google.maps.android.clustering.view;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
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.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 androidx.compose.runtime.ComposerKt;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
import com.google.android.gms.maps.Projection;
|
||||
import com.google.android.gms.maps.model.AdvancedMarker;
|
||||
import com.google.android.gms.maps.model.AdvancedMarkerOptions;
|
||||
import com.google.android.gms.maps.model.BitmapDescriptor;
|
||||
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.android.gms.maps.model.LatLngBounds;
|
||||
import com.google.android.gms.maps.model.Marker;
|
||||
import com.google.maps.android.R;
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import com.google.maps.android.clustering.ClusterManager;
|
||||
import com.google.maps.android.collections.MarkerManager;
|
||||
import com.google.maps.android.geometry.Point;
|
||||
import com.google.maps.android.projection.SphericalMercatorProjection;
|
||||
import com.google.maps.android.ui.IconGenerator;
|
||||
import com.google.maps.android.ui.SquareTextView;
|
||||
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.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class DefaultAdvancedMarkersClusterRenderer<T extends ClusterItem> implements ClusterRenderer<T> {
|
||||
private ClusterManager.OnClusterClickListener<T> mClickListener;
|
||||
private final ClusterManager<T> mClusterManager;
|
||||
private MarkerCache<Cluster<T>> mClusterMarkerCache;
|
||||
private Set<? extends Cluster<T>> mClusters;
|
||||
private ShapeDrawable mColoredCircleBackground;
|
||||
private final float mDensity;
|
||||
private final IconGenerator mIconGenerator;
|
||||
private ClusterManager.OnClusterInfoWindowClickListener<T> mInfoWindowClickListener;
|
||||
private ClusterManager.OnClusterInfoWindowLongClickListener<T> mInfoWindowLongClickListener;
|
||||
private ClusterManager.OnClusterItemClickListener<T> mItemClickListener;
|
||||
private ClusterManager.OnClusterItemInfoWindowClickListener<T> mItemInfoWindowClickListener;
|
||||
private ClusterManager.OnClusterItemInfoWindowLongClickListener<T> mItemInfoWindowLongClickListener;
|
||||
private final GoogleMap mMap;
|
||||
private MarkerCache<T> mMarkerCache;
|
||||
private final DefaultAdvancedMarkersClusterRenderer<T>.ViewModifier mViewModifier;
|
||||
private float mZoom;
|
||||
private static final int[] BUCKETS = {10, 20, 50, 100, ComposerKt.invocationKey, 500, 1000};
|
||||
private static final TimeInterpolator ANIMATION_INTERP = new DecelerateInterpolator();
|
||||
private final Executor mExecutor = Executors.newSingleThreadExecutor();
|
||||
private Set<MarkerWithPosition> mMarkers = Collections.newSetFromMap(new ConcurrentHashMap());
|
||||
private SparseArray<BitmapDescriptor> mIcons = new SparseArray<>();
|
||||
private int mMinClusterSize = 4;
|
||||
private boolean mAnimate = true;
|
||||
private long mAnimationDurationMs = 300;
|
||||
|
||||
protected void onClusterItemRendered(T t, Marker marker) {
|
||||
}
|
||||
|
||||
protected void onClusterRendered(Cluster<T> cluster, Marker marker) {
|
||||
}
|
||||
|
||||
public DefaultAdvancedMarkersClusterRenderer(Context context, GoogleMap googleMap, ClusterManager<T> clusterManager) {
|
||||
this.mMarkerCache = new MarkerCache<>();
|
||||
this.mClusterMarkerCache = new MarkerCache<>();
|
||||
this.mViewModifier = new ViewModifier();
|
||||
this.mMap = googleMap;
|
||||
this.mDensity = context.getResources().getDisplayMetrics().density;
|
||||
IconGenerator iconGenerator = new IconGenerator(context);
|
||||
this.mIconGenerator = iconGenerator;
|
||||
iconGenerator.setContentView(makeSquareTextView(context));
|
||||
iconGenerator.setTextAppearance(R.style.amu_ClusterIcon_TextAppearance);
|
||||
iconGenerator.setBackground(makeClusterBackground());
|
||||
this.mClusterManager = clusterManager;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void onAdd() {
|
||||
this.mClusterManager.getMarkerCollection().setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { // from class: com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer.1
|
||||
/* JADX WARN: Multi-variable type inference failed */
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnMarkerClickListener
|
||||
public boolean onMarkerClick(Marker marker) {
|
||||
return DefaultAdvancedMarkersClusterRenderer.this.mItemClickListener != null && DefaultAdvancedMarkersClusterRenderer.this.mItemClickListener.onClusterItemClick((ClusterItem) DefaultAdvancedMarkersClusterRenderer.this.mMarkerCache.get(marker));
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getMarkerCollection().setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { // from class: com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer.2
|
||||
/* JADX WARN: Multi-variable type inference failed */
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener
|
||||
public void onInfoWindowClick(Marker marker) {
|
||||
if (DefaultAdvancedMarkersClusterRenderer.this.mItemInfoWindowClickListener != null) {
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mItemInfoWindowClickListener.onClusterItemInfoWindowClick((ClusterItem) DefaultAdvancedMarkersClusterRenderer.this.mMarkerCache.get(marker));
|
||||
}
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getMarkerCollection().setOnInfoWindowLongClickListener(new GoogleMap.OnInfoWindowLongClickListener() { // from class: com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer$$ExternalSyntheticLambda0
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowLongClickListener
|
||||
public final void onInfoWindowLongClick(Marker marker) {
|
||||
this.f$0.m7754xfde6dfc5(marker);
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { // from class: com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer$$ExternalSyntheticLambda1
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnMarkerClickListener
|
||||
public final boolean onMarkerClick(Marker marker) {
|
||||
return this.f$0.m7755x50fc206(marker);
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { // from class: com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer$$ExternalSyntheticLambda2
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener
|
||||
public final void onInfoWindowClick(Marker marker) {
|
||||
this.f$0.m7756xc38a447(marker);
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnInfoWindowLongClickListener(new GoogleMap.OnInfoWindowLongClickListener() { // from class: com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer$$ExternalSyntheticLambda3
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowLongClickListener
|
||||
public final void onInfoWindowLongClick(Marker marker) {
|
||||
this.f$0.m7757x13618688(marker);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$onAdd$0$com-google-maps-android-clustering-view-DefaultAdvancedMarkersClusterRenderer, reason: not valid java name */
|
||||
/* synthetic */ void m7754xfde6dfc5(Marker marker) {
|
||||
ClusterManager.OnClusterItemInfoWindowLongClickListener<T> onClusterItemInfoWindowLongClickListener = this.mItemInfoWindowLongClickListener;
|
||||
if (onClusterItemInfoWindowLongClickListener != null) {
|
||||
onClusterItemInfoWindowLongClickListener.onClusterItemInfoWindowLongClick(this.mMarkerCache.get(marker));
|
||||
}
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$onAdd$1$com-google-maps-android-clustering-view-DefaultAdvancedMarkersClusterRenderer, reason: not valid java name */
|
||||
/* synthetic */ boolean m7755x50fc206(Marker marker) {
|
||||
ClusterManager.OnClusterClickListener<T> onClusterClickListener = this.mClickListener;
|
||||
return onClusterClickListener != null && onClusterClickListener.onClusterClick(this.mClusterMarkerCache.get(marker));
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$onAdd$2$com-google-maps-android-clustering-view-DefaultAdvancedMarkersClusterRenderer, reason: not valid java name */
|
||||
/* synthetic */ void m7756xc38a447(Marker marker) {
|
||||
ClusterManager.OnClusterInfoWindowClickListener<T> onClusterInfoWindowClickListener = this.mInfoWindowClickListener;
|
||||
if (onClusterInfoWindowClickListener != null) {
|
||||
onClusterInfoWindowClickListener.onClusterInfoWindowClick(this.mClusterMarkerCache.get(marker));
|
||||
}
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$onAdd$3$com-google-maps-android-clustering-view-DefaultAdvancedMarkersClusterRenderer, reason: not valid java name */
|
||||
/* synthetic */ void m7757x13618688(Marker marker) {
|
||||
ClusterManager.OnClusterInfoWindowLongClickListener<T> onClusterInfoWindowLongClickListener = this.mInfoWindowLongClickListener;
|
||||
if (onClusterInfoWindowLongClickListener != null) {
|
||||
onClusterInfoWindowLongClickListener.onClusterInfoWindowLongClick(this.mClusterMarkerCache.get(marker));
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void onRemove() {
|
||||
this.mClusterManager.getMarkerCollection().setOnMarkerClickListener(null);
|
||||
this.mClusterManager.getMarkerCollection().setOnInfoWindowClickListener(null);
|
||||
this.mClusterManager.getMarkerCollection().setOnInfoWindowLongClickListener(null);
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnMarkerClickListener(null);
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnInfoWindowClickListener(null);
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnInfoWindowLongClickListener(null);
|
||||
}
|
||||
|
||||
private LayerDrawable makeClusterBackground() {
|
||||
this.mColoredCircleBackground = new ShapeDrawable(new OvalShape());
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
|
||||
shapeDrawable.getPaint().setColor(-2130706433);
|
||||
LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{shapeDrawable, this.mColoredCircleBackground});
|
||||
int i = (int) (this.mDensity * 3.0f);
|
||||
layerDrawable.setLayerInset(1, i, i, i, i);
|
||||
return layerDrawable;
|
||||
}
|
||||
|
||||
private SquareTextView makeSquareTextView(Context context) {
|
||||
SquareTextView squareTextView = new SquareTextView(context);
|
||||
squareTextView.setLayoutParams(new ViewGroup.LayoutParams(-2, -2));
|
||||
squareTextView.setId(R.id.amu_text);
|
||||
int i = (int) (this.mDensity * 12.0f);
|
||||
squareTextView.setPadding(i, i, i, i);
|
||||
return squareTextView;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public int getColor(int i) {
|
||||
float fMin = 300.0f - Math.min(i, 300.0f);
|
||||
return Color.HSVToColor(new float[]{((fMin * fMin) / 90000.0f) * 220.0f, 1.0f, 0.6f});
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public int getClusterTextAppearance(int i) {
|
||||
return R.style.amu_ClusterIcon_TextAppearance;
|
||||
}
|
||||
|
||||
protected String getClusterText(int i) {
|
||||
if (i < BUCKETS[0]) {
|
||||
return String.valueOf(i);
|
||||
}
|
||||
return i + org.slf4j.Marker.ANY_NON_NULL_MARKER;
|
||||
}
|
||||
|
||||
protected int getBucket(Cluster<T> cluster) {
|
||||
int size = cluster.getSize();
|
||||
int i = 0;
|
||||
if (size <= BUCKETS[0]) {
|
||||
return size;
|
||||
}
|
||||
while (true) {
|
||||
int[] iArr = BUCKETS;
|
||||
if (i < iArr.length - 1) {
|
||||
int i2 = i + 1;
|
||||
if (size < iArr[i2]) {
|
||||
return iArr[i];
|
||||
}
|
||||
i = i2;
|
||||
} else {
|
||||
return iArr[iArr.length - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getMinClusterSize() {
|
||||
return this.mMinClusterSize;
|
||||
}
|
||||
|
||||
public void setMinClusterSize(int i) {
|
||||
this.mMinClusterSize = i;
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
class ViewModifier extends Handler {
|
||||
private static final int RUN_TASK = 0;
|
||||
private static final int TASK_FINISHED = 1;
|
||||
private DefaultAdvancedMarkersClusterRenderer<T>.RenderTask mNextClusters;
|
||||
private boolean mViewModificationInProgress;
|
||||
|
||||
private ViewModifier() {
|
||||
this.mViewModificationInProgress = false;
|
||||
this.mNextClusters = null;
|
||||
}
|
||||
|
||||
@Override // android.os.Handler
|
||||
public void handleMessage(Message message) {
|
||||
DefaultAdvancedMarkersClusterRenderer<T>.RenderTask renderTask;
|
||||
if (message.what == 1) {
|
||||
this.mViewModificationInProgress = false;
|
||||
if (this.mNextClusters != null) {
|
||||
sendEmptyMessage(0);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
removeMessages(0);
|
||||
if (this.mViewModificationInProgress || this.mNextClusters == null) {
|
||||
return;
|
||||
}
|
||||
Projection projection = DefaultAdvancedMarkersClusterRenderer.this.mMap.getProjection();
|
||||
synchronized (this) {
|
||||
renderTask = this.mNextClusters;
|
||||
this.mNextClusters = null;
|
||||
this.mViewModificationInProgress = true;
|
||||
}
|
||||
renderTask.setCallback(new Runnable() { // from class: com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer$ViewModifier$$ExternalSyntheticLambda0
|
||||
@Override // java.lang.Runnable
|
||||
public final void run() {
|
||||
this.f$0.m7758x1c4a00de();
|
||||
}
|
||||
});
|
||||
renderTask.setProjection(projection);
|
||||
renderTask.setMapZoom(DefaultAdvancedMarkersClusterRenderer.this.mMap.getCameraPosition().zoom);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mExecutor.execute(renderTask);
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$handleMessage$0$com-google-maps-android-clustering-view-DefaultAdvancedMarkersClusterRenderer$ViewModifier, reason: not valid java name */
|
||||
/* synthetic */ void m7758x1c4a00de() {
|
||||
sendEmptyMessage(1);
|
||||
}
|
||||
|
||||
public void queue(Set<? extends Cluster<T>> set) {
|
||||
synchronized (this) {
|
||||
this.mNextClusters = new RenderTask(set);
|
||||
}
|
||||
sendEmptyMessage(0);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldRenderAsCluster(Cluster<T> cluster) {
|
||||
return cluster.getSize() >= this.mMinClusterSize;
|
||||
}
|
||||
|
||||
protected boolean shouldRender(Set<? extends Cluster<T>> set, Set<? extends Cluster<T>> set2) {
|
||||
return !set2.equals(set);
|
||||
}
|
||||
|
||||
private class RenderTask implements Runnable {
|
||||
final Set<? extends Cluster<T>> clusters;
|
||||
private Runnable mCallback;
|
||||
private float mMapZoom;
|
||||
private Projection mProjection;
|
||||
private SphericalMercatorProjection mSphericalMercatorProjection;
|
||||
|
||||
private RenderTask(Set<? extends Cluster<T>> set) {
|
||||
this.clusters = set;
|
||||
}
|
||||
|
||||
public void setCallback(Runnable runnable) {
|
||||
this.mCallback = runnable;
|
||||
}
|
||||
|
||||
public void setProjection(Projection projection) {
|
||||
this.mProjection = projection;
|
||||
}
|
||||
|
||||
public void setMapZoom(float f) {
|
||||
this.mMapZoom = f;
|
||||
this.mSphericalMercatorProjection = new SphericalMercatorProjection(Math.pow(2.0d, Math.min(f, DefaultAdvancedMarkersClusterRenderer.this.mZoom)) * 256.0d);
|
||||
}
|
||||
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
LatLngBounds latLngBoundsBuild;
|
||||
ArrayList arrayList;
|
||||
DefaultAdvancedMarkersClusterRenderer defaultAdvancedMarkersClusterRenderer = DefaultAdvancedMarkersClusterRenderer.this;
|
||||
if (!defaultAdvancedMarkersClusterRenderer.shouldRender(defaultAdvancedMarkersClusterRenderer.immutableOf(defaultAdvancedMarkersClusterRenderer.mClusters), DefaultAdvancedMarkersClusterRenderer.this.immutableOf(this.clusters))) {
|
||||
this.mCallback.run();
|
||||
return;
|
||||
}
|
||||
ArrayList arrayList2 = null;
|
||||
MarkerModifier markerModifier = new MarkerModifier();
|
||||
float f = this.mMapZoom;
|
||||
boolean z = f > DefaultAdvancedMarkersClusterRenderer.this.mZoom;
|
||||
float f2 = f - DefaultAdvancedMarkersClusterRenderer.this.mZoom;
|
||||
Set<MarkerWithPosition> set = DefaultAdvancedMarkersClusterRenderer.this.mMarkers;
|
||||
try {
|
||||
latLngBoundsBuild = this.mProjection.getVisibleRegion().latLngBounds;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
latLngBoundsBuild = LatLngBounds.builder().include(new LatLng(0.0d, 0.0d)).build();
|
||||
}
|
||||
if (DefaultAdvancedMarkersClusterRenderer.this.mClusters == null || !DefaultAdvancedMarkersClusterRenderer.this.mAnimate) {
|
||||
arrayList = null;
|
||||
} else {
|
||||
arrayList = new ArrayList();
|
||||
for (Cluster<T> cluster : DefaultAdvancedMarkersClusterRenderer.this.mClusters) {
|
||||
if (DefaultAdvancedMarkersClusterRenderer.this.shouldRenderAsCluster(cluster) && latLngBoundsBuild.contains(cluster.getPosition())) {
|
||||
arrayList.add(this.mSphericalMercatorProjection.toPoint(cluster.getPosition()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Set setNewSetFromMap = Collections.newSetFromMap(new ConcurrentHashMap());
|
||||
for (Cluster<T> cluster2 : this.clusters) {
|
||||
boolean zContains = latLngBoundsBuild.contains(cluster2.getPosition());
|
||||
if (z && zContains && DefaultAdvancedMarkersClusterRenderer.this.mAnimate) {
|
||||
Point pointFindClosestCluster = DefaultAdvancedMarkersClusterRenderer.this.findClosestCluster(arrayList, this.mSphericalMercatorProjection.toPoint(cluster2.getPosition()));
|
||||
if (pointFindClosestCluster != null) {
|
||||
markerModifier.add(true, new CreateMarkerTask(cluster2, setNewSetFromMap, this.mSphericalMercatorProjection.toLatLng(pointFindClosestCluster)));
|
||||
} else {
|
||||
markerModifier.add(true, new CreateMarkerTask(cluster2, setNewSetFromMap, null));
|
||||
}
|
||||
} else {
|
||||
markerModifier.add(zContains, new CreateMarkerTask(cluster2, setNewSetFromMap, null));
|
||||
}
|
||||
}
|
||||
markerModifier.waitUntilFree();
|
||||
set.removeAll(setNewSetFromMap);
|
||||
if (DefaultAdvancedMarkersClusterRenderer.this.mAnimate) {
|
||||
arrayList2 = new ArrayList();
|
||||
for (Cluster<T> cluster3 : this.clusters) {
|
||||
if (DefaultAdvancedMarkersClusterRenderer.this.shouldRenderAsCluster(cluster3) && latLngBoundsBuild.contains(cluster3.getPosition())) {
|
||||
arrayList2.add(this.mSphericalMercatorProjection.toPoint(cluster3.getPosition()));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (MarkerWithPosition markerWithPosition : set) {
|
||||
boolean zContains2 = latLngBoundsBuild.contains(markerWithPosition.position);
|
||||
if (!z && f2 > -3.0f && zContains2 && DefaultAdvancedMarkersClusterRenderer.this.mAnimate) {
|
||||
Point pointFindClosestCluster2 = DefaultAdvancedMarkersClusterRenderer.this.findClosestCluster(arrayList2, this.mSphericalMercatorProjection.toPoint(markerWithPosition.position));
|
||||
if (pointFindClosestCluster2 != null) {
|
||||
markerModifier.animateThenRemove(markerWithPosition, markerWithPosition.position, this.mSphericalMercatorProjection.toLatLng(pointFindClosestCluster2));
|
||||
} else {
|
||||
markerModifier.remove(true, markerWithPosition.marker);
|
||||
}
|
||||
} else {
|
||||
markerModifier.remove(zContains2, markerWithPosition.marker);
|
||||
}
|
||||
}
|
||||
markerModifier.waitUntilFree();
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mMarkers = setNewSetFromMap;
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mClusters = this.clusters;
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mZoom = f;
|
||||
this.mCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void onClustersChanged(Set<? extends Cluster<T>> set) {
|
||||
this.mViewModifier.queue(set);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterClickListener(ClusterManager.OnClusterClickListener<T> onClusterClickListener) {
|
||||
this.mClickListener = onClusterClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterInfoWindowClickListener(ClusterManager.OnClusterInfoWindowClickListener<T> onClusterInfoWindowClickListener) {
|
||||
this.mInfoWindowClickListener = onClusterInfoWindowClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterInfoWindowLongClickListener(ClusterManager.OnClusterInfoWindowLongClickListener<T> onClusterInfoWindowLongClickListener) {
|
||||
this.mInfoWindowLongClickListener = onClusterInfoWindowLongClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterItemClickListener(ClusterManager.OnClusterItemClickListener<T> onClusterItemClickListener) {
|
||||
this.mItemClickListener = onClusterItemClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterItemInfoWindowClickListener(ClusterManager.OnClusterItemInfoWindowClickListener<T> onClusterItemInfoWindowClickListener) {
|
||||
this.mItemInfoWindowClickListener = onClusterItemInfoWindowClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterItemInfoWindowLongClickListener(ClusterManager.OnClusterItemInfoWindowLongClickListener<T> onClusterItemInfoWindowLongClickListener) {
|
||||
this.mItemInfoWindowLongClickListener = onClusterItemInfoWindowLongClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setAnimation(boolean z) {
|
||||
this.mAnimate = z;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setAnimationDuration(long j) {
|
||||
this.mAnimationDurationMs = j;
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public Set<? extends Cluster<T>> immutableOf(Set<? extends Cluster<T>> set) {
|
||||
return set != null ? Collections.unmodifiableSet(set) : Collections.emptySet();
|
||||
}
|
||||
|
||||
private static double distanceSquared(Point point, Point point2) {
|
||||
return ((point.x - point2.x) * (point.x - point2.x)) + ((point.y - point2.y) * (point.y - point2.y));
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public Point findClosestCluster(List<Point> list, Point point) {
|
||||
Point point2 = null;
|
||||
if (list != null && !list.isEmpty()) {
|
||||
int maxDistanceBetweenClusteredItems = this.mClusterManager.getAlgorithm().getMaxDistanceBetweenClusteredItems();
|
||||
double d = maxDistanceBetweenClusteredItems * maxDistanceBetweenClusteredItems;
|
||||
for (Point point3 : list) {
|
||||
double dDistanceSquared = distanceSquared(point3, point);
|
||||
if (dDistanceSquared < d) {
|
||||
point2 = point3;
|
||||
d = dDistanceSquared;
|
||||
}
|
||||
}
|
||||
}
|
||||
return point2;
|
||||
}
|
||||
|
||||
private class MarkerModifier extends Handler implements MessageQueue.IdleHandler {
|
||||
private static final int BLANK = 0;
|
||||
private final Condition busyCondition;
|
||||
private final Lock lock;
|
||||
private Queue<DefaultAdvancedMarkersClusterRenderer<T>.AnimationTask> mAnimationTasks;
|
||||
private Queue<DefaultAdvancedMarkersClusterRenderer<T>.CreateMarkerTask> mCreateMarkerTasks;
|
||||
private boolean mListenerAdded;
|
||||
private Queue<DefaultAdvancedMarkersClusterRenderer<T>.CreateMarkerTask> mOnScreenCreateMarkerTasks;
|
||||
private Queue<Marker> mOnScreenRemoveMarkerTasks;
|
||||
private Queue<Marker> mRemoveMarkerTasks;
|
||||
|
||||
private MarkerModifier() {
|
||||
super(Looper.getMainLooper());
|
||||
ReentrantLock reentrantLock = new ReentrantLock();
|
||||
this.lock = reentrantLock;
|
||||
this.busyCondition = reentrantLock.newCondition();
|
||||
this.mCreateMarkerTasks = new LinkedList();
|
||||
this.mOnScreenCreateMarkerTasks = new LinkedList();
|
||||
this.mRemoveMarkerTasks = new LinkedList();
|
||||
this.mOnScreenRemoveMarkerTasks = new LinkedList();
|
||||
this.mAnimationTasks = new LinkedList();
|
||||
}
|
||||
|
||||
public void add(boolean z, DefaultAdvancedMarkersClusterRenderer<T>.CreateMarkerTask createMarkerTask) {
|
||||
this.lock.lock();
|
||||
sendEmptyMessage(0);
|
||||
if (z) {
|
||||
this.mOnScreenCreateMarkerTasks.add(createMarkerTask);
|
||||
} else {
|
||||
this.mCreateMarkerTasks.add(createMarkerTask);
|
||||
}
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
public void remove(boolean z, Marker marker) {
|
||||
this.lock.lock();
|
||||
sendEmptyMessage(0);
|
||||
if (z) {
|
||||
this.mOnScreenRemoveMarkerTasks.add(marker);
|
||||
} else {
|
||||
this.mRemoveMarkerTasks.add(marker);
|
||||
}
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
public void animate(MarkerWithPosition markerWithPosition, LatLng latLng, LatLng latLng2) {
|
||||
this.lock.lock();
|
||||
this.mAnimationTasks.add(new AnimationTask(markerWithPosition, latLng, latLng2));
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
public void animateThenRemove(MarkerWithPosition markerWithPosition, LatLng latLng, LatLng latLng2) {
|
||||
this.lock.lock();
|
||||
DefaultAdvancedMarkersClusterRenderer<T>.AnimationTask animationTask = new AnimationTask(markerWithPosition, latLng, latLng2);
|
||||
animationTask.removeOnAnimationComplete(DefaultAdvancedMarkersClusterRenderer.this.mClusterManager.getMarkerManager());
|
||||
this.mAnimationTasks.add(animationTask);
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
@Override // android.os.Handler
|
||||
public void handleMessage(Message message) {
|
||||
if (!this.mListenerAdded) {
|
||||
Looper.myQueue().addIdleHandler(this);
|
||||
this.mListenerAdded = true;
|
||||
}
|
||||
removeMessages(0);
|
||||
this.lock.lock();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
performNextTask();
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
if (!isBusy()) {
|
||||
this.mListenerAdded = false;
|
||||
Looper.myQueue().removeIdleHandler(this);
|
||||
this.busyCondition.signalAll();
|
||||
} else {
|
||||
sendEmptyMessageDelayed(0, 10L);
|
||||
}
|
||||
}
|
||||
|
||||
private void performNextTask() {
|
||||
if (!this.mOnScreenRemoveMarkerTasks.isEmpty()) {
|
||||
removeMarker(this.mOnScreenRemoveMarkerTasks.poll());
|
||||
return;
|
||||
}
|
||||
if (!this.mAnimationTasks.isEmpty()) {
|
||||
this.mAnimationTasks.poll().perform();
|
||||
return;
|
||||
}
|
||||
if (this.mOnScreenCreateMarkerTasks.isEmpty()) {
|
||||
if (this.mCreateMarkerTasks.isEmpty()) {
|
||||
if (this.mRemoveMarkerTasks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
removeMarker(this.mRemoveMarkerTasks.poll());
|
||||
return;
|
||||
}
|
||||
this.mCreateMarkerTasks.poll().perform(this);
|
||||
return;
|
||||
}
|
||||
this.mOnScreenCreateMarkerTasks.poll().perform(this);
|
||||
}
|
||||
|
||||
private void removeMarker(Marker marker) {
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mMarkerCache.remove(marker);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mClusterMarkerCache.remove(marker);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mClusterManager.getMarkerManager().remove(marker);
|
||||
}
|
||||
|
||||
/* JADX WARN: Removed duplicated region for block: B:14:0x0030 */
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
public boolean isBusy() {
|
||||
/*
|
||||
r2 = this;
|
||||
java.util.concurrent.locks.Lock r0 = r2.lock // Catch: java.lang.Throwable -> L37
|
||||
r0.lock() // Catch: java.lang.Throwable -> L37
|
||||
java.util.Queue<com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer<T>$CreateMarkerTask> r0 = r2.mCreateMarkerTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 == 0) goto L30
|
||||
java.util.Queue<com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer<T>$CreateMarkerTask> r0 = r2.mOnScreenCreateMarkerTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 == 0) goto L30
|
||||
java.util.Queue<com.google.android.gms.maps.model.Marker> r0 = r2.mOnScreenRemoveMarkerTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 == 0) goto L30
|
||||
java.util.Queue<com.google.android.gms.maps.model.Marker> r0 = r2.mRemoveMarkerTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 == 0) goto L30
|
||||
java.util.Queue<com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer<T>$AnimationTask> r0 = r2.mAnimationTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 != 0) goto L2e
|
||||
goto L30
|
||||
L2e:
|
||||
r0 = 0
|
||||
goto L31
|
||||
L30:
|
||||
r0 = 1
|
||||
L31:
|
||||
java.util.concurrent.locks.Lock r1 = r2.lock
|
||||
r1.unlock()
|
||||
return r0
|
||||
L37:
|
||||
r0 = move-exception
|
||||
java.util.concurrent.locks.Lock r1 = r2.lock
|
||||
r1.unlock()
|
||||
throw r0
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: com.google.maps.android.clustering.view.DefaultAdvancedMarkersClusterRenderer.MarkerModifier.isBusy():boolean");
|
||||
}
|
||||
|
||||
public void waitUntilFree() {
|
||||
while (isBusy()) {
|
||||
sendEmptyMessage(0);
|
||||
this.lock.lock();
|
||||
try {
|
||||
try {
|
||||
if (isBusy()) {
|
||||
this.busyCondition.await();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // android.os.MessageQueue.IdleHandler
|
||||
public boolean queueIdle() {
|
||||
sendEmptyMessage(0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MarkerCache<T> {
|
||||
private Map<T, Marker> mCache;
|
||||
private Map<Marker, T> mCacheReverse;
|
||||
|
||||
private MarkerCache() {
|
||||
this.mCache = new HashMap();
|
||||
this.mCacheReverse = new HashMap();
|
||||
}
|
||||
|
||||
public Marker get(T t) {
|
||||
return this.mCache.get(t);
|
||||
}
|
||||
|
||||
public T get(Marker marker) {
|
||||
return this.mCacheReverse.get(marker);
|
||||
}
|
||||
|
||||
public void put(T t, Marker marker) {
|
||||
this.mCache.put(t, marker);
|
||||
this.mCacheReverse.put(marker, t);
|
||||
}
|
||||
|
||||
public void remove(Marker marker) {
|
||||
T t = this.mCacheReverse.get(marker);
|
||||
this.mCacheReverse.remove(marker);
|
||||
this.mCache.remove(t);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onBeforeClusterItemRendered(T t, AdvancedMarkerOptions advancedMarkerOptions) {
|
||||
if (t.getTitle() != null && t.getSnippet() != null) {
|
||||
advancedMarkerOptions.title(t.getTitle());
|
||||
advancedMarkerOptions.snippet(t.getSnippet());
|
||||
} else if (t.getTitle() != null) {
|
||||
advancedMarkerOptions.title(t.getTitle());
|
||||
} else if (t.getSnippet() != null) {
|
||||
advancedMarkerOptions.title(t.getSnippet());
|
||||
}
|
||||
}
|
||||
|
||||
protected void onClusterItemUpdated(T t, Marker marker) {
|
||||
boolean z = true;
|
||||
boolean z2 = false;
|
||||
if (t.getTitle() != null && t.getSnippet() != null) {
|
||||
if (!t.getTitle().equals(marker.getTitle())) {
|
||||
marker.setTitle(t.getTitle());
|
||||
z2 = true;
|
||||
}
|
||||
if (!t.getSnippet().equals(marker.getSnippet())) {
|
||||
marker.setSnippet(t.getSnippet());
|
||||
z2 = true;
|
||||
}
|
||||
} else {
|
||||
if (t.getSnippet() != null && !t.getSnippet().equals(marker.getTitle())) {
|
||||
marker.setTitle(t.getSnippet());
|
||||
} else if (t.getTitle() != null && !t.getTitle().equals(marker.getTitle())) {
|
||||
marker.setTitle(t.getTitle());
|
||||
}
|
||||
z2 = true;
|
||||
}
|
||||
if (marker.getPosition().equals(t.getPosition())) {
|
||||
z = z2;
|
||||
} else {
|
||||
marker.setPosition(t.getPosition());
|
||||
if (t.getZIndex() != null) {
|
||||
marker.setZIndex(t.getZIndex().floatValue());
|
||||
}
|
||||
}
|
||||
if (z && marker.isInfoWindowShown()) {
|
||||
marker.showInfoWindow();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onBeforeClusterRendered(Cluster<T> cluster, AdvancedMarkerOptions advancedMarkerOptions) {
|
||||
advancedMarkerOptions.icon(getDescriptorForCluster(cluster));
|
||||
}
|
||||
|
||||
protected BitmapDescriptor getDescriptorForCluster(Cluster<T> cluster) {
|
||||
int bucket = getBucket(cluster);
|
||||
BitmapDescriptor bitmapDescriptor = this.mIcons.get(bucket);
|
||||
if (bitmapDescriptor != null) {
|
||||
return bitmapDescriptor;
|
||||
}
|
||||
this.mColoredCircleBackground.getPaint().setColor(getColor(bucket));
|
||||
this.mIconGenerator.setTextAppearance(getClusterTextAppearance(bucket));
|
||||
BitmapDescriptor bitmapDescriptorFromBitmap = BitmapDescriptorFactory.fromBitmap(this.mIconGenerator.makeIcon(getClusterText(bucket)));
|
||||
this.mIcons.put(bucket, bitmapDescriptorFromBitmap);
|
||||
return bitmapDescriptorFromBitmap;
|
||||
}
|
||||
|
||||
protected void onClusterUpdated(Cluster<T> cluster, AdvancedMarker advancedMarker) {
|
||||
advancedMarker.setIcon(getDescriptorForCluster(cluster));
|
||||
}
|
||||
|
||||
public Marker getMarker(T t) {
|
||||
return this.mMarkerCache.get(t);
|
||||
}
|
||||
|
||||
public T getClusterItem(Marker marker) {
|
||||
return this.mMarkerCache.get(marker);
|
||||
}
|
||||
|
||||
public Marker getMarker(Cluster<T> cluster) {
|
||||
return this.mClusterMarkerCache.get(cluster);
|
||||
}
|
||||
|
||||
public Cluster<T> getCluster(Marker marker) {
|
||||
return this.mClusterMarkerCache.get(marker);
|
||||
}
|
||||
|
||||
private class CreateMarkerTask {
|
||||
private final LatLng animateFrom;
|
||||
private final Cluster<T> cluster;
|
||||
private final Set<MarkerWithPosition> newMarkers;
|
||||
|
||||
public CreateMarkerTask(Cluster<T> cluster, Set<MarkerWithPosition> set, LatLng latLng) {
|
||||
this.cluster = cluster;
|
||||
this.newMarkers = set;
|
||||
this.animateFrom = latLng;
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public void perform(DefaultAdvancedMarkersClusterRenderer<T>.MarkerModifier markerModifier) {
|
||||
MarkerWithPosition markerWithPosition;
|
||||
MarkerWithPosition markerWithPosition2;
|
||||
if (DefaultAdvancedMarkersClusterRenderer.this.shouldRenderAsCluster(this.cluster)) {
|
||||
AdvancedMarker advancedMarker = (AdvancedMarker) DefaultAdvancedMarkersClusterRenderer.this.mClusterMarkerCache.get(this.cluster);
|
||||
if (advancedMarker == null) {
|
||||
AdvancedMarkerOptions advancedMarkerOptions = new AdvancedMarkerOptions();
|
||||
LatLng position = this.animateFrom;
|
||||
if (position == null) {
|
||||
position = this.cluster.getPosition();
|
||||
}
|
||||
AdvancedMarkerOptions advancedMarkerOptionsPosition = advancedMarkerOptions.position(position);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.onBeforeClusterRendered(this.cluster, advancedMarkerOptionsPosition);
|
||||
advancedMarker = (AdvancedMarker) DefaultAdvancedMarkersClusterRenderer.this.mClusterManager.getClusterMarkerCollection().addMarker(advancedMarkerOptionsPosition);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mClusterMarkerCache.put(this.cluster, advancedMarker);
|
||||
markerWithPosition = new MarkerWithPosition(advancedMarker);
|
||||
LatLng latLng = this.animateFrom;
|
||||
if (latLng != null) {
|
||||
markerModifier.animate(markerWithPosition, latLng, this.cluster.getPosition());
|
||||
}
|
||||
} else {
|
||||
markerWithPosition = new MarkerWithPosition(advancedMarker);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.onClusterUpdated(this.cluster, advancedMarker);
|
||||
}
|
||||
DefaultAdvancedMarkersClusterRenderer.this.onClusterRendered(this.cluster, advancedMarker);
|
||||
this.newMarkers.add(markerWithPosition);
|
||||
return;
|
||||
}
|
||||
for (T t : this.cluster.getItems()) {
|
||||
AdvancedMarker advancedMarker2 = (AdvancedMarker) DefaultAdvancedMarkersClusterRenderer.this.mMarkerCache.get(t);
|
||||
if (advancedMarker2 == null) {
|
||||
AdvancedMarkerOptions advancedMarkerOptions2 = new AdvancedMarkerOptions();
|
||||
LatLng latLng2 = this.animateFrom;
|
||||
if (latLng2 != null) {
|
||||
advancedMarkerOptions2.position(latLng2);
|
||||
} else {
|
||||
advancedMarkerOptions2.position(t.getPosition());
|
||||
if (t.getZIndex() != null) {
|
||||
advancedMarkerOptions2.zIndex(t.getZIndex().floatValue());
|
||||
}
|
||||
}
|
||||
DefaultAdvancedMarkersClusterRenderer.this.onBeforeClusterItemRendered(t, advancedMarkerOptions2);
|
||||
advancedMarker2 = (AdvancedMarker) DefaultAdvancedMarkersClusterRenderer.this.mClusterManager.getMarkerCollection().addMarker(advancedMarkerOptions2);
|
||||
markerWithPosition2 = new MarkerWithPosition(advancedMarker2);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mMarkerCache.put(t, advancedMarker2);
|
||||
LatLng latLng3 = this.animateFrom;
|
||||
if (latLng3 != null) {
|
||||
markerModifier.animate(markerWithPosition2, latLng3, t.getPosition());
|
||||
}
|
||||
} else {
|
||||
markerWithPosition2 = new MarkerWithPosition(advancedMarker2);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.onClusterItemUpdated(t, advancedMarker2);
|
||||
}
|
||||
DefaultAdvancedMarkersClusterRenderer.this.onClusterItemRendered(t, advancedMarker2);
|
||||
this.newMarkers.add(markerWithPosition2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MarkerWithPosition {
|
||||
private final Marker marker;
|
||||
private LatLng position;
|
||||
|
||||
private MarkerWithPosition(Marker marker) {
|
||||
this.marker = marker;
|
||||
this.position = marker.getPosition();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof MarkerWithPosition) {
|
||||
return this.marker.equals(((MarkerWithPosition) obj).marker);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.marker.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private class AnimationTask extends AnimatorListenerAdapter implements ValueAnimator.AnimatorUpdateListener {
|
||||
private final LatLng from;
|
||||
private MarkerManager mMarkerManager;
|
||||
private boolean mRemoveOnComplete;
|
||||
private final Marker marker;
|
||||
private final MarkerWithPosition markerWithPosition;
|
||||
private final LatLng to;
|
||||
|
||||
private AnimationTask(MarkerWithPosition markerWithPosition, LatLng latLng, LatLng latLng2) {
|
||||
this.markerWithPosition = markerWithPosition;
|
||||
this.marker = markerWithPosition.marker;
|
||||
this.from = latLng;
|
||||
this.to = latLng2;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
ValueAnimator valueAnimatorOfFloat = ValueAnimator.ofFloat(0.0f, 1.0f);
|
||||
valueAnimatorOfFloat.setInterpolator(DefaultAdvancedMarkersClusterRenderer.ANIMATION_INTERP);
|
||||
valueAnimatorOfFloat.setDuration(DefaultAdvancedMarkersClusterRenderer.this.mAnimationDurationMs);
|
||||
valueAnimatorOfFloat.addUpdateListener(this);
|
||||
valueAnimatorOfFloat.addListener(this);
|
||||
valueAnimatorOfFloat.start();
|
||||
}
|
||||
|
||||
@Override // android.animation.AnimatorListenerAdapter, android.animation.Animator.AnimatorListener
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
if (this.mRemoveOnComplete) {
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mMarkerCache.remove(this.marker);
|
||||
DefaultAdvancedMarkersClusterRenderer.this.mClusterMarkerCache.remove(this.marker);
|
||||
this.mMarkerManager.remove(this.marker);
|
||||
}
|
||||
this.markerWithPosition.position = this.to;
|
||||
}
|
||||
|
||||
public void removeOnAnimationComplete(MarkerManager markerManager) {
|
||||
this.mMarkerManager = markerManager;
|
||||
this.mRemoveOnComplete = true;
|
||||
}
|
||||
|
||||
@Override // android.animation.ValueAnimator.AnimatorUpdateListener
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
double animatedFraction = valueAnimator.getAnimatedFraction();
|
||||
double d = ((this.to.latitude - this.from.latitude) * animatedFraction) + this.from.latitude;
|
||||
double dSignum = this.to.longitude - this.from.longitude;
|
||||
if (Math.abs(dSignum) > 180.0d) {
|
||||
dSignum -= Math.signum(dSignum) * 360.0d;
|
||||
}
|
||||
this.marker.setPosition(new LatLng(d, (dSignum * animatedFraction) + this.from.longitude));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,921 @@
|
||||
package com.google.maps.android.clustering.view;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
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.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 androidx.compose.runtime.ComposerKt;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
import com.google.android.gms.maps.Projection;
|
||||
import com.google.android.gms.maps.model.BitmapDescriptor;
|
||||
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.android.gms.maps.model.LatLngBounds;
|
||||
import com.google.android.gms.maps.model.Marker;
|
||||
import com.google.android.gms.maps.model.MarkerOptions;
|
||||
import com.google.maps.android.R;
|
||||
import com.google.maps.android.clustering.Cluster;
|
||||
import com.google.maps.android.clustering.ClusterItem;
|
||||
import com.google.maps.android.clustering.ClusterManager;
|
||||
import com.google.maps.android.collections.MarkerManager;
|
||||
import com.google.maps.android.geometry.Point;
|
||||
import com.google.maps.android.projection.SphericalMercatorProjection;
|
||||
import com.google.maps.android.ui.IconGenerator;
|
||||
import com.google.maps.android.ui.SquareTextView;
|
||||
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.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/* JADX INFO: loaded from: classes2.dex */
|
||||
public class DefaultClusterRenderer<T extends ClusterItem> implements ClusterRenderer<T> {
|
||||
private ClusterManager.OnClusterClickListener<T> mClickListener;
|
||||
private final ClusterManager<T> mClusterManager;
|
||||
private MarkerCache<Cluster<T>> mClusterMarkerCache;
|
||||
private Set<? extends Cluster<T>> mClusters;
|
||||
private ShapeDrawable mColoredCircleBackground;
|
||||
private final float mDensity;
|
||||
private final IconGenerator mIconGenerator;
|
||||
private ClusterManager.OnClusterInfoWindowClickListener<T> mInfoWindowClickListener;
|
||||
private ClusterManager.OnClusterInfoWindowLongClickListener<T> mInfoWindowLongClickListener;
|
||||
private ClusterManager.OnClusterItemClickListener<T> mItemClickListener;
|
||||
private ClusterManager.OnClusterItemInfoWindowClickListener<T> mItemInfoWindowClickListener;
|
||||
private ClusterManager.OnClusterItemInfoWindowLongClickListener<T> mItemInfoWindowLongClickListener;
|
||||
private final GoogleMap mMap;
|
||||
private MarkerCache<T> mMarkerCache;
|
||||
private final DefaultClusterRenderer<T>.ViewModifier mViewModifier;
|
||||
private float mZoom;
|
||||
private static final int[] BUCKETS = {10, 20, 50, 100, ComposerKt.invocationKey, 500, 1000};
|
||||
private static final TimeInterpolator ANIMATION_INTERP = new DecelerateInterpolator();
|
||||
private final Executor mExecutor = Executors.newSingleThreadExecutor();
|
||||
private Set<MarkerWithPosition> mMarkers = Collections.newSetFromMap(new ConcurrentHashMap());
|
||||
private SparseArray<BitmapDescriptor> mIcons = new SparseArray<>();
|
||||
private int mMinClusterSize = 4;
|
||||
private boolean mAnimate = true;
|
||||
private long mAnimationDurationMs = 300;
|
||||
|
||||
protected void onClusterItemRendered(T t, Marker marker) {
|
||||
}
|
||||
|
||||
protected void onClusterRendered(Cluster<T> cluster, Marker marker) {
|
||||
}
|
||||
|
||||
public DefaultClusterRenderer(Context context, GoogleMap googleMap, ClusterManager<T> clusterManager) {
|
||||
this.mMarkerCache = new MarkerCache<>();
|
||||
this.mClusterMarkerCache = new MarkerCache<>();
|
||||
this.mViewModifier = new ViewModifier();
|
||||
this.mMap = googleMap;
|
||||
this.mDensity = context.getResources().getDisplayMetrics().density;
|
||||
IconGenerator iconGenerator = new IconGenerator(context);
|
||||
this.mIconGenerator = iconGenerator;
|
||||
iconGenerator.setContentView(makeSquareTextView(context));
|
||||
iconGenerator.setTextAppearance(R.style.amu_ClusterIcon_TextAppearance);
|
||||
iconGenerator.setBackground(makeClusterBackground());
|
||||
this.mClusterManager = clusterManager;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void onAdd() {
|
||||
this.mClusterManager.getMarkerCollection().setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { // from class: com.google.maps.android.clustering.view.DefaultClusterRenderer.1
|
||||
/* JADX WARN: Multi-variable type inference failed */
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnMarkerClickListener
|
||||
public boolean onMarkerClick(Marker marker) {
|
||||
return DefaultClusterRenderer.this.mItemClickListener != null && DefaultClusterRenderer.this.mItemClickListener.onClusterItemClick((ClusterItem) DefaultClusterRenderer.this.mMarkerCache.get(marker));
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getMarkerCollection().setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { // from class: com.google.maps.android.clustering.view.DefaultClusterRenderer.2
|
||||
/* JADX WARN: Multi-variable type inference failed */
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener
|
||||
public void onInfoWindowClick(Marker marker) {
|
||||
if (DefaultClusterRenderer.this.mItemInfoWindowClickListener != null) {
|
||||
DefaultClusterRenderer.this.mItemInfoWindowClickListener.onClusterItemInfoWindowClick((ClusterItem) DefaultClusterRenderer.this.mMarkerCache.get(marker));
|
||||
}
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getMarkerCollection().setOnInfoWindowLongClickListener(new GoogleMap.OnInfoWindowLongClickListener() { // from class: com.google.maps.android.clustering.view.DefaultClusterRenderer$$ExternalSyntheticLambda0
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowLongClickListener
|
||||
public final void onInfoWindowLongClick(Marker marker) {
|
||||
this.f$0.m7759x54249de(marker);
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { // from class: com.google.maps.android.clustering.view.DefaultClusterRenderer$$ExternalSyntheticLambda1
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnMarkerClickListener
|
||||
public final boolean onMarkerClick(Marker marker) {
|
||||
return this.f$0.m7760x83a34dbd(marker);
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { // from class: com.google.maps.android.clustering.view.DefaultClusterRenderer$$ExternalSyntheticLambda2
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener
|
||||
public final void onInfoWindowClick(Marker marker) {
|
||||
this.f$0.m7761x204519c(marker);
|
||||
}
|
||||
});
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnInfoWindowLongClickListener(new GoogleMap.OnInfoWindowLongClickListener() { // from class: com.google.maps.android.clustering.view.DefaultClusterRenderer$$ExternalSyntheticLambda3
|
||||
@Override // com.google.android.gms.maps.GoogleMap.OnInfoWindowLongClickListener
|
||||
public final void onInfoWindowLongClick(Marker marker) {
|
||||
this.f$0.m7762x8065557b(marker);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$onAdd$0$com-google-maps-android-clustering-view-DefaultClusterRenderer, reason: not valid java name */
|
||||
/* synthetic */ void m7759x54249de(Marker marker) {
|
||||
ClusterManager.OnClusterItemInfoWindowLongClickListener<T> onClusterItemInfoWindowLongClickListener = this.mItemInfoWindowLongClickListener;
|
||||
if (onClusterItemInfoWindowLongClickListener != null) {
|
||||
onClusterItemInfoWindowLongClickListener.onClusterItemInfoWindowLongClick(this.mMarkerCache.get(marker));
|
||||
}
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$onAdd$1$com-google-maps-android-clustering-view-DefaultClusterRenderer, reason: not valid java name */
|
||||
/* synthetic */ boolean m7760x83a34dbd(Marker marker) {
|
||||
ClusterManager.OnClusterClickListener<T> onClusterClickListener = this.mClickListener;
|
||||
return onClusterClickListener != null && onClusterClickListener.onClusterClick(this.mClusterMarkerCache.get(marker));
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$onAdd$2$com-google-maps-android-clustering-view-DefaultClusterRenderer, reason: not valid java name */
|
||||
/* synthetic */ void m7761x204519c(Marker marker) {
|
||||
ClusterManager.OnClusterInfoWindowClickListener<T> onClusterInfoWindowClickListener = this.mInfoWindowClickListener;
|
||||
if (onClusterInfoWindowClickListener != null) {
|
||||
onClusterInfoWindowClickListener.onClusterInfoWindowClick(this.mClusterMarkerCache.get(marker));
|
||||
}
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$onAdd$3$com-google-maps-android-clustering-view-DefaultClusterRenderer, reason: not valid java name */
|
||||
/* synthetic */ void m7762x8065557b(Marker marker) {
|
||||
ClusterManager.OnClusterInfoWindowLongClickListener<T> onClusterInfoWindowLongClickListener = this.mInfoWindowLongClickListener;
|
||||
if (onClusterInfoWindowLongClickListener != null) {
|
||||
onClusterInfoWindowLongClickListener.onClusterInfoWindowLongClick(this.mClusterMarkerCache.get(marker));
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void onRemove() {
|
||||
this.mClusterManager.getMarkerCollection().setOnMarkerClickListener(null);
|
||||
this.mClusterManager.getMarkerCollection().setOnInfoWindowClickListener(null);
|
||||
this.mClusterManager.getMarkerCollection().setOnInfoWindowLongClickListener(null);
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnMarkerClickListener(null);
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnInfoWindowClickListener(null);
|
||||
this.mClusterManager.getClusterMarkerCollection().setOnInfoWindowLongClickListener(null);
|
||||
}
|
||||
|
||||
private LayerDrawable makeClusterBackground() {
|
||||
this.mColoredCircleBackground = new ShapeDrawable(new OvalShape());
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
|
||||
shapeDrawable.getPaint().setColor(-2130706433);
|
||||
LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{shapeDrawable, this.mColoredCircleBackground});
|
||||
int i = (int) (this.mDensity * 3.0f);
|
||||
layerDrawable.setLayerInset(1, i, i, i, i);
|
||||
return layerDrawable;
|
||||
}
|
||||
|
||||
private SquareTextView makeSquareTextView(Context context) {
|
||||
SquareTextView squareTextView = new SquareTextView(context);
|
||||
squareTextView.setLayoutParams(new ViewGroup.LayoutParams(-2, -2));
|
||||
squareTextView.setId(R.id.amu_text);
|
||||
int i = (int) (this.mDensity * 12.0f);
|
||||
squareTextView.setPadding(i, i, i, i);
|
||||
return squareTextView;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public int getColor(int i) {
|
||||
float fMin = 300.0f - Math.min(i, 300.0f);
|
||||
return Color.HSVToColor(new float[]{((fMin * fMin) / 90000.0f) * 220.0f, 1.0f, 0.6f});
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public int getClusterTextAppearance(int i) {
|
||||
return R.style.amu_ClusterIcon_TextAppearance;
|
||||
}
|
||||
|
||||
protected String getClusterText(int i) {
|
||||
if (i < BUCKETS[0]) {
|
||||
return String.valueOf(i);
|
||||
}
|
||||
return i + org.slf4j.Marker.ANY_NON_NULL_MARKER;
|
||||
}
|
||||
|
||||
protected int getBucket(Cluster<T> cluster) {
|
||||
int size = cluster.getSize();
|
||||
int i = 0;
|
||||
if (size <= BUCKETS[0]) {
|
||||
return size;
|
||||
}
|
||||
while (true) {
|
||||
int[] iArr = BUCKETS;
|
||||
if (i < iArr.length - 1) {
|
||||
int i2 = i + 1;
|
||||
if (size < iArr[i2]) {
|
||||
return iArr[i];
|
||||
}
|
||||
i = i2;
|
||||
} else {
|
||||
return iArr[iArr.length - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getMinClusterSize() {
|
||||
return this.mMinClusterSize;
|
||||
}
|
||||
|
||||
public void setMinClusterSize(int i) {
|
||||
this.mMinClusterSize = i;
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
class ViewModifier extends Handler {
|
||||
private static final int RUN_TASK = 0;
|
||||
private static final int TASK_FINISHED = 1;
|
||||
private DefaultClusterRenderer<T>.RenderTask mNextClusters;
|
||||
private boolean mViewModificationInProgress;
|
||||
|
||||
private ViewModifier() {
|
||||
this.mViewModificationInProgress = false;
|
||||
this.mNextClusters = null;
|
||||
}
|
||||
|
||||
@Override // android.os.Handler
|
||||
public void handleMessage(Message message) {
|
||||
DefaultClusterRenderer<T>.RenderTask renderTask;
|
||||
if (message.what == 1) {
|
||||
this.mViewModificationInProgress = false;
|
||||
if (this.mNextClusters != null) {
|
||||
sendEmptyMessage(0);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
removeMessages(0);
|
||||
if (this.mViewModificationInProgress || this.mNextClusters == null) {
|
||||
return;
|
||||
}
|
||||
Projection projection = DefaultClusterRenderer.this.mMap.getProjection();
|
||||
synchronized (this) {
|
||||
renderTask = this.mNextClusters;
|
||||
this.mNextClusters = null;
|
||||
this.mViewModificationInProgress = true;
|
||||
}
|
||||
renderTask.setCallback(new Runnable() { // from class: com.google.maps.android.clustering.view.DefaultClusterRenderer$ViewModifier$$ExternalSyntheticLambda0
|
||||
@Override // java.lang.Runnable
|
||||
public final void run() {
|
||||
this.f$0.m7763xef9a7a7f();
|
||||
}
|
||||
});
|
||||
renderTask.setProjection(projection);
|
||||
renderTask.setMapZoom(DefaultClusterRenderer.this.mMap.getCameraPosition().zoom);
|
||||
DefaultClusterRenderer.this.mExecutor.execute(renderTask);
|
||||
}
|
||||
|
||||
/* JADX INFO: renamed from: lambda$handleMessage$0$com-google-maps-android-clustering-view-DefaultClusterRenderer$ViewModifier, reason: not valid java name */
|
||||
/* synthetic */ void m7763xef9a7a7f() {
|
||||
sendEmptyMessage(1);
|
||||
}
|
||||
|
||||
public void queue(Set<? extends Cluster<T>> set) {
|
||||
synchronized (this) {
|
||||
this.mNextClusters = new RenderTask(set);
|
||||
}
|
||||
sendEmptyMessage(0);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldRenderAsCluster(Cluster<T> cluster) {
|
||||
return cluster.getSize() >= this.mMinClusterSize;
|
||||
}
|
||||
|
||||
protected boolean shouldRender(Set<? extends Cluster<T>> set, Set<? extends Cluster<T>> set2) {
|
||||
return !set2.equals(set);
|
||||
}
|
||||
|
||||
private class RenderTask implements Runnable {
|
||||
final Set<? extends Cluster<T>> clusters;
|
||||
private Runnable mCallback;
|
||||
private float mMapZoom;
|
||||
private Projection mProjection;
|
||||
private SphericalMercatorProjection mSphericalMercatorProjection;
|
||||
|
||||
private RenderTask(Set<? extends Cluster<T>> set) {
|
||||
this.clusters = set;
|
||||
}
|
||||
|
||||
public void setCallback(Runnable runnable) {
|
||||
this.mCallback = runnable;
|
||||
}
|
||||
|
||||
public void setProjection(Projection projection) {
|
||||
this.mProjection = projection;
|
||||
}
|
||||
|
||||
public void setMapZoom(float f) {
|
||||
this.mMapZoom = f;
|
||||
this.mSphericalMercatorProjection = new SphericalMercatorProjection(Math.pow(2.0d, Math.min(f, DefaultClusterRenderer.this.mZoom)) * 256.0d);
|
||||
}
|
||||
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
LatLngBounds latLngBoundsBuild;
|
||||
ArrayList arrayList;
|
||||
DefaultClusterRenderer defaultClusterRenderer = DefaultClusterRenderer.this;
|
||||
if (!defaultClusterRenderer.shouldRender(defaultClusterRenderer.immutableOf(defaultClusterRenderer.mClusters), DefaultClusterRenderer.this.immutableOf(this.clusters))) {
|
||||
this.mCallback.run();
|
||||
return;
|
||||
}
|
||||
ArrayList arrayList2 = null;
|
||||
MarkerModifier markerModifier = new MarkerModifier();
|
||||
float f = this.mMapZoom;
|
||||
boolean z = f > DefaultClusterRenderer.this.mZoom;
|
||||
float f2 = f - DefaultClusterRenderer.this.mZoom;
|
||||
Set<MarkerWithPosition> set = DefaultClusterRenderer.this.mMarkers;
|
||||
try {
|
||||
latLngBoundsBuild = this.mProjection.getVisibleRegion().latLngBounds;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
latLngBoundsBuild = LatLngBounds.builder().include(new LatLng(0.0d, 0.0d)).build();
|
||||
}
|
||||
if (DefaultClusterRenderer.this.mClusters == null || !DefaultClusterRenderer.this.mAnimate) {
|
||||
arrayList = null;
|
||||
} else {
|
||||
arrayList = new ArrayList();
|
||||
for (Cluster<T> cluster : DefaultClusterRenderer.this.mClusters) {
|
||||
if (DefaultClusterRenderer.this.shouldRenderAsCluster(cluster) && latLngBoundsBuild.contains(cluster.getPosition())) {
|
||||
arrayList.add(this.mSphericalMercatorProjection.toPoint(cluster.getPosition()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Set setNewSetFromMap = Collections.newSetFromMap(new ConcurrentHashMap());
|
||||
for (Cluster<T> cluster2 : this.clusters) {
|
||||
boolean zContains = latLngBoundsBuild.contains(cluster2.getPosition());
|
||||
if (z && zContains && DefaultClusterRenderer.this.mAnimate) {
|
||||
Point pointFindClosestCluster = DefaultClusterRenderer.this.findClosestCluster(arrayList, this.mSphericalMercatorProjection.toPoint(cluster2.getPosition()));
|
||||
if (pointFindClosestCluster != null) {
|
||||
markerModifier.add(true, new CreateMarkerTask(cluster2, setNewSetFromMap, this.mSphericalMercatorProjection.toLatLng(pointFindClosestCluster)));
|
||||
} else {
|
||||
markerModifier.add(true, new CreateMarkerTask(cluster2, setNewSetFromMap, null));
|
||||
}
|
||||
} else {
|
||||
markerModifier.add(zContains, new CreateMarkerTask(cluster2, setNewSetFromMap, null));
|
||||
}
|
||||
}
|
||||
markerModifier.waitUntilFree();
|
||||
set.removeAll(setNewSetFromMap);
|
||||
if (DefaultClusterRenderer.this.mAnimate) {
|
||||
arrayList2 = new ArrayList();
|
||||
for (Cluster<T> cluster3 : this.clusters) {
|
||||
if (DefaultClusterRenderer.this.shouldRenderAsCluster(cluster3) && latLngBoundsBuild.contains(cluster3.getPosition())) {
|
||||
arrayList2.add(this.mSphericalMercatorProjection.toPoint(cluster3.getPosition()));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (MarkerWithPosition markerWithPosition : set) {
|
||||
boolean zContains2 = latLngBoundsBuild.contains(markerWithPosition.position);
|
||||
if (!z && f2 > -3.0f && zContains2 && DefaultClusterRenderer.this.mAnimate) {
|
||||
Point pointFindClosestCluster2 = DefaultClusterRenderer.this.findClosestCluster(arrayList2, this.mSphericalMercatorProjection.toPoint(markerWithPosition.position));
|
||||
if (pointFindClosestCluster2 != null) {
|
||||
markerModifier.animateThenRemove(markerWithPosition, markerWithPosition.position, this.mSphericalMercatorProjection.toLatLng(pointFindClosestCluster2));
|
||||
} else {
|
||||
markerModifier.remove(true, markerWithPosition.marker);
|
||||
}
|
||||
} else {
|
||||
markerModifier.remove(zContains2, markerWithPosition.marker);
|
||||
}
|
||||
}
|
||||
markerModifier.waitUntilFree();
|
||||
DefaultClusterRenderer.this.mMarkers = setNewSetFromMap;
|
||||
DefaultClusterRenderer.this.mClusters = this.clusters;
|
||||
DefaultClusterRenderer.this.mZoom = f;
|
||||
this.mCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void onClustersChanged(Set<? extends Cluster<T>> set) {
|
||||
this.mViewModifier.queue(set);
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterClickListener(ClusterManager.OnClusterClickListener<T> onClusterClickListener) {
|
||||
this.mClickListener = onClusterClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterInfoWindowClickListener(ClusterManager.OnClusterInfoWindowClickListener<T> onClusterInfoWindowClickListener) {
|
||||
this.mInfoWindowClickListener = onClusterInfoWindowClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterInfoWindowLongClickListener(ClusterManager.OnClusterInfoWindowLongClickListener<T> onClusterInfoWindowLongClickListener) {
|
||||
this.mInfoWindowLongClickListener = onClusterInfoWindowLongClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterItemClickListener(ClusterManager.OnClusterItemClickListener<T> onClusterItemClickListener) {
|
||||
this.mItemClickListener = onClusterItemClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterItemInfoWindowClickListener(ClusterManager.OnClusterItemInfoWindowClickListener<T> onClusterItemInfoWindowClickListener) {
|
||||
this.mItemInfoWindowClickListener = onClusterItemInfoWindowClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setOnClusterItemInfoWindowLongClickListener(ClusterManager.OnClusterItemInfoWindowLongClickListener<T> onClusterItemInfoWindowLongClickListener) {
|
||||
this.mItemInfoWindowLongClickListener = onClusterItemInfoWindowLongClickListener;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setAnimation(boolean z) {
|
||||
this.mAnimate = z;
|
||||
}
|
||||
|
||||
@Override // com.google.maps.android.clustering.view.ClusterRenderer
|
||||
public void setAnimationDuration(long j) {
|
||||
this.mAnimationDurationMs = j;
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public Set<? extends Cluster<T>> immutableOf(Set<? extends Cluster<T>> set) {
|
||||
return set != null ? Collections.unmodifiableSet(set) : Collections.emptySet();
|
||||
}
|
||||
|
||||
private static double distanceSquared(Point point, Point point2) {
|
||||
return ((point.x - point2.x) * (point.x - point2.x)) + ((point.y - point2.y) * (point.y - point2.y));
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public Point findClosestCluster(List<Point> list, Point point) {
|
||||
Point point2 = null;
|
||||
if (list != null && !list.isEmpty()) {
|
||||
int maxDistanceBetweenClusteredItems = this.mClusterManager.getAlgorithm().getMaxDistanceBetweenClusteredItems();
|
||||
double d = maxDistanceBetweenClusteredItems * maxDistanceBetweenClusteredItems;
|
||||
for (Point point3 : list) {
|
||||
double dDistanceSquared = distanceSquared(point3, point);
|
||||
if (dDistanceSquared < d) {
|
||||
point2 = point3;
|
||||
d = dDistanceSquared;
|
||||
}
|
||||
}
|
||||
}
|
||||
return point2;
|
||||
}
|
||||
|
||||
private class MarkerModifier extends Handler implements MessageQueue.IdleHandler {
|
||||
private static final int BLANK = 0;
|
||||
private final Condition busyCondition;
|
||||
private final Lock lock;
|
||||
private Queue<DefaultClusterRenderer<T>.AnimationTask> mAnimationTasks;
|
||||
private Queue<DefaultClusterRenderer<T>.CreateMarkerTask> mCreateMarkerTasks;
|
||||
private boolean mListenerAdded;
|
||||
private Queue<DefaultClusterRenderer<T>.CreateMarkerTask> mOnScreenCreateMarkerTasks;
|
||||
private Queue<Marker> mOnScreenRemoveMarkerTasks;
|
||||
private Queue<Marker> mRemoveMarkerTasks;
|
||||
|
||||
private MarkerModifier() {
|
||||
super(Looper.getMainLooper());
|
||||
ReentrantLock reentrantLock = new ReentrantLock();
|
||||
this.lock = reentrantLock;
|
||||
this.busyCondition = reentrantLock.newCondition();
|
||||
this.mCreateMarkerTasks = new LinkedList();
|
||||
this.mOnScreenCreateMarkerTasks = new LinkedList();
|
||||
this.mRemoveMarkerTasks = new LinkedList();
|
||||
this.mOnScreenRemoveMarkerTasks = new LinkedList();
|
||||
this.mAnimationTasks = new LinkedList();
|
||||
}
|
||||
|
||||
public void add(boolean z, DefaultClusterRenderer<T>.CreateMarkerTask createMarkerTask) {
|
||||
this.lock.lock();
|
||||
sendEmptyMessage(0);
|
||||
if (z) {
|
||||
this.mOnScreenCreateMarkerTasks.add(createMarkerTask);
|
||||
} else {
|
||||
this.mCreateMarkerTasks.add(createMarkerTask);
|
||||
}
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
public void remove(boolean z, Marker marker) {
|
||||
this.lock.lock();
|
||||
sendEmptyMessage(0);
|
||||
if (z) {
|
||||
this.mOnScreenRemoveMarkerTasks.add(marker);
|
||||
} else {
|
||||
this.mRemoveMarkerTasks.add(marker);
|
||||
}
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
public void animate(MarkerWithPosition markerWithPosition, LatLng latLng, LatLng latLng2) {
|
||||
this.lock.lock();
|
||||
this.mAnimationTasks.add(new AnimationTask(markerWithPosition, latLng, latLng2));
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
public void animateThenRemove(MarkerWithPosition markerWithPosition, LatLng latLng, LatLng latLng2) {
|
||||
this.lock.lock();
|
||||
DefaultClusterRenderer<T>.AnimationTask animationTask = new AnimationTask(markerWithPosition, latLng, latLng2);
|
||||
animationTask.removeOnAnimationComplete(DefaultClusterRenderer.this.mClusterManager.getMarkerManager());
|
||||
this.mAnimationTasks.add(animationTask);
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
@Override // android.os.Handler
|
||||
public void handleMessage(Message message) {
|
||||
if (!this.mListenerAdded) {
|
||||
Looper.myQueue().addIdleHandler(this);
|
||||
this.mListenerAdded = true;
|
||||
}
|
||||
removeMessages(0);
|
||||
this.lock.lock();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
performNextTask();
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
if (!isBusy()) {
|
||||
this.mListenerAdded = false;
|
||||
Looper.myQueue().removeIdleHandler(this);
|
||||
this.busyCondition.signalAll();
|
||||
} else {
|
||||
sendEmptyMessageDelayed(0, 10L);
|
||||
}
|
||||
}
|
||||
|
||||
private void performNextTask() {
|
||||
if (!this.mOnScreenRemoveMarkerTasks.isEmpty()) {
|
||||
removeMarker(this.mOnScreenRemoveMarkerTasks.poll());
|
||||
return;
|
||||
}
|
||||
if (!this.mAnimationTasks.isEmpty()) {
|
||||
this.mAnimationTasks.poll().perform();
|
||||
return;
|
||||
}
|
||||
if (this.mOnScreenCreateMarkerTasks.isEmpty()) {
|
||||
if (this.mCreateMarkerTasks.isEmpty()) {
|
||||
if (this.mRemoveMarkerTasks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
removeMarker(this.mRemoveMarkerTasks.poll());
|
||||
return;
|
||||
}
|
||||
this.mCreateMarkerTasks.poll().perform(this);
|
||||
return;
|
||||
}
|
||||
this.mOnScreenCreateMarkerTasks.poll().perform(this);
|
||||
}
|
||||
|
||||
private void removeMarker(Marker marker) {
|
||||
DefaultClusterRenderer.this.mMarkerCache.remove(marker);
|
||||
DefaultClusterRenderer.this.mClusterMarkerCache.remove(marker);
|
||||
DefaultClusterRenderer.this.mClusterManager.getMarkerManager().remove(marker);
|
||||
}
|
||||
|
||||
/* JADX WARN: Removed duplicated region for block: B:14:0x0030 */
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
public boolean isBusy() {
|
||||
/*
|
||||
r2 = this;
|
||||
java.util.concurrent.locks.Lock r0 = r2.lock // Catch: java.lang.Throwable -> L37
|
||||
r0.lock() // Catch: java.lang.Throwable -> L37
|
||||
java.util.Queue<com.google.maps.android.clustering.view.DefaultClusterRenderer<T>$CreateMarkerTask> r0 = r2.mCreateMarkerTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 == 0) goto L30
|
||||
java.util.Queue<com.google.maps.android.clustering.view.DefaultClusterRenderer<T>$CreateMarkerTask> r0 = r2.mOnScreenCreateMarkerTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 == 0) goto L30
|
||||
java.util.Queue<com.google.android.gms.maps.model.Marker> r0 = r2.mOnScreenRemoveMarkerTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 == 0) goto L30
|
||||
java.util.Queue<com.google.android.gms.maps.model.Marker> r0 = r2.mRemoveMarkerTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 == 0) goto L30
|
||||
java.util.Queue<com.google.maps.android.clustering.view.DefaultClusterRenderer<T>$AnimationTask> r0 = r2.mAnimationTasks // Catch: java.lang.Throwable -> L37
|
||||
boolean r0 = r0.isEmpty() // Catch: java.lang.Throwable -> L37
|
||||
if (r0 != 0) goto L2e
|
||||
goto L30
|
||||
L2e:
|
||||
r0 = 0
|
||||
goto L31
|
||||
L30:
|
||||
r0 = 1
|
||||
L31:
|
||||
java.util.concurrent.locks.Lock r1 = r2.lock
|
||||
r1.unlock()
|
||||
return r0
|
||||
L37:
|
||||
r0 = move-exception
|
||||
java.util.concurrent.locks.Lock r1 = r2.lock
|
||||
r1.unlock()
|
||||
throw r0
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: com.google.maps.android.clustering.view.DefaultClusterRenderer.MarkerModifier.isBusy():boolean");
|
||||
}
|
||||
|
||||
public void waitUntilFree() {
|
||||
while (isBusy()) {
|
||||
sendEmptyMessage(0);
|
||||
this.lock.lock();
|
||||
try {
|
||||
try {
|
||||
if (isBusy()) {
|
||||
this.busyCondition.await();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override // android.os.MessageQueue.IdleHandler
|
||||
public boolean queueIdle() {
|
||||
sendEmptyMessage(0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MarkerCache<T> {
|
||||
private Map<T, Marker> mCache;
|
||||
private Map<Marker, T> mCacheReverse;
|
||||
|
||||
private MarkerCache() {
|
||||
this.mCache = new HashMap();
|
||||
this.mCacheReverse = new HashMap();
|
||||
}
|
||||
|
||||
public Marker get(T t) {
|
||||
return this.mCache.get(t);
|
||||
}
|
||||
|
||||
public T get(Marker marker) {
|
||||
return this.mCacheReverse.get(marker);
|
||||
}
|
||||
|
||||
public void put(T t, Marker marker) {
|
||||
this.mCache.put(t, marker);
|
||||
this.mCacheReverse.put(marker, t);
|
||||
}
|
||||
|
||||
public void remove(Marker marker) {
|
||||
T t = this.mCacheReverse.get(marker);
|
||||
this.mCacheReverse.remove(marker);
|
||||
this.mCache.remove(t);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onBeforeClusterItemRendered(T t, MarkerOptions markerOptions) {
|
||||
if (t.getTitle() != null && t.getSnippet() != null) {
|
||||
markerOptions.title(t.getTitle());
|
||||
markerOptions.snippet(t.getSnippet());
|
||||
} else if (t.getTitle() != null) {
|
||||
markerOptions.title(t.getTitle());
|
||||
} else if (t.getSnippet() != null) {
|
||||
markerOptions.title(t.getSnippet());
|
||||
}
|
||||
}
|
||||
|
||||
protected void onClusterItemUpdated(T t, Marker marker) {
|
||||
boolean z = true;
|
||||
boolean z2 = false;
|
||||
if (t.getTitle() != null && t.getSnippet() != null) {
|
||||
if (!t.getTitle().equals(marker.getTitle())) {
|
||||
marker.setTitle(t.getTitle());
|
||||
z2 = true;
|
||||
}
|
||||
if (!t.getSnippet().equals(marker.getSnippet())) {
|
||||
marker.setSnippet(t.getSnippet());
|
||||
z2 = true;
|
||||
}
|
||||
} else {
|
||||
if (t.getSnippet() != null && !t.getSnippet().equals(marker.getTitle())) {
|
||||
marker.setTitle(t.getSnippet());
|
||||
} else if (t.getTitle() != null && !t.getTitle().equals(marker.getTitle())) {
|
||||
marker.setTitle(t.getTitle());
|
||||
}
|
||||
z2 = true;
|
||||
}
|
||||
if (marker.getPosition().equals(t.getPosition())) {
|
||||
z = z2;
|
||||
} else {
|
||||
marker.setPosition(t.getPosition());
|
||||
if (t.getZIndex() != null) {
|
||||
marker.setZIndex(t.getZIndex().floatValue());
|
||||
}
|
||||
}
|
||||
if (z && marker.isInfoWindowShown()) {
|
||||
marker.showInfoWindow();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onBeforeClusterRendered(Cluster<T> cluster, MarkerOptions markerOptions) {
|
||||
markerOptions.icon(getDescriptorForCluster(cluster));
|
||||
}
|
||||
|
||||
protected BitmapDescriptor getDescriptorForCluster(Cluster<T> cluster) {
|
||||
int bucket = getBucket(cluster);
|
||||
BitmapDescriptor bitmapDescriptor = this.mIcons.get(bucket);
|
||||
if (bitmapDescriptor != null) {
|
||||
return bitmapDescriptor;
|
||||
}
|
||||
this.mColoredCircleBackground.getPaint().setColor(getColor(bucket));
|
||||
this.mIconGenerator.setTextAppearance(getClusterTextAppearance(bucket));
|
||||
BitmapDescriptor bitmapDescriptorFromBitmap = BitmapDescriptorFactory.fromBitmap(this.mIconGenerator.makeIcon(getClusterText(bucket)));
|
||||
this.mIcons.put(bucket, bitmapDescriptorFromBitmap);
|
||||
return bitmapDescriptorFromBitmap;
|
||||
}
|
||||
|
||||
protected void onClusterUpdated(Cluster<T> cluster, Marker marker) {
|
||||
marker.setIcon(getDescriptorForCluster(cluster));
|
||||
}
|
||||
|
||||
public Marker getMarker(T t) {
|
||||
return this.mMarkerCache.get(t);
|
||||
}
|
||||
|
||||
public T getClusterItem(Marker marker) {
|
||||
return this.mMarkerCache.get(marker);
|
||||
}
|
||||
|
||||
public Marker getMarker(Cluster<T> cluster) {
|
||||
return this.mClusterMarkerCache.get(cluster);
|
||||
}
|
||||
|
||||
public Cluster<T> getCluster(Marker marker) {
|
||||
return this.mClusterMarkerCache.get(marker);
|
||||
}
|
||||
|
||||
private class CreateMarkerTask {
|
||||
private final LatLng animateFrom;
|
||||
private final Cluster<T> cluster;
|
||||
private final Set<MarkerWithPosition> newMarkers;
|
||||
|
||||
public CreateMarkerTask(Cluster<T> cluster, Set<MarkerWithPosition> set, LatLng latLng) {
|
||||
this.cluster = cluster;
|
||||
this.newMarkers = set;
|
||||
this.animateFrom = latLng;
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public void perform(DefaultClusterRenderer<T>.MarkerModifier markerModifier) {
|
||||
MarkerWithPosition markerWithPosition;
|
||||
MarkerWithPosition markerWithPosition2;
|
||||
if (DefaultClusterRenderer.this.shouldRenderAsCluster(this.cluster)) {
|
||||
Marker markerAddMarker = DefaultClusterRenderer.this.mClusterMarkerCache.get(this.cluster);
|
||||
if (markerAddMarker == null) {
|
||||
MarkerOptions markerOptions = new MarkerOptions();
|
||||
LatLng position = this.animateFrom;
|
||||
if (position == null) {
|
||||
position = this.cluster.getPosition();
|
||||
}
|
||||
MarkerOptions markerOptionsPosition = markerOptions.position(position);
|
||||
DefaultClusterRenderer.this.onBeforeClusterRendered(this.cluster, markerOptionsPosition);
|
||||
markerAddMarker = DefaultClusterRenderer.this.mClusterManager.getClusterMarkerCollection().addMarker(markerOptionsPosition);
|
||||
DefaultClusterRenderer.this.mClusterMarkerCache.put(this.cluster, markerAddMarker);
|
||||
markerWithPosition = new MarkerWithPosition(markerAddMarker);
|
||||
LatLng latLng = this.animateFrom;
|
||||
if (latLng != null) {
|
||||
markerModifier.animate(markerWithPosition, latLng, this.cluster.getPosition());
|
||||
}
|
||||
} else {
|
||||
markerWithPosition = new MarkerWithPosition(markerAddMarker);
|
||||
DefaultClusterRenderer.this.onClusterUpdated(this.cluster, markerAddMarker);
|
||||
}
|
||||
DefaultClusterRenderer.this.onClusterRendered(this.cluster, markerAddMarker);
|
||||
this.newMarkers.add(markerWithPosition);
|
||||
return;
|
||||
}
|
||||
for (T t : this.cluster.getItems()) {
|
||||
Marker markerAddMarker2 = DefaultClusterRenderer.this.mMarkerCache.get(t);
|
||||
if (markerAddMarker2 == null) {
|
||||
MarkerOptions markerOptions2 = new MarkerOptions();
|
||||
LatLng latLng2 = this.animateFrom;
|
||||
if (latLng2 != null) {
|
||||
markerOptions2.position(latLng2);
|
||||
} else {
|
||||
markerOptions2.position(t.getPosition());
|
||||
if (t.getZIndex() != null) {
|
||||
markerOptions2.zIndex(t.getZIndex().floatValue());
|
||||
}
|
||||
}
|
||||
DefaultClusterRenderer.this.onBeforeClusterItemRendered(t, markerOptions2);
|
||||
markerAddMarker2 = DefaultClusterRenderer.this.mClusterManager.getMarkerCollection().addMarker(markerOptions2);
|
||||
markerWithPosition2 = new MarkerWithPosition(markerAddMarker2);
|
||||
DefaultClusterRenderer.this.mMarkerCache.put(t, markerAddMarker2);
|
||||
LatLng latLng3 = this.animateFrom;
|
||||
if (latLng3 != null) {
|
||||
markerModifier.animate(markerWithPosition2, latLng3, t.getPosition());
|
||||
}
|
||||
} else {
|
||||
markerWithPosition2 = new MarkerWithPosition(markerAddMarker2);
|
||||
DefaultClusterRenderer.this.onClusterItemUpdated(t, markerAddMarker2);
|
||||
}
|
||||
DefaultClusterRenderer.this.onClusterItemRendered(t, markerAddMarker2);
|
||||
this.newMarkers.add(markerWithPosition2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MarkerWithPosition {
|
||||
private final Marker marker;
|
||||
private LatLng position;
|
||||
|
||||
private MarkerWithPosition(Marker marker) {
|
||||
this.marker = marker;
|
||||
this.position = marker.getPosition();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof MarkerWithPosition) {
|
||||
return this.marker.equals(((MarkerWithPosition) obj).marker);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.marker.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private class AnimationTask extends AnimatorListenerAdapter implements ValueAnimator.AnimatorUpdateListener {
|
||||
private final LatLng from;
|
||||
private MarkerManager mMarkerManager;
|
||||
private boolean mRemoveOnComplete;
|
||||
private final Marker marker;
|
||||
private final MarkerWithPosition markerWithPosition;
|
||||
private final LatLng to;
|
||||
|
||||
private AnimationTask(MarkerWithPosition markerWithPosition, LatLng latLng, LatLng latLng2) {
|
||||
this.markerWithPosition = markerWithPosition;
|
||||
this.marker = markerWithPosition.marker;
|
||||
this.from = latLng;
|
||||
this.to = latLng2;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
ValueAnimator valueAnimatorOfFloat = ValueAnimator.ofFloat(0.0f, 1.0f);
|
||||
valueAnimatorOfFloat.setInterpolator(DefaultClusterRenderer.ANIMATION_INTERP);
|
||||
valueAnimatorOfFloat.setDuration(DefaultClusterRenderer.this.mAnimationDurationMs);
|
||||
valueAnimatorOfFloat.addUpdateListener(this);
|
||||
valueAnimatorOfFloat.addListener(this);
|
||||
valueAnimatorOfFloat.start();
|
||||
}
|
||||
|
||||
@Override // android.animation.AnimatorListenerAdapter, android.animation.Animator.AnimatorListener
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
if (this.mRemoveOnComplete) {
|
||||
DefaultClusterRenderer.this.mMarkerCache.remove(this.marker);
|
||||
DefaultClusterRenderer.this.mClusterMarkerCache.remove(this.marker);
|
||||
this.mMarkerManager.remove(this.marker);
|
||||
}
|
||||
this.markerWithPosition.position = this.to;
|
||||
}
|
||||
|
||||
public void removeOnAnimationComplete(MarkerManager markerManager) {
|
||||
this.mMarkerManager = markerManager;
|
||||
this.mRemoveOnComplete = true;
|
||||
}
|
||||
|
||||
@Override // android.animation.ValueAnimator.AnimatorUpdateListener
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
if (this.to == null || this.from == null || this.marker == null) {
|
||||
return;
|
||||
}
|
||||
double animatedFraction = valueAnimator.getAnimatedFraction();
|
||||
double d = ((this.to.latitude - this.from.latitude) * animatedFraction) + this.from.latitude;
|
||||
double dSignum = this.to.longitude - this.from.longitude;
|
||||
if (Math.abs(dSignum) > 180.0d) {
|
||||
dSignum -= Math.signum(dSignum) * 360.0d;
|
||||
}
|
||||
this.marker.setPosition(new LatLng(d, (dSignum * animatedFraction) + this.from.longitude));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user