MapControl.java :  » GPS » big-planet-tracks » tyt » android » bigplanettracks » maps » ui » Android Open Source

Android Open Source » GPS » big planet tracks 
big planet tracks » tyt » android » bigplanettracks » maps » ui » MapControl.java
package tyt.android.bigplanettracks.maps.ui;

import java.util.ArrayList;
import java.util.List;

import tyt.android.bigplanettracks.BigPlanet;
import tyt.android.bigplanettracks.R;
import tyt.android.bigplanettracks.maps.AbstractCommand;
import tyt.android.bigplanettracks.maps.MarkerManager;
import tyt.android.bigplanettracks.maps.MarkerManager.Marker;
import tyt.android.bigplanettracks.maps.PhysicMap;
import tyt.android.bigplanettracks.maps.RawTile;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

/**
 * ,  
 * 
 * @author hudvin
 * 
 */
public class MapControl extends RelativeLayout {

  private static final int TILE_SIZE = 256;

  public static final int ZOOM_MODE = 0;

  public static final int SELECT_MODE = 1;

  private int mapMode = ZOOM_MODE;

  private Panel main;

  private Canvas cs;

  private DoubleClickDetector dcDetector = new DoubleClickDetector();

  private PhysicMap pmap;

  /*
   * Toolbar with zoom cont
   */
  private ZoomPanel zoomPanel;

  private boolean isNew = true;

  private Bitmap cb = null;

  private final static int BCG_CELL_SIZE = 16;

  private OnMapLongClickListener onMapLongClickListener;

  private MarkerManager markerManager;

  public static Bitmap CELL_BACKGROUND = BitmapUtils.drawBackground(BCG_CELL_SIZE, TILE_SIZE, TILE_SIZE);

  public static Bitmap EMPTY_BACKGROUND = BitmapUtils.drawEmptyBackground(TILE_SIZE);

  private Point scalePoint = new Point();

  private SmoothZoomEngine szEngine;

  public Handler h;
  
  private Context context;
  
  private final float density = BigPlanet.density;
  private int bestZoomFromDB = -2;
  private int initialZoomFromDB = -2;
  private int minZoomFromDB = 10; // (tile.Zoom = 17-10 = 7)
  
  private List<Marker> markersTemp = new ArrayList<Marker>();

  // MyTracks
  private final Drawable arrow[] = new Drawable[18];
  private final int arrowWidth, arrowHeight;
  
  /**
   * Constructor
   * 
   * @param context
   * @param width
   * @param height
   * @param startTile
   */
  public MapControl(Context context, int width, int height,
      RawTile startTile, MarkerManager markerManager) {
    super(context);
    this.context = context;
    scalePoint.set(width / 2, height / 2);
    this.markerManager = markerManager;
    buildView(width, height, startTile);
    
    arrow[0] = context.getResources().getDrawable(R.drawable.arrow_0);
    arrow[1] = context.getResources().getDrawable(R.drawable.arrow_20);
    arrow[2] = context.getResources().getDrawable(R.drawable.arrow_40);
    arrow[3] = context.getResources().getDrawable(R.drawable.arrow_60);
    arrow[4] = context.getResources().getDrawable(R.drawable.arrow_80);
    arrow[5] = context.getResources().getDrawable(R.drawable.arrow_100);
    arrow[6] = context.getResources().getDrawable(R.drawable.arrow_120);
    arrow[7] = context.getResources().getDrawable(R.drawable.arrow_140);
    arrow[8] = context.getResources().getDrawable(R.drawable.arrow_160);
    arrow[9] = context.getResources().getDrawable(R.drawable.arrow_180);
    arrow[10] = context.getResources().getDrawable(R.drawable.arrow_200);
    arrow[11] = context.getResources().getDrawable(R.drawable.arrow_220);
    arrow[12] = context.getResources().getDrawable(R.drawable.arrow_240);
    arrow[13] = context.getResources().getDrawable(R.drawable.arrow_260);
    arrow[14] = context.getResources().getDrawable(R.drawable.arrow_280);
    arrow[15] = context.getResources().getDrawable(R.drawable.arrow_300);
    arrow[16] = context.getResources().getDrawable(R.drawable.arrow_320);
    arrow[17] = context.getResources().getDrawable(R.drawable.arrow_340);
    arrowWidth = arrow[BigPlanet.lastHeading].getIntrinsicWidth();
    arrowHeight = arrow[BigPlanet.lastHeading].getIntrinsicHeight();
    for (int i = 0; i <= 17; i++) {
      arrow[i].setBounds(0, 0, arrowWidth, arrowHeight);
    }
    
    final Handler updateControlsHandler = new Handler() {

      @Override
      public void handleMessage(Message msg) {

        switch (msg.what) {
        case 0:
          updateZoomControls();
          break;
        }
        super.handleMessage(msg);
      }
    };
    
    szEngine = SmoothZoomEngine.getInstance();
    szEngine.setReloadMapCommand(new AbstractCommand() {

      public void execute(Object object) {
        double sf = (Float) object;
        pmap.zoomS(sf);
        updateControlsHandler.sendEmptyMessage(0);
      }

    });
    szEngine.setUpdateScreenCommand(new AbstractCommand() {
      
      public void execute(Object object) {
        pmap.scaleFactor = (Float) object;
        postInvalidate();
      }

    });
  }

