<commit_before>/*
 * Copyright (C) 2010 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.flightmap.android;

import java.util.SortedSet;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.location.Location;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.ZoomButtonsController;

import com.google.flightmap.common.NavigationUtil;
import com.google.flightmap.common.data.AirportDistance;
import com.google.flightmap.common.data.LatLng;

/**
 * View for the moving map.
 */
public class MapView extends SurfaceView implements SurfaceHolder.Callback {
  private static final String TAG = MapView.class.getSimpleName();

  // Paints.
  private static final Paint MAGENTA_PAINT = new Paint();
  private static final Paint AIRCRAFT_PAINT = new Paint();
  private static final Paint AIRPORT_LABEL_PAINT = new Paint();
  private static final Paint PANEL_PAINT = new Paint();
  private static final Paint PANEL_TEXT_PAINT = new Paint();

  // Zoom items.
  private static final int MIN_ZOOM = 0;
  private static final int MAX_ZOOM = 30;
  private static final float ZOOM_STEP = 0.5f;
  private ZoomButtonsController zoomController;
  private float zoom = 12;

  // Top panel items.
  private static final float PANEL_HEIGHT = 50;
  private static final float PANEL_TEXT_MARGIN = 10;
  private static final float PANEL_NOTCH_HEIGHT = 10;
  private static final float PANEL_NOTCH_WIDTH = 10;
  private static final float PANEL_TEXT_BASELINE =
      PANEL_HEIGHT - PANEL_NOTCH_HEIGHT - PANEL_TEXT_MARGIN;
  private static final String DEGREES_SYMBOL = "\u00b0";
  private Path topPanel;

  // Main class.
  private final FlightMap flightMap;

  // Coordinates to draw the aircraft on the map.
  private int aircraftX;
  private int aircraftY;

  // Static initialization.
  static {
    MAGENTA_PAINT.setAntiAlias(true);
    MAGENTA_PAINT.setColor(Color.MAGENTA);
    AIRPORT_LABEL_PAINT.setColor(Color.WHITE);
    AIRPORT_LABEL_PAINT.setTypeface(Typeface.SANS_SERIF);
    AIRPORT_LABEL_PAINT.setTextSize(20);
    AIRPORT_LABEL_PAINT.setAntiAlias(true);
    AIRPORT_LABEL_PAINT.setTextAlign(Align.CENTER);
    AIRCRAFT_PAINT.setColor(Color.WHITE);
    AIRCRAFT_PAINT.setStrokeWidth(3);
    PANEL_PAINT.setARGB(200, 200, 200, 200);
    PANEL_TEXT_PAINT.setColor(Color.WHITE);
    PANEL_TEXT_PAINT.setTypeface(Typeface.SANS_SERIF);
    PANEL_TEXT_PAINT.setTextSize(30);
    PANEL_TEXT_PAINT.setAntiAlias(true);
  }

  public MapView(FlightMap flightMap) {
    super(flightMap);
    this.flightMap = flightMap;
    getHolder().addCallback(this);
    setFocusable(true); // make sure we get key events
    setKeepScreenOn(true);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    showZoomController();
    return true;
  }

  @Override
  public boolean onTrackballEvent(MotionEvent event) {
    showZoomController();
    return true;
  }

  private synchronized void showZoomController() {
    if (null != zoomController) {
      zoomController.setVisible(true);
    }
  }

  /**
   * Surface dimensions changed.
   */
  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    Log.i(TAG, String.format("format=%d w=%d h=%d", format, width, height));
    aircraftX = width / 2;
    aircraftY = height - (height / 4);
    createTopPanelPath(width);
  }

  private void createTopPanelPath(int width) {
    final float center = width / 2.0f;
    topPanel = new Path();
    topPanel.moveTo(0, 0);
    topPanel.lineTo(width, 0);
    topPanel.lineTo(width, PANEL_HEIGHT);
    topPanel.lineTo(center + PANEL_NOTCH_WIDTH, PANEL_HEIGHT);
    topPanel.lineTo(center, PANEL_HEIGHT - PANEL_NOTCH_HEIGHT);
    topPanel.lineTo(center - PANEL_NOTCH_WIDTH, PANEL_HEIGHT);
    topPanel.lineTo(0, PANEL_HEIGHT);
    topPanel.close();
  }

  @Override
  public void surfaceCreated(SurfaceHolder holder) {
    zoomController = new ZoomButtonsController(this);
    zoomController.setOnZoomListener(new ZoomButtonsController.OnZoomListener() {
      @Override
      public void onZoom(boolean zoomIn) {
        final float zoomCopy = getZoom(); // copy for thread safety.
        if (zoomIn) {
          setZoom(zoomCopy + ZOOM_STEP);
        } else {
          setZoom(zoomCopy - ZOOM_STEP);
        }
        zoomController.setZoomInEnabled(getZoom() < MAX_ZOOM);
        zoomController.setZoomOutEnabled(getZoom() > MIN_ZOOM);
      }

      @Override
      public void onVisibilityChanged(boolean visible) {
        // Ignored.
      }
    });
  }

  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {
  }

  public void drawMap(Location location) {<commit_msg>Fixed issue 7 - crashing when switching orientations. 1) Only create the ZoomButtonsController once. 2) RTFM and "If you are using this with a custom View, please call    setVisible(false) from the onDetachedFromWindow()."<commit_after>/*
 * Copyright (C) 2010 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.flightmap.android;

import java.util.SortedSet;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.location.Location;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.ZoomButtonsController;

import com.google.flightmap.common.NavigationUtil;
import com.google.flightmap.common.data.AirportDistance;
import com.google.flightmap.common.data.LatLng;

/**
 * View for the moving map.
 */
