see_you/ContactsPositionOverlay.java

917 lines
28 KiB
Java

package org.thinkname.ap.main;
import jade.util.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.thinkname.ap.R;
import org.thinkname.ap.contact.Contact;
import org.thinkname.ap.contact.ContactListChanges;
import org.thinkname.ap.contact.ContactLocation;
import org.thinkname.ap.contact.ContactManager;
import org.thinkname.ap.msn.MsnSessionManager;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint.FontMetrics;
import android.location.Location;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
/**
* Defines the overlay used to draw information over the map view.
* It allows drawing contacts position and provides functionalities for
* automatic zooming and centering of the map.
*/
public class ContactsPositionOverlay extends Overlay {
/**
* Instance of the Jade logger for debugging.
*/
private final Logger myLogger = Logger.getMyLogger(this.getClass().getName());
/**
* Upper threshold, used for automatic zooming adjustment. It is a squared distance defined as a percentage of screen width
*/
private int UPPER_THRESHOLD = 0;
/**
* Lower threshold, used for automatic zooming adjustment. It is a squared distance defined as a percentage of screen width
*/
private int LOWER_THRESHOLD = 0;
/**
* Controller used to perform map zooming and centering
*/
private MapController mapController;
/**
* Paint object, used for drawing.
*/
private Paint myPaint;
/**
* Bitmap object that shows the yellow paddle.
*/
private Bitmap ylwPaddle;
/** The blue paddle. */
private Bitmap bluePaddle;
/**
* Bitmap object that shows the blue baloon.
*/
private Bitmap blueBaloon;
/**
* Bitmap object that shows the highlight when selecting a contact in map mode
*/
private Bitmap highlight;
/**
* Resource object, stored for making quicker access to resource files
*/
private Resources appRes;
/**
* Map containing data describing the online contacts to be drawn and their status (checked/unchecked)
*/
private Map<String, ContactLayoutData> contactPositionMap;
/**
* Percentage defining the scroll area width with respect to screen width
*/
private static final float SCROLL_AREA_WIDTH_RATIO = 0.70f;
/**
* Percentage defining the scroll area height with respect to screen height
*/
private static final float SCROLL_AREA_HEIGHT_RATIO= 0.70f;
/**
* Percentage with respect to screen width for defining the upper threshold.
*/
private static final float UPPER_THRESHOLD_RATIO = 0.46f;
/**
* Percentage with respect to screen width for defining the lower threshold
*/
private static final float LOWER_THRESHOLD_RATIO = 0.35f;
/**
* Final width of the scrolling area in Pixel
*/
private int SCROLL_AREA_WIDTH=-1;
/**
* Final height of the scrolling area in Pixel
*/
private int SCROLL_AREA_HEIGHT=-1;
/**
* Map view object on which we draw the overlay
*/
private MapView myMapView;
/**
* Width of the map view on which we draw
*/
private int WIDTH=-1;
/**
* Height of the map view on which we draw
*/
private int HEIGHT=-1;
/**
* Constant used to for choosing zoom level. It means that zoom to max level is required
*/
private static final int ZOOM_MAX=0;
/**
* Constant used to for choosing zoom level. It means that zoom should be dynamically recomputed
*/
private static final int RECOMPUTE_ZOOM=1;
/**
* Constant used to for choosing zoom level. It means zoom shall not be recomputed
*/
private static final int NO_ZOOM=2;
/**
* The scrolling area (when exiting this area, scrolling is recomputed)
*/
private Rect scrollingArea;
private Context ctn;
private boolean focusState=false;
/**
* Instantiates a new contacts position overlay.
*
* @param cont current application context
* @param myMapView the map view on which the overlay is drawn
* @param ctn the file for accessing resources
*/
public ContactsPositionOverlay(Context cont, MapView myMapView, Resources ctn){
this.ctn = cont;
mapController = myMapView.getController();
//根据联网状态显示放大缩小
//if(!MainActivity.CONNECTSTATE.equals("CONNECT"))
//myMapView.setBuiltInZoomControls(true);
appRes= ctn;
myPaint = new Paint();
this.myMapView = myMapView;
scrollingArea= new Rect();
contactPositionMap = new HashMap<String,ContactLayoutData>() ;
ylwPaddle = BitmapFactory.decodeResource(appRes,R.drawable.ylw_circle);
highlight = BitmapFactory.decodeResource(appRes,R.drawable.checked);
blueBaloon = BitmapFactory.decodeResource(appRes,R.drawable.bluemessage);
bluePaddle = BitmapFactory.decodeResource(appRes,R.drawable.blu_circle);
}
/**
* Check if scrolling of the map view is needed or not. This basically means that
* the view should be centered.
*
* @return true centering is needed and false otherwise
*/
private boolean scrollingIsNeeded(){
Collection<ContactLayoutData> pointList = contactPositionMap.values();
for (Iterator<ContactLayoutData> iterator = pointList.iterator(); iterator.hasNext();) {
ContactLayoutData contactLayoutData = iterator.next();
if (contactLayoutData.isVisible && !scrollingArea.contains(contactLayoutData.positionOnScreen.x, contactLayoutData.positionOnScreen.y)){
return true;
}
}
return false;
}
/**
* Checks if zoom level should be recomputed according to current position of contacts on the map.
* It basically checks if the max squared distance between the midpoint and one of the contacts is greater than the given threshold.
* If only one contact is drawn, zoom level shall be set to max.
*
* @param params object containing the parameters computed from the current map view.
* @return value that indicates how zoom level should be changed (ZOOM_MAX, NO_ZOOM, RECOMPUTE_ZOOM)
*/
private int zoomChangeIsNeeded(PointClusterParams params){
int retval = NO_ZOOM;
int currentNumberOfPoints = getContactsOnline();
//If we have just one point left, we need to zoom to max level
if (currentNumberOfPoints == 1 && myMapView.getZoomLevel() < 21){
retval = ZOOM_MAX;
} else if (currentNumberOfPoints > 1){
//If we have many points compute the max squared distance from the midpoint
int maxDistSquared = getMaxDistSquared(contactPositionMap.values(), params.midpointOnScreen);
//if we are in the too far or too near range
if (maxDistSquared < LOWER_THRESHOLD || maxDistSquared > UPPER_THRESHOLD){
retval = RECOMPUTE_ZOOM;
}
}
return retval;
}
/**
* Performs scrolling by centering the map on the point cluster using the set of parameters
*
* @param params the set of parameters computed from point cluster
*/
private void doScrolling(PointClusterParams params){
mapController.setCenter(params.midpointOnMap);//设置中心位置
}
/**
* Adjust the zoom level depending on cluster point parameters (coordinate max span in average)
*
* @param params the point cluster parameters
* @param howToZoom integer value coming from zoomChangeIsNeeded()
*/
private void doZoom(PointClusterParams params, int howToZoom){
if (howToZoom == ZOOM_MAX)
mapController.setZoom(16);
if (howToZoom == RECOMPUTE_ZOOM)
mapController.zoomToSpan(params.coordMaxSpan[0],params.coordMaxSpan[1]);
}
/**
* Draws all the online contacts on the map.
*
* @param c the canvas we use to draw
* @param p the paint object we use to draw
*/
private void drawOnlineContacts(Canvas c, Paint p){
//myLogger.log(Logger.INFO, "Start drawing all contacts!!");
FontMetrics fm = p.getFontMetrics();
int bluePaddleOffsetY= bluePaddle.getHeight();
int bluePaddleOffsetX= bluePaddle.getWidth()/2;
int ylwPaddleOffsetY= ylwPaddle.getHeight();
int ylwPaddleOffsetX= ylwPaddle.getWidth()/2;
int blueBaloonOffsetY = 25;
int blueBaloonOffsetX = 4;
myPaint.setTextSize(18);
Set<String> allParticipants = MsnSessionManager.getInstance().getAllParticipantIds();
int color=0;
int iconToTextOffsetY= 5;
for (Iterator<ContactLayoutData>iterator = contactPositionMap.values().iterator(); iterator.hasNext();) {
ContactLayoutData cData = (ContactLayoutData) iterator.next();
int bitmapOriginX=0;
int bitmapOriginY=0;
Bitmap bitmapToBeDrawn = null;
if (cData.isVisible){
if (cData.isMyContact){
//204, 153, 102, 0
color = R.color.chat_dark_orange;
//myLogger.log(Logger.INFO, "Drawing my contact: position on screen (" + cData.positionOnScreen[0] + ";" + cData.positionOnScreen[1] + ")");
bitmapOriginX = cData.positionOnScreen.x - ylwPaddleOffsetX;
bitmapOriginY = cData.positionOnScreen.y - ylwPaddleOffsetY;
//if(!focusState)//只有非聚焦状态才是自身,不改变颜色
bitmapToBeDrawn = ylwPaddle;
}
else {
//Here blueBaloon for people you're chatting with
if(allParticipants.contains(cData.idContact)){
bitmapOriginX = cData.positionOnScreen.x-blueBaloonOffsetX;
bitmapOriginY = cData.positionOnScreen.y-blueBaloonOffsetY;
bitmapToBeDrawn = blueBaloon;
}
else{
bitmapOriginX = cData.positionOnScreen.x-bluePaddleOffsetX;
bitmapOriginY = cData.positionOnScreen.y-bluePaddleOffsetY;
bitmapToBeDrawn = bluePaddle;
}
color = R.color.BuleDark;
}
int textOriginX = cData.positionOnScreen.x;
int textOriginY = bitmapOriginY - iconToTextOffsetY;
RectF rect = new RectF(textOriginX - 2, textOriginY + (int) fm.top - 2, textOriginX +this.getStringLength(cData.name, myPaint) + 2,textOriginY + (int) fm.bottom + 2);
//Draws the debugging rct for collision
//Draw the right bitmap icon
if (cData.isChecked){
c.drawBitmap(highlight, bitmapOriginX, bitmapOriginY, myPaint);
} else {
c.drawBitmap(bitmapToBeDrawn, bitmapOriginX, bitmapOriginY, myPaint);
}
//Change color for background rectangle
myPaint.setColor(Color.argb(204, 204,204, 0));
c.drawRoundRect(rect, 4.0f, 4.0f, myPaint);// Rect(rect, myPaint);
//ChangeColor for text
myPaint.setColor(color);
c.drawText(cData.name,textOriginX, textOriginY, myPaint);
myPaint.setARGB(204, 153, 102, 0);
}
}
}
/**
* Overrides Overlay.draw() to draw the scene
*/
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Projection p = mapView.getProjection();
updateOnScreenPosition(p);
//Compute params needed for further computations on the point cluster
int onlineContacts = getContactsOnline();
if(!MainActivity.mapMoveFlag)
{
if (onlineContacts > 0){
PointClusterParams params = extractParams(p, onlineContacts);
//Things we do just the first time
if (WIDTH == -1){
initialize(p, mapView.getWidth(), mapView.getHeight());
int howToZoom = zoomChangeIsNeeded(params);
doScrolling(params);
doZoom(params, howToZoom);
} else {
//if any pixel is out our scrolling area
if (scrollingIsNeeded()){
//change map center
doScrolling(params);
}
int howToZoom = zoomChangeIsNeeded(params);
if (howToZoom != NO_ZOOM) {
doZoom(params,howToZoom);
}
}
//Draw all the contacts
drawOnlineContacts(canvas, myPaint);
}
}else{
if (onlineContacts > 0){
PointClusterParams params = extractParams(p, onlineContacts);
//Things we do just the first time
if (WIDTH == -1){
initialize(p, mapView.getWidth(), mapView.getHeight());
int howToZoom = zoomChangeIsNeeded(params);
//doScrolling(params);
//doZoom(params, howToZoom);
} else {
//if any pixel is out our scrolling area
if (scrollingIsNeeded()){
//change map center
//doScrolling(params);
}
int howToZoom = zoomChangeIsNeeded(params);
if (howToZoom != NO_ZOOM) {
//doZoom(params,howToZoom);
}
}
//Draw all the contacts
drawOnlineContacts(canvas, myPaint);
}
}
}
/**
* Initialize all the constants values needed for drawing contacts and
* performing zooming and scrolling.
*
* @param calculator {@link PixelCalculator} needed for retrieving map view size and projecting map points on screen
*/
private void initialize( Projection p, int width, int height ) {
WIDTH = width;
HEIGHT = height;
SCROLL_AREA_HEIGHT = (int) (HEIGHT * SCROLL_AREA_HEIGHT_RATIO);
SCROLL_AREA_WIDTH = (int) (WIDTH * SCROLL_AREA_WIDTH_RATIO);
scrollingArea.top = (HEIGHT - SCROLL_AREA_HEIGHT)/2;
scrollingArea.bottom = scrollingArea.top + SCROLL_AREA_HEIGHT;
scrollingArea.left = (WIDTH - SCROLL_AREA_WIDTH)/2;
scrollingArea.right = scrollingArea.left + SCROLL_AREA_WIDTH;
int tmpThresh = (int ) (WIDTH * UPPER_THRESHOLD_RATIO);
UPPER_THRESHOLD = tmpThresh * tmpThresh;
tmpThresh = (int) (WIDTH * LOWER_THRESHOLD_RATIO);
LOWER_THRESHOLD = tmpThresh * tmpThresh;
}
/**
* Recomputes on screen positions of all the contacts after changing their location on the map
*
* @param calc the pixel calculator
*/
private void updateOnScreenPosition(Projection calc){
for (ContactLayoutData cData : contactPositionMap.values()) {
if (cData.isVisible){
calc.toPixels(new GeoPoint(cData.latitudeE6, cData.longitudeE6),cData.positionOnScreen);
}
}
}
/**
* Retrieves the number of contacts that currently are online
*
* @return number of online contacts
*/
private int getContactsOnline(){
int online =0;
for (ContactLayoutData mapEntry : contactPositionMap.values()){
if (mapEntry.isVisible){
online++;
}
}
return online;
}
/**
* Computes a set of parameters from the the current contacts locations.
* <p>
* These are in particular:
* <ul>
* <li> cluster midpoint on the map (back projection of midpoint on screen)
* <li> cluster midpoint on screen (average of contact positions on screen)
* <li> max longitude span
* <li> max latitude span
* </ul>
* These parameters are useful for automatic zooming and centering and are computed during each draw cycle
*
* @param calc the {@link PixelCalculator} needed for computations
*
* @return class carrying results of computation
*/
private PointClusterParams extractParams(Projection p, int contactsOnLine){
int maxLat = Integer.MIN_VALUE;
int minLat= Integer.MAX_VALUE;;
int maxLong= Integer.MIN_VALUE;;
int minLong =Integer.MAX_VALUE;;
PointClusterParams params = new PointClusterParams();
params.midpointOnScreen = new int[2];
params.midpointOnScreen[0] = 0;
params.midpointOnScreen[1] = 0;
params.coordMaxSpan = new int[2];
for (Iterator<ContactLayoutData> iterator = contactPositionMap.values().iterator(); iterator.hasNext();) {
ContactLayoutData clData = (ContactLayoutData) iterator.next();
if (clData.isVisible){
params.midpointOnScreen[0] += clData.positionOnScreen.x;
params.midpointOnScreen[1] += clData.positionOnScreen.y;
maxLat = (clData.latitudeE6> maxLat)? clData.latitudeE6 : maxLat;
maxLong = (clData.longitudeE6 > maxLong)? clData.longitudeE6 : maxLong;
minLong = (clData.longitudeE6 < minLong)? clData.longitudeE6 : minLong;
minLat = (clData.latitudeE6 < minLat)? clData.latitudeE6 : minLat;
//we need to zoom in another way if we have a single point
if (maxLat == minLat){
params.coordMaxSpan[0] = -1;
params.coordMaxSpan[1] = -1;
} else {
params.coordMaxSpan[0] = maxLat -minLat;
params.coordMaxSpan[1] = maxLong - minLong;
}
}
}
params.midpointOnScreen[0] /= contactsOnLine;
params.midpointOnScreen[1] /= contactsOnLine;
params.midpointOnMap = p.fromPixels(params.midpointOnScreen[0], params.midpointOnScreen[1]);
return params;
}
/**
* Computes the max squared distance between the position of each contact on the screen and the midpoint.
*
* @param points locations of the online contacts in screen coordinates
* @param midpoint the midpoint in screen coordinate
*
* @return the max squared distance
*/
private int getMaxDistSquared(Collection<ContactLayoutData> points,int[] midpoint){
int maxDist =0;
//For each point
for (Iterator <ContactLayoutData>iterator = points.iterator(); iterator.hasNext();) {
ContactLayoutData contactLayoutData = iterator.next();
//Compute distance squared
int distX = midpoint[0] - contactLayoutData.positionOnScreen.x;
int distY = midpoint[1] - contactLayoutData.positionOnScreen.y;
int distSq = distX*distX + distY*distY;
if (distSq > maxDist)
maxDist = distSq;
}
return maxDist;
}
/**
* Collects and stores a set of parameters useful for automatic adjustment of zoom level
* and automatic map centering.
*/
private class PointClusterParams {
/**
* Max span of latitude and longitude as a coordinate pair in microdegrees
*/
public int[] coordMaxSpan;
/**
* Midpoint on the map (computed as the back projection of the midpoint on screen)
*/
public GeoPoint midpointOnMap;
/**
* The midpoint on screen obtained as the average of the contact's on-screen positions.
*/
public int[] midpointOnScreen;
}
/**
* Provides the status of the contacts as drawn on the screen.
* Mantains a collection of info useful for drawing contacts data on map
*/
private class ContactLayoutData{
/**
* The position on screen in pixel.
*/
public Point positionOnScreen;
/**
* The latitude in microdegrees.
*/
public int latitudeE6;
/**
* The longitude in microdegrees.
*/
public int longitudeE6;
/**
* The altitude in microdegrees.
*/
public int altitudeE6;
/**
* The name of the contact that should be drawn as a label
*/
public String name;
/**
* true if the contact is selected on map, false otherwise
*/
public boolean isChecked;
/**
* true if this is my contact, false otherwise
*/
public boolean isMyContact;
/**
* Flag that means that the contact should be shown on map (online)
*/
public boolean isVisible;
/**
* The contact id.
*/
public String idContact;
/**
* Instantiates a new contact layout data.
*
* @param cname the name of the contact
* @param idcontact the contact id
* @param contactLoc the contact location on the map
* @param visible true if contact should be drawn, false otherwise
*/
public ContactLayoutData(String cname, String idcontact, Location contactLoc, boolean visible){
this.name = cname;
this.idContact= idcontact;
isMyContact = false;//
positionOnScreen = new Point();
latitudeE6 = (int)(contactLoc.getLatitude() * 1E6);
longitudeE6 = (int) (contactLoc.getLongitude() * 1E6);
altitudeE6=(int)(contactLoc.getAltitude()*1E6);
isVisible = visible;
}
//TODO:重载方法,焦点定位
public ContactLayoutData(String cname, String idcontact, Location contactLoc, boolean visible,int foucs){
this.name = cname;
this.idContact= idcontact;
isMyContact = true;//
positionOnScreen = new Point();
latitudeE6 = (int)(contactLoc.getLatitude() * 1E6);
longitudeE6 = (int) (contactLoc.getLongitude() * 1E6);
altitudeE6=(int)(contactLoc.getAltitude()*1E6);
isVisible = visible;
}
/**
* Update the contact location on map with new data
*
* @param latitude the latitude in microdegrees
* @param longitude the longitude in microdegrees
* @param altitude the altitude in microdegrees
*/
public void updateLocation(int latitude, int longitude, int altitude){
latitudeE6 = latitude;
longitudeE6 = longitude;
altitudeE6 = altitude;
}
}
/**
* Returns the length of a string on screen in pixel drawn with the given Paint object.
*
* @param name string to be drawn
* @param paint the Paint object
*
* @return the string length in pixel
*/
private int getStringLength (String name, Paint paint) {
float [] widthtext= new float[name.length()];
float sumvalues=0;
paint.getTextWidths(name, widthtext);
for(int n=0; n<widthtext.length; n++){
sumvalues+= widthtext[n];
}
return (int) sumvalues;
}
/**
* Check clicked position for hitting any contact. Any contact hit is marked as checked.
*
* @param point the clicked point in screen coordinate
*/
public void checkClickedPosition (Point point)
{
int width= bluePaddle.getWidth();
int height= bluePaddle.getHeight();
String myId = ContactManager.getInstance().getMyContact().getPhoneNumber();
for (ContactLayoutData contact : contactPositionMap.values()){
Rect r= new Rect(contact.positionOnScreen.x- width/2, contact.positionOnScreen.y-height, contact.positionOnScreen.x+width/2, contact.positionOnScreen.y );
if(r.contains(point.x, point.y) && !contact.idContact.equals(myId) ){
contact.isChecked = !contact.isChecked;
}
}
}
/**
* Retrieves all the clicked contacts
*
* @return list of id (phone numbers) of all selected contacts
*/
public List<String> getSelectedItems(){
List<String> ids = new ArrayList<String>();
for (ContactLayoutData cdata : contactPositionMap.values()) {
if (cdata.isChecked){
ids.add(cdata.idContact);
}
}
return ids;
}
/**
* Unchecks all contacts.
*/
public void uncheckAllContacts(){
for (ContactLayoutData data : contactPositionMap.values()) {
data.isChecked=false;
myMapView.invalidate();
}
}
/**
* Initialize the adapter by populating it with all available contacts and by creating the info
* for each item. Every other modification shall be incremental.
*
*/
public final void initializePositions(){
Map<String, Contact> localContactMap = ContactManager.getInstance().getAllContacts();
Contact myContact = ContactManager.getInstance().getMyContact();
ContactLocation myCloc = ContactManager.getInstance().getMyContactLocation();
ContactLayoutData myCl = new ContactLayoutData(myContact.getName(),myContact.getPhoneNumber(),myCloc,true);
myCl.isMyContact=true;
myCl.isVisible = isValid(myCloc);
contactPositionMap.put(myCl.idContact, myCl);
for (Map.Entry<String,Contact> contactEntry : localContactMap.entrySet()) {
String phoneNum = contactEntry.getKey();
Contact currentC = contactEntry.getValue();
//empty location for invisible contact
ContactLayoutData cdata = new ContactLayoutData(
currentC.getName(),phoneNum,
new ContactLocation( ((JChatApplication)((Activity) ctn).getApplication()).getProperty(JChatApplication.LOCATION_PROVIDER) ) ,
false);
contactPositionMap.put(phoneNum, cdata);
}
focusState=false;//非聚焦状态改为false
}
public final void initializePositionsFocus(String id){
//取到所以联系人
Map<String, Contact> localContactMap = ContactManager.getInstance().getAllContacts();
//取到自己的
Contact myContact = ContactManager.getInstance().getMyContact();
ContactLocation myCloc = ContactManager.getInstance().getMyContactLocation();
ContactLayoutData myCl = new ContactLayoutData(myContact.getName(),myContact.getPhoneNumber(),myCloc,true);
//不以自己为中心
contactPositionMap.clear();//清空联系人,然后重新初始化
myCl.isMyContact=false;
myCl.isVisible = isValid(myCloc);
contactPositionMap.put(myCl.idContact, myCl);
for (Map.Entry<String,Contact> contactEntry : localContactMap.entrySet()) {
String phoneNum = contactEntry.getKey();
Contact currentC = contactEntry.getValue();
if(phoneNum.equals(id))
{
//重载,可见
ContactLayoutData cdata = new ContactLayoutData(
currentC.getName(),phoneNum,
new ContactLocation( ((JChatApplication)((Activity) ctn).getApplication())
.getProperty(JChatApplication.LOCATION_PROVIDER) ) ,
true,1);
contactPositionMap.put(phoneNum, cdata);
}else{
//empty location for invisible contact
ContactLayoutData cdata = new ContactLayoutData(
currentC.getName(),phoneNum,
new ContactLocation( ((JChatApplication)((Activity) ctn)
.getApplication()).getProperty(JChatApplication.LOCATION_PROVIDER) ) ,
false);
contactPositionMap.put(phoneNum, cdata);
}
}
focusState=true;//聚焦状态改为true
}
/**
* Update all contacts location based on the changes notified by the agent (contacts added and contacts removed)
*
* @param changes list of changes
* @param locationMap
* @param contactMap
*/
public void update(ContactListChanges changes, Map<String, Contact> contactMap, Map<String, ContactLocation> locationMap){
ContactLocation cMyLoc = ContactManager.getInstance().getMyContactLocation();
//myLogger.log(Logger.INFO, "It's time for updating the contactsPositionOverlay!!!!!");
//Removed contacts
for ( String removedId : changes.contactsDeleted) {
contactPositionMap.remove(removedId);
}
//Added contacts
for ( String addedId : changes.contactsAdded) {
ContactLayoutData newData = new ContactLayoutData(contactMap.get(addedId).getName(),addedId,locationMap.get(addedId),true);
newData.isVisible = isValid(locationMap.get(addedId));
contactPositionMap.put(addedId, newData);
}
//update all others
for (ContactLayoutData cData : contactPositionMap.values()) {
ContactLocation lastLocation= null;
Contact curContact = null;
if (cData.isMyContact) {
//update contact visibility
//if(!focusState){
lastLocation = cMyLoc;
cData.isVisible = isValid(lastLocation);
//myLogger.log(Logger.INFO, "Ok... Ready to update location of my contact!!!!!");
cData.updateLocation((int)(lastLocation.getLatitude()*1E6), (int)(lastLocation.getLongitude()*1E6), (int)(lastLocation.getAltitude()*1E6));
} else {
curContact = contactMap.get(cData.idContact);
if (curContact != null && curContact.isOnline()){
lastLocation = locationMap.get(cData.idContact);
if (isValid(lastLocation)){
cData.isVisible = true;
cData.updateLocation((int)(lastLocation.getLatitude()*1E6), (int)(lastLocation.getLongitude()*1E6), (int)(lastLocation.getAltitude()*1E6));
}
} else {
cData.isVisible = false;
}
}
}
}
private boolean isValid(Location loc){
return (loc.getLatitude() != Double.POSITIVE_INFINITY &&
loc.getLongitude() != Double.POSITIVE_INFINITY &&
loc.getAltitude() != Double.POSITIVE_INFINITY);
}
}