  public int getMapMode() {
    return mapMode;
  }

  /**
   *      -(  
   *     )
   * 
   * @param mapMode
   */
  public void setMapMode(int mapMode) {
    this.mapMode = mapMode;
    updateZoomControls();
  }

  public void setOnMapLongClickListener(
      OnMapLongClickListener onMapLongClickListener) {
    this.onMapLongClickListener = onMapLongClickListener;
  }

  /**
   *      
   * 
   * @param width
   * @param height
   */
  public void setSize(int width, int height) {
    if (main != null) {
      removeView(main);
    }
    pmap.resetCell(width, height);
    buildView(width, height, pmap.getDefaultTile());
  }

  /**
   *   
   * 
   * @return
   */
  public PhysicMap getPhysicalMap() {
    return pmap;
  }

  public void goTo(int x, int y, int z, int offsetX, int offsetY) {
    getPhysicalMap().goTo(x, y, z, offsetX, offsetY);
    updateZoomControls();
    updateScreen();
  }

  /**
   *  ,  ,   .
   * 
   * @param width
   * @param height
   * @param startTile
   */
  private void buildView(int width, int height, RawTile startTile) {
    h = new Handler() {
      @Override
      public void handleMessage(Message msg) {
        updateZoomControls();
      }
    };
    
    //    
    main = new Panel(this.getContext());
    addView(main, 0, new ViewGroup.LayoutParams(width, height));
    //  -
    if (zoomPanel == null) { //    
      zoomPanel = new ZoomPanel(this.getContext());
      //  
      zoomPanel.setOnZoomOutClickListener(new OnClickListener() {
        public void onClick(View v) {
          Log.i("MapControl", "OnZoomOutClick");
          BigPlanet.isMapInCenter = false;
          int zoomLevel = PhysicMap.getZoomLevel();
          if (zoomLevel >= 17) {
            return;
          }
          //zoomPanel.setIsZoomOutEnabled(false); // avoid double click to cause grey screen
          scalePoint.set(pmap.getWidth() / 2, pmap.getHeight() / 2);
          smoothZoom(-1);
        }
      });

      //  
      zoomPanel.setOnZoomInClickListener(new OnClickListener() {
        public void onClick(View v) {
          Log.i("MapControl", "OnZoomInClick");
          BigPlanet.isMapInCenter = false;
          int zoomLevel = PhysicMap.getZoomLevel();
          if (zoomLevel <= -2) {
            return;
          }
          //zoomPanel.setIsZoomInEnabled(false); // avoid double click to cause grey screen
          scalePoint.set(pmap.getWidth() / 2, pmap.getHeight() / 2);
          smoothZoom(1);
        }
      });

      addView(zoomPanel, new LayoutParams(LayoutParams.WRAP_CONTENT,
          LayoutParams.WRAP_CONTENT));

    }
    // Convert the dips to pixels 
    zoomPanel.setPadding((width - (int)(160*(density))) / 2, height - (int)(50*(density)), 0, 0);

    if (pmap == null) { //     
      pmap = new PhysicMap(width, height, startTile, new AbstractCommand() {

        /**
         * Callback,     
         */
        @Override
        public void execute() {
          updateScreen();
        }

      });
    }
    pmap.quickHack();
  }

