altosdroid: Add map source preference
[fw/altos] / altosdroid / src / org / altusmetrum / AltosDroid / AltosMapView.java
1 /*
2  * Copyright © 2015 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package org.altusmetrum.AltosDroid;
19
20 import java.util.*;
21 import java.io.*;
22
23 import org.altusmetrum.altoslib_7.*;
24
25 import android.app.Activity;
26 import android.graphics.*;
27 import android.os.Bundle;
28 import android.support.v4.app.Fragment;
29 import android.support.v4.app.FragmentTransaction;
30 import android.view.*;
31 import android.widget.*;
32 import android.location.Location;
33 import android.content.*;
34 import android.util.*;
35
36 public class AltosMapView extends View implements ScaleGestureDetector.OnScaleGestureListener {
37         ScaleGestureDetector    scale_detector;
38         boolean                 scaling;
39         TabMapOffline           tab;
40
41         class Line {
42                 AltosLatLon     a, b;
43
44                 void paint() {
45                         if (a != null && b != null) {
46                                 AltosPointDouble        a_screen = tab.map.transform.screen(a);
47                                 AltosPointDouble        b_screen = tab.map.transform.screen(b);
48                                 tab.paint.setColor(0xff8080ff);
49                                 tab.canvas.drawLine((float) a_screen.x, (float) a_screen.y,
50                                                     (float) b_screen.x, (float) b_screen.y,
51                                                     tab.paint);
52                         }
53                 }
54
55                 void set_a(AltosLatLon a) {
56                         this.a = a;
57                 }
58
59                 void set_b(AltosLatLon b) {
60                         this.b = b;
61                 }
62
63                 Line() {
64                 }
65         }
66
67         Line line = new Line();
68
69         private void draw_bitmap(AltosLatLon lat_lon, Bitmap bitmap, int off_x, int off_y) {
70                 if (lat_lon != null && tab.map != null && tab.map.transform != null) {
71                         AltosPointInt pt = new AltosPointInt(tab.map.transform.screen(lat_lon));
72
73                         tab.canvas.drawBitmap(bitmap, pt.x - off_x, pt.y - off_y, tab.paint);
74                 }
75         }
76
77         private void draw_positions() {
78                 line.set_a(tab.map.last_position);
79                 line.set_b(tab.here);
80                 line.paint();
81                 draw_bitmap(tab.pad, tab.pad_bitmap, tab.pad_off_x, tab.pad_off_y);
82
83                 Rocket[]        rockets = tab.rockets.values().toArray(new Rocket[0]);
84
85                 Arrays.sort(rockets);
86                 for (Rocket rocket : rockets)
87                         rocket.paint();
88                 draw_bitmap(tab.here, tab.here_bitmap, tab.here_off_x, tab.here_off_y);
89         }
90
91         @Override public void invalidate() {
92                 Rect r = new Rect();
93                 getDrawingRect(r);
94                 super.invalidate();
95         }
96
97         @Override public void invalidate(int l, int t, int r, int b) {
98                 Rect rect = new Rect();
99                 getDrawingRect(rect);
100                 super.invalidate();
101         }
102
103         @Override
104         protected void onDraw(Canvas view_canvas) {
105                 tab.canvas = view_canvas;
106                 tab.paint = new Paint(Paint.ANTI_ALIAS_FLAG);
107                 tab.paint.setStrokeWidth(tab.stroke_width);
108                 tab.paint.setStrokeCap(Paint.Cap.ROUND);
109                 tab.paint.setStrokeJoin(Paint.Join.ROUND);
110                 tab.paint.setTextSize(40);
111                 tab.map.paint();
112                 draw_positions();
113                 tab.canvas = null;
114         }
115
116         public boolean onScale(ScaleGestureDetector detector) {
117                 float   f = detector.getScaleFactor();
118
119                 if (f <= 0.8) {
120                         tab.map.set_zoom_centre(tab.map.get_zoom() - 1, new AltosPointInt((int) detector.getFocusX(), (int) detector.getFocusY()));
121                         return true;
122                 }
123                 if (f >= 1.2) {
124                         tab.map.set_zoom_centre(tab.map.get_zoom() + 1, new AltosPointInt((int) detector.getFocusX(), (int) detector.getFocusY()));
125                         return true;
126                 }
127                 return false;
128         }
129
130         public boolean onScaleBegin(ScaleGestureDetector detector) {
131                 return true;
132         }
133
134         public void onScaleEnd(ScaleGestureDetector detector) {
135         }
136
137         @Override
138         public boolean dispatchTouchEvent(MotionEvent event) {
139                 scale_detector.onTouchEvent(event);
140
141                 if (scale_detector.isInProgress()) {
142                         scaling = true;
143                 }
144
145                 if (scaling) {
146                         if (event.getAction() == MotionEvent.ACTION_UP) {
147                                 scaling = false;
148                         }
149                         return true;
150                 }
151
152                 if (event.getAction() == MotionEvent.ACTION_DOWN) {
153                         tab.map.touch_start((int) event.getX(), (int) event.getY(), true);
154                 } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
155                         tab.map.touch_continue((int) event.getX(), (int) event.getY(), true);
156                 }
157                 return true;
158         }
159
160         public void set_tab(TabMapOffline tab) {
161                 this.tab = tab;
162         }
163
164         public AltosMapView(Context context, AttributeSet attrs) {
165                 super(context, attrs);
166                 scale_detector = new ScaleGestureDetector(context, this);
167         }
168 }