public class MapView extends SurfaceView implements SurfaceHolder.Callback {
  private static final String TAG = MapView.class.getSimpleName();

  // Paints.
  private static final Paint MAGENTA_PAINT = new Paint();
  private static final Paint AIRCRAFT_PAINT = new Paint();
  private static final Paint AIRPORT_LABEL_PAINT = new Paint();
  private static final Paint PANEL_PAINT = new Paint();
  private static final Paint PANEL_TEXT_PAINT = new Paint();

  // Zoom items.
  private static final int MIN_ZOOM = 0;
  private static final int MAX_ZOOM = 30;
  private static final float ZOOM_STEP = 0.5f;
  private ZoomButtonsController zoomController;
  private float zoom = 12;

  // Top panel items.
  private static final float PANEL_HEIGHT = 50;
  private static final float PANEL_TEXT_MARGIN = 10;
  private static final float PANEL_NOTCH_HEIGHT = 10;
  private static final float PANEL_NOTCH_WIDTH = 10;
  private static final float PANEL_TEXT_BASELINE =
      PANEL_HEIGHT - PANEL_NOTCH_HEIGHT - PANEL_TEXT_MARGIN;
  private static final String DEGREES_SYMBOL = "\u00b0";
  private Path topPanel;

  // Main class.
  private final FlightMap flightMap;

  // Coordinates to draw the aircraft on the map.
  private int aircraftX;
  private int aircraftY;

  // Static initialization.
  static {
    MAGENTA_PAINT.setAntiAlias(true);
    MAGENTA_PAINT.setColor(Color.MAGENTA);
    AIRPORT_LABEL_PAINT.setColor(Color.WHITE);
    AIRPORT_LABEL_PAINT.setTypeface(Typeface.SANS_SERIF);
    AIRPORT_LABEL_PAINT.setTextSize(20);
    AIRPORT_LABEL_PAINT.setAntiAlias(true);
    AIRPORT_LABEL_PAINT.setTextAlign(Align.CENTER);
    AIRCRAFT_PAINT.setColor(Color.WHITE);
    AIRCRAFT_PAINT.setStrokeWidth(3);
    PANEL_PAINT.setARGB(200, 200, 200, 200);
    PANEL_TEXT_PAINT.setColor(Color.WHITE);
    PANEL_TEXT_PAINT.setTypeface(Typeface.SANS_SERIF);
    PANEL_TEXT_PAINT.setTextSize(30);
    PANEL_TEXT_PAINT.setAntiAlias(true);
  }

  public MapView(FlightMap flightMap) {
    super(flightMap);
    this.flightMap = flightMap;
    getHolder().addCallback(this);
    setFocusable(true); // make sure we get key events
    setKeepScreenOn(true);
    createZoomController();
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    showZoomController();
    return true;
  }

  @Override
  public boolean onTrackballEvent(MotionEvent event) {
    showZoomController();
    return true;
  }

  private synchronized void showZoomController() {
    if (null != zoomController) {
      zoomController.setVisible(true);
    }
  }

  @Override
  protected void onDetachedFromWindow() {
    if (null != zoomController) {
      zoomController.setVisible(false);
    }
  }

  /**
   * Surface dimensions changed.
   */
  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    Log.i(TAG, String.format("format=%d w=%d h=%d", format, width, height));
    aircraftX = width / 2;
    aircraftY = height - (height / 4);
    createTopPanelPath(width);
  }

  private void createTopPanelPath(int width) {
    final float center = width / 2.0f;
    topPanel = new Path();
    topPanel.moveTo(0, 0);
    topPanel.lineTo(width, 0);
    topPanel.lineTo(width, PANEL_HEIGHT);
    topPanel.lineTo(center + PANEL_NOTCH_WIDTH, PANEL_HEIGHT);
    topPanel.lineTo(center, PANEL_HEIGHT - PANEL_NOTCH_HEIGHT);
    topPanel.lineTo(center - PANEL_NOTCH_WIDTH, PANEL_HEIGHT);
    topPanel.lineTo(0, PANEL_HEIGHT);
    topPanel.close();
  }

  @Override
  public void surfaceCreated(SurfaceHolder holder) {
  }

  /**
   * 
   */
  private void createZoomController() {
    zoomController = new ZoomButtonsController(this);
    zoomController.setOnZoomListener(new ZoomButtonsController.OnZoomListener() {
      @Override
      public void onZoom(boolean zoomIn) {
        final float zoomCopy = getZoom(); // copy for thread safety.
        if (zoomIn) {
          setZoom(zoomCopy + ZOOM_STEP);
        } else {
          setZoom(zoomCopy - ZOOM_STEP);
        }
        zoomController.setZoomInEnabled(getZoom() < MAX_ZOOM);
        zoomController.setZoomOutEnabled(getZoom() > MIN_ZOOM);
      }

      @Override
      public void onVisibilityChanged(boolean visible) {
        // Ignored.
      }
    });
  }
  
  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {
  }

  public void drawMap(Location location) {
{'fraction_non_alphanumeric': 0.09068432671081678, 'fraction_numerical': 0.009271523178807948, 'mean_word_length': 3.8463842533162174, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1456945', 'n_tokens_mistral': 3675, 'n_tokens_neox': 3461, 'n_words': 906}