  private void smoothZoom(int direction) {
//    System.out.println(getPhysicalMap().getTileResolver().getLoaded());
    szEngine.addToScaleQ(direction);
  }

  public synchronized void updateScreen() {
    if (main != null) {
      main.postInvalidate();
      Intent i = new Intent(BigPlanet.UpdateScreenAction);
      context.sendBroadcast(i);
    }
  }
  
  private void invokeGoToMyLocation(double lat, double lon, int zoom) {
    Intent i = new Intent(BigPlanet.UpdateScreenAction);
    i.putExtra("type", 1);
    i.putExtra("lat", lat);
    i.putExtra("lon", lon);
    i.putExtra("zoom", zoom);
    context.sendBroadcast(i);
  }

  /**
   *   zoomIn/zoomOut     
   * 
   */
  public void updateZoomControls() {
    pmap.getTileResolver().clearCache();
    int zoomLevel = PhysicMap.getZoomLevel();
    markerManager.updateAll(zoomLevel);
    if (getMapMode() == MapControl.SELECT_MODE) {
      zoomPanel.setVisibility(View.INVISIBLE);
    } else {
      zoomPanel.setVisibility(View.VISIBLE);
      if (zoomLevel >= 17) {
        zoomPanel.setIsZoomOutEnabled(false);
        zoomPanel.setIsZoomInEnabled(true);
      } else if (zoomLevel <= -2) {
        zoomPanel.setIsZoomOutEnabled(true);
        zoomPanel.setIsZoomInEnabled(false);
      } else {
        zoomPanel.setIsZoomOutEnabled(true);
        zoomPanel.setIsZoomInEnabled(true);
      }
    }
  }

  /**
   *  
   * 
   * @param canvas
   * @param paint
   */
  private synchronized void doDraw(Canvas c, Paint paint) {
    if (cb == null || cb.getHeight() != pmap.getHeight()) {
      cs = new Canvas();
      cb = Bitmap.createBitmap(pmap.getWidth(), pmap.getHeight(), Bitmap.Config.RGB_565);
      cs.setBitmap(cb);
    }
//    System.out.println("doDraw scaleFactor " + pmap.scaleFactor);
    Bitmap tmpBitmap;
    for (int i = 2; i < pmap.cells.length+2; i++) {
      for (int j = 2; j < pmap.cells[0].length+2; j++) {
        if ((i > 1 && i < pmap.cells.length+2) && ((j > 1 && j < pmap.cells[0].length+2))) {
          tmpBitmap = pmap.getCell(i - 2, j - 2);
          if (tmpBitmap != null) {
            isNew = false;
            cs.drawBitmap(tmpBitmap, 
                (i - 2) * TILE_SIZE + pmap.getGlobalOffset().x, 
                (j - 2) * TILE_SIZE + pmap.getGlobalOffset().y, paint);
          }
        } else {
          if (pmap.scaleFactor == 1) {
            cs.drawBitmap(CELL_BACKGROUND, 
                (i - 2) * TILE_SIZE + pmap.getGlobalOffset().x, 
                (j - 2) * TILE_SIZE + pmap.getGlobalOffset().y, paint);
          } else {
            cs.drawBitmap(EMPTY_BACKGROUND, 
                (i - 2) * TILE_SIZE + pmap.getGlobalOffset().x, 
                (j - 2) * TILE_SIZE + pmap.getGlobalOffset().y, paint);
          }
        }
      }
    }

    if (pmap.scaleFactor == 1) {
      //  
      if(!BigPlanet.isGPSTracking){
        for (int i = 2; i < pmap.cells.length+2; i++) {
          for (int j = 2; j < pmap.cells[0].length+2; j++) {
            if ((i > 1 && i < pmap.cells.length+2) && ((j > 1 && j < pmap.cells[0].length+2))) {
              RawTile tile = pmap.getDefaultTile();
              int z = PhysicMap.getZoomLevel();
              int tileX = tile.x + (i - 2);
              int tileY = tile.y + (j - 2);
              List<Marker> markers = markerManager.getMarkers(tileX, tileY, z);
              
              for (Marker marker : markers) {
                if (BigPlanet.currentLocation != null && BigPlanet.currentLocation.getSpeed()>0) {
                  Drawable drawable = arrow[BigPlanet.lastHeading];
                  cs.drawBitmap(((BitmapDrawable)drawable).getBitmap(),
                      (i - 2) * TILE_SIZE  + pmap.getGlobalOffset().x
                      + (int) marker.getOffset().x
                      - 15*density, 
                      (j - 2) * TILE_SIZE + pmap.getGlobalOffset().y
                      + (int) marker.getOffset().y
                      - 26*density, paint);
                } else {
                  cs.drawBitmap(marker.getMarkerImage().getImage(),
                      (i - 2) * TILE_SIZE  + pmap.getGlobalOffset().x
                      + (int) marker.getOffset().x
                      - marker.getMarkerImage().getOffsetX()*density, 
                      (j - 2) * TILE_SIZE + pmap.getGlobalOffset().y
                      + (int) marker.getOffset().y
                      - marker.getMarkerImage().getOffsetY()*density, paint);
                }
              }
            }
          }
        }
      }
    }

    int paintColor[] = new int[] {
        Color.RED,
        Color.BLUE,
        Color.CYAN,
      };
    
    int length = paintColor.length;
    
    boolean isEnabled[] = new boolean[] {
        true,
        BigPlanet.isGPSTracking,
        BigPlanet.isGPSTrackSaved,
      };
      
    int markerType[] = new int[] {
        MarkerManager.START_GREEN_MARKER,
        MarkerManager.START_BLUE_MARKER,
        MarkerManager.START_BLUE_MARKER,
    };
    
    List<List<Marker>> allMarkerList = new ArrayList<List<Marker>>();
    allMarkerList.add(MarkerManager.markersDB);
    allMarkerList.add(MarkerManager.markersG);
    allMarkerList.add(MarkerManager.savedTrackG);
    
    boolean isDrawingMarkerG[] = new boolean[length];
    boolean isDrawing = false;
    for (int m = 0; m < allMarkerList.size(); m++) {
      if (isEnabled[m] && allMarkerList.get(m).size() != 0) {
        isDrawingMarkerG[m] = true;
        isDrawing = true;
      }
    }
    
    if (isDrawing) {
      for (int m = 0; m < allMarkerList.size(); m++) {
        if (isDrawingMarkerG[m]) {
          float x1 = 0, x2 = 0, y1 = 0, y2 = 0, startPointX = 0, startPointY = 0;
          boolean isDrawingStartMarker = false;
          boolean isSetStartPoint = false;
          paint.setColor(paintColor[m]);
          paint.setStrokeWidth(3);
          List<Marker> markerList = allMarkerList.get(m);
          for (int k = 0; k < markerList.size(); k++) {
            Marker marker = markerList.get(k);
            for (int i = 2; i < pmap.cells.length+2; i++) {
              for (int j = 2; j < pmap.cells[0].length+2; j++) {
                if ((i > 1 && i < pmap.cells.length+2) && ((j > 1 && j < pmap.cells[0].length+2))) {
                  RawTile tile = pmap.getDefaultTile();
                  int z = PhysicMap.getZoomLevel();
                  int tileX = tile.x + (i - 2);
                  int tileY = tile.y + (j - 2);
                  
                  boolean result = markerManager.isDrawingMarkerG(tileX, tileY, z, marker);
                  if (result) {
                    if (isSetStartPoint) {
                      x2 = (i - 2)* TILE_SIZE + pmap.getGlobalOffset().x + (int) marker.getOffset().x;
                      y2 = (j - 2)* TILE_SIZE + pmap.getGlobalOffset().y + (int) marker.getOffset().y+3;
                      if (x2 != 0 && y2 != 0) {
                        cs.drawLine(x1, y1, x2, y2, paint);
                        x1 = x2;
                        y1 = y2;
                      }
                    } else {
                      x1 = (i - 2)* TILE_SIZE + pmap.getGlobalOffset().x + (int) marker.getOffset().x;
                      y1 = (j - 2)* TILE_SIZE + pmap.getGlobalOffset().y + (int) marker.getOffset().y+3;
                      if (x1 != 0 && y1 != 0) {
                        startPointX = x1;
                        startPointY = y1;
                        isSetStartPoint = true;
                      }  
                    }
                    
                    if (k == 0) {
                      isDrawingStartMarker = true;
                    } else if (k == markerList.size()-1) {
                      markerList.get(k).setMarkerImage(MarkerManager.images.get(markerType[m]+1)); // END_MY_TRACK_MARKER
                      cs.drawBitmap(markerList.get(k).getMarkerImage().getImage(),
                          x2 - markerList.get(k).getMarkerImage().getOffsetX()*density,
                          y2 - markerList.get(k).getMarkerImage().getOffsetY()*density,paint);
                    }
                  }
                }
              }
            }
          } // end for (int k = 0; k < markerGList.size(); k++)
          if (isDrawingStartMarker) {
            isDrawingStartMarker = false;
            markerList.get(0).setMarkerImage(MarkerManager.images.get(markerType[m])); // START_MY_TRACK_MARKER
            cs.drawBitmap(markerList.get(0).getMarkerImage().getImage(),
                startPointX - markerList.get(0).getMarkerImage().getOffsetX()*density,
                startPointY - markerList.get(0).getMarkerImage().getOffsetY()*density,paint);
          }
        }
      }
    }
    Matrix matr = new Matrix();
    matr.postScale((float) pmap.scaleFactor, (float) pmap.scaleFactor, scalePoint.x, scalePoint.y);
    c.drawColor(BitmapUtils.BACKGROUND_COLOR);
    c.drawBitmap(cb, matr, paint);
  }

  @Override
  protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    new Thread() {
      @Override
      public void run() {
        while (isNew) {
          try {
            Thread.sleep(100);
            postInvalidate();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }

    }.start();
  }

  /**
   * ,    
   * 
   * @author hudvin
   * 
   */
  class Panel extends View {
    Paint paint;

    public Panel(Context context) {
      super(context);
      paint = new Paint();

    }

    @Override
    protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      
      if (BigPlanet.autoDisplayDB && MarkerManager.markersDB.size()!=0 && MarkerManager.markers.size()!=0) {
        if(BigPlanet.autoDisplayDBforMarker){
          markersTemp.add(MarkerManager.markers.get(0));
        }
        BigPlanet.autoDisplayDBforMarker = false;
        
        boolean check = checkMarkersDBforDisplay();
        if (bestZoomFromDB<minZoomFromDB && !check) {
          bestZoomFromDB = bestZoomFromDB+1;
          invokeGoToMyLocation(BigPlanet.autoDisplayDB_Lat, BigPlanet.autoDisplayDB_Lon, bestZoomFromDB);
          // It shows the progress of zooming out and can be disabled to speedup.
          doDraw(canvas, paint);
        } else {
          BigPlanet.autoDisplayDB = false;
          BigPlanet.autoDisplayDBforMarker = true;
          invokeGoToMyLocation(BigPlanet.autoDisplayDB_Lat, BigPlanet.autoDisplayDB_Lon, bestZoomFromDB+1);
          doDraw(canvas, paint);
          bestZoomFromDB = initialZoomFromDB; // initial value
        }
        
      } else {
        if (BigPlanet.autoDisplayDBforMarker && MarkerManager.markersDB.size()!=0) {
          MarkerManager.markers.clear();
          if (!BigPlanet.clearYellowPersonMarker) {
            MarkerManager.markers.add(markersTemp.get(0));
          } else {
            // clear the yellow person marker after loading the track from DB
            // don't execute markers.add()
            BigPlanet.clearYellowPersonMarker = false;
          }
          BigPlanet.autoDisplayDBforMarker = false;
        }
        doDraw(canvas, paint);
      }
    }
    
    public boolean checkMarkersDBforDisplay() {
      // check all points
      int factor = 1;
      int num = MarkerManager.markersDB.size();
      // quick check
      if (num > 40) {
        factor = 10;
        num = Math.round(num/factor);
      }
      int countDB = 0;
      for (int k=0; k < num; k++) {
        int index = k*factor;
        for (int i = 2; i < pmap.cells.length+2; i++) {
          for (int j = 2; j < pmap.cells[0].length+2; j++) {
            if ((i > 1 && i < pmap.cells.length+2) && ((j > 1 && j < pmap.cells[0].length+2))) {
              RawTile tile = pmap.getDefaultTile();
              int tileX = tile.x + (i - 2);
              int tileY = tile.y + (j - 2);

              try {
                if (MarkerManager.markersDB.get(index).tile.x == tileX && 
                    MarkerManager.markersDB.get(index).tile.y == tileY && 
                    MarkerManager.markersDB.get(index).tile.z == bestZoomFromDB) {
                  countDB = countDB + 1;
                }  
              } catch (IndexOutOfBoundsException e) {
                if (MarkerManager.markersDB.get(index-1).tile.x == tileX && 
                    MarkerManager.markersDB.get(index-1).tile.y == tileY && 
                    MarkerManager.markersDB.get(index-1).tile.z == bestZoomFromDB) {
                  countDB = countDB + 1;
                }
              }
            }
          }
        }
      }
//      Log.i("MapControl", "auto map zooming out: z="+(17-bestZoomFromDB)+", "+ countDB +"="+num);
      if (countDB == num) {
        return true;
      } else {
        return false;
      }
    }
    
    long touchTime = 0;

    /**
     *  
     */
    @Override
    public boolean onTouchEvent(final MotionEvent event) {
      switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        pmap.inMove = false;
        touchTime = System.currentTimeMillis();
//        System.out.println("touchTime " + touchTime);
        pmap.getNextMovePoint().set((int) event.getX(), (int) event.getY());
        break;
      case MotionEvent.ACTION_MOVE:
        long now = System.currentTimeMillis();
        long diff = now - touchTime;
        if (pmap.scaleFactor == 1){
//          System.out.println("inmove " + pmap.inMove);
          pmap.inMove = true;
          pmap.moveCoordinates(event.getX(), event.getY());
        }
        // for Auto-Follow
        BigPlanet.disabledAutoFollow(MapControl.this.context);
        if (pmap.inMove && diff>50) {
          touchTime = now;
//          System.out.println("diff " + diff);
          pmap.inMove = false;
          pmap.moveCoordinates(event.getX(), event.getY());
          pmap.quickHack();
          pmap.loadFromCache();
          updateScreen();
        }
        break;
      case MotionEvent.ACTION_UP:
        if (dcDetector.process(event)) { // double-tap
          if (pmap.scaleFactor == 1) { // zoom has stopped
            if (mapMode == MapControl.ZOOM_MODE) {
              
            } else {
              if (onMapLongClickListener != null) {
                onMapLongClickListener.onMapLongClick(0, 0);
              }
            }
          }
        } else { // not double-tap
          if (pmap.inMove) {
            pmap.inMove = false;
            pmap.moveCoordinates(event.getX(), event.getY());
            pmap.quickHack();
            pmap.loadFromCache();
            updateScreen();
            // pmap.reloadTiles();
          }
        }
        break;
      }

      return true;
    }
  }

  public void setMapSource(int sourceId) {
    getPhysicalMap().getTileResolver().setMapSource(sourceId);
    getPhysicalMap().reloadTiles();
    updateScreen();
  }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.