altosdroid: Split out AltosMapView into separate file
authorKeith Packard <keithp@keithp.com>
Fri, 29 May 2015 05:13:39 +0000 (22:13 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 29 May 2015 05:14:39 +0000 (22:14 -0700)
This lets us use the regular layout configuration bits in the .xml
file instead of needing to patch the map object into the display. That
was causing problems when re-entering the map tab as the map view
would somehow end up with a zero width.

Signed-off-by: Keith Packard <keithp@keithp.com>
altosdroid/res/layout/tab_map_offline.xml [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/AltosMapView.java [new file with mode: 0644]
altosdroid/src/org/altusmetrum/AltosDroid/TabMapOffline.java

diff --git a/altosdroid/res/layout/tab_map_offline.xml b/altosdroid/res/layout/tab_map_offline.xml
new file mode 100644 (file)
index 0000000..e6f134d
--- /dev/null
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright © 2013 Mike Beattie <mike@ethernal.org>
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; version 2 of the License.
+
+     This program is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License along
+     with this program; if not, write to the Free Software Foundation, Inc.,
+     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+       android:layout_width="match_parent"
+       android:layout_height="match_parent"
+       android:orientation="vertical" >
+
+  <org.altusmetrum.AltosDroid.AltosMapView android:id="@+id/map_view_offline"
+                                          android:layout_width="fill_parent"
+                                          android:layout_height="wrap_content"
+                                          android:layout_weight="1"
+                                          />
+  
+  <LinearLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:baselineAligned="true"
+      android:orientation="horizontal" >
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/distance_label_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/distance_label" />
+
+      <TextView
+         android:id="@+id/distance_value_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/distance_label_offline"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/bearing_label_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/bearing_label" />
+
+      <TextView
+         android:id="@+id/bearing_value_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/bearing_label_offline"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+  </LinearLayout>
+
+  <LinearLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:baselineAligned="true"
+      android:orientation="horizontal" >
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/target_lat_label_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/target_latitude_label" />
+
+      <TextView
+         android:id="@+id/target_lat_value_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/target_lat_label_offline"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/target_lon_label_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/target_longitude_label" />
+
+      <TextView
+         android:id="@+id/target_lon_value_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/target_lon_label_offline"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+  </LinearLayout>
+
+  <LinearLayout
+      xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:baselineAligned="true"
+      android:orientation="horizontal" >
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/receiver_lat_label_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/receiver_latitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_lat_value_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/receiver_lat_label_offline"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+
+    <RelativeLayout
+       android:layout_width="0dp"
+       android:layout_height="wrap_content"
+       android:layout_weight="1"
+       android:paddingTop="5dp" >
+
+      <TextView
+         android:id="@+id/receiver_lon_label_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:paddingRight="4dp"
+         android:text="@string/receiver_longitude_label" />
+
+      <TextView
+         android:id="@+id/receiver_lon_value_offline"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:layout_toRightOf="@id/receiver_lon_label_offline"
+         android:text=""
+         android:textAppearance="?android:attr/textAppearanceSmall" />
+    </RelativeLayout>
+  </LinearLayout>
+</LinearLayout>
diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapView.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapView.java
new file mode 100644 (file)
index 0000000..460a3a2
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import java.io.*;
+
+import org.altusmetrum.altoslib_7.*;
+
+import android.app.Activity;
+import android.graphics.*;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.view.*;
+import android.widget.*;
+import android.location.Location;
+import android.content.*;
+import android.util.*;
+
+public class AltosMapView extends View implements ScaleGestureDetector.OnScaleGestureListener {
+       ScaleGestureDetector    scale_detector;
+       boolean                 scaling;
+       TabMapOffline           tab;
+
+       class Line {
+               AltosLatLon     a, b;
+
+               void paint() {
+                       if (a != null && b != null) {
+                               AltosPointDouble        a_screen = tab.map.transform.screen(a);
+                               AltosPointDouble        b_screen = tab.map.transform.screen(b);
+                               tab.paint.setColor(0xff8080ff);
+                               tab.canvas.drawLine((float) a_screen.x, (float) a_screen.y,
+                                                   (float) b_screen.x, (float) b_screen.y,
+                                                   tab.paint);
+                       }
+               }
+
+               void set_a(AltosLatLon a) {
+                       this.a = a;
+               }
+
+               void set_b(AltosLatLon b) {
+                       this.b = b;
+               }
+
+               Line() {
+               }
+       }
+
+       Line line = new Line();
+
+       private void draw_bitmap(AltosLatLon lat_lon, Bitmap bitmap, int off_x, int off_y) {
+               if (lat_lon != null && tab.map != null && tab.map.transform != null) {
+                       AltosPointInt pt = new AltosPointInt(tab.map.transform.screen(lat_lon));
+
+                       tab.canvas.drawBitmap(bitmap, pt.x - off_x, pt.y - off_y, tab.paint);
+               }
+       }
+
+       private void draw_positions() {
+               line.set_a(tab.map.last_position);
+               line.set_b(tab.here);
+               line.paint();
+               draw_bitmap(tab.pad, tab.pad_bitmap, tab.pad_off_x, tab.pad_off_y);
+               for (Rocket rocket : tab.rockets.values())
+                       rocket.paint();
+               draw_bitmap(tab.here, tab.here_bitmap, tab.here_off_x, tab.here_off_y);
+       }
+
+       @Override public void invalidate() {
+               Rect r = new Rect();
+               getDrawingRect(r);
+               super.invalidate();
+       }
+
+       @Override public void invalidate(int l, int t, int r, int b) {
+               Rect rect = new Rect();
+               getDrawingRect(rect);
+               super.invalidate();
+       }
+
+       @Override
+       protected void onDraw(Canvas view_canvas) {
+               tab.canvas = view_canvas;
+               tab.paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+               tab.paint.setStrokeWidth(tab.stroke_width);
+               tab.paint.setStrokeCap(Paint.Cap.ROUND);
+               tab.paint.setStrokeJoin(Paint.Join.ROUND);
+               tab.paint.setTextSize(40);
+               tab.map.paint();
+               draw_positions();
+               tab.canvas = null;
+       }
+
+       public boolean onScale(ScaleGestureDetector detector) {
+               float   f = detector.getScaleFactor();
+               if (f <= 0.8) {
+                       tab.map.set_zoom(tab.map.get_zoom() - 1);
+                       return true;
+               }
+               if (f >= 1.2) {
+                       tab.map.set_zoom(tab.map.get_zoom() + 1);
+                       return true;
+               }
+               return false;
+       }
+
+       public boolean onScaleBegin(ScaleGestureDetector detector) {
+               return true;
+       }
+
+       public void onScaleEnd(ScaleGestureDetector detector) {
+       }
+
+       @Override
+       public boolean dispatchTouchEvent(MotionEvent event) {
+               scale_detector.onTouchEvent(event);
+
+               if (scale_detector.isInProgress()) {
+                       scaling = true;
+               }
+
+               if (scaling) {
+                       if (event.getAction() == MotionEvent.ACTION_UP) {
+                               scaling = false;
+                       }
+                       return true;
+               }
+
+               if (event.getAction() == MotionEvent.ACTION_DOWN) {
+                       tab.map.touch_start((int) event.getX(), (int) event.getY(), true);
+               } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+                       tab.map.touch_continue((int) event.getX(), (int) event.getY(), true);
+               }
+               return true;
+       }
+
+       public void set_tab(TabMapOffline tab) {
+               this.tab = tab;
+       }
+
+       public AltosMapView(Context context, AttributeSet attrs) {
+               super(context, attrs);
+               scale_detector = new ScaleGestureDetector(context, this);
+       }
+}
index cbf500187c1fbfbe0063a44898b57add7cdfff38..90b4115634ea4ef26b3116e683b252045240308f 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.altusmetrum.AltosDroid;
 
 
 package org.altusmetrum.AltosDroid;
 
-import java.util.Arrays;
+import java.util.*;
 import java.io.*;
 
 import org.altusmetrum.altoslib_7.*;
 import java.io.*;
 
 import org.altusmetrum.altoslib_7.*;
@@ -32,6 +32,26 @@ import android.widget.*;
 import android.location.Location;
 import android.content.*;
 
 import android.location.Location;
 import android.content.*;
 
+class Rocket {
+       AltosLatLon     position;
+       String          name;
+       TabMapOffline   tab;
+
+       void paint() {
+               tab.draw_bitmap(position, tab.rocket_bitmap, tab.rocket_off_x, tab.rocket_off_y);
+               tab.draw_text(position, name, 0, 3*tab.rocket_bitmap.getHeight()/4);
+       }
+
+       void set_position(AltosLatLon position) {
+               this.position = position;
+       }
+
+       Rocket(String name, TabMapOffline tab) {
+               this.name = name;
+               this.tab = tab;
+       }
+}
+
 public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
 
        AltosDroid mAltosDroid;
 public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
 
        AltosDroid mAltosDroid;
@@ -59,117 +79,41 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
        private TextView mTargetLongitudeView;
        private TextView mReceiverLatitudeView;
        private TextView mReceiverLongitudeView;
        private TextView mTargetLongitudeView;
        private TextView mReceiverLatitudeView;
        private TextView mReceiverLongitudeView;
+       private AltosMapView map_view;
 
        private double mapAccuracy = -1;
 
        int     stroke_width = 20;
 
 
        private double mapAccuracy = -1;
 
        int     stroke_width = 20;
 
-       private void draw_bitmap(AltosLatLon lat_lon, Bitmap bitmap, int off_x, int off_y) {
-               if (lat_lon != null) {
-                       AltosPointInt pt = new AltosPointInt(map.transform.screen(lat_lon));
-
-                       canvas.drawBitmap(bitmap, pt.x - off_x, pt.y - off_y, paint);
-               }
-       }
-
-       class MapView extends View implements ScaleGestureDetector.OnScaleGestureListener {
-
-               ScaleGestureDetector    scale_detector;
-               boolean                 scaling;
 
 
-               private void draw_positions() {
-                       if (map.last_position != null && here != null) {
-                               AltosPointDouble        rocket_screen = map.transform.screen(map.last_position);
-                               AltosPointDouble        here_screen = map.transform.screen(here);
-                               paint.setColor(0xff8080ff);
-                               canvas.drawLine((float) rocket_screen.x, (float) rocket_screen.y,
-                                               (float) here_screen.x, (float) here_screen.y, paint);
-                       }
-                       draw_bitmap(pad, pad_bitmap, pad_off_x, pad_off_y);
-                       draw_bitmap(map.last_position, rocket_bitmap, rocket_off_x, rocket_off_y);
-                       draw_bitmap(here, here_bitmap, here_off_x, here_off_y);
-               }
-
-               protected void onDraw(Canvas view_canvas) {
-                       canvas = view_canvas;
-                       paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-                       paint.setStrokeWidth(stroke_width);
-                       paint.setStrokeCap(Paint.Cap.ROUND);
-                       paint.setStrokeJoin(Paint.Join.ROUND);
-                       map.paint();
-                       draw_positions();
-                       canvas = null;
-               }
-
-               public boolean onScale(ScaleGestureDetector detector) {
-                       float   f = detector.getScaleFactor();
-                       AltosDebug.debug("onScale %f\n", f);
-                       if (f <= 0.8) {
-                               map.set_zoom(map.get_zoom() - 1);
-                               return true;
-                       }
-                       if (f >= 1.2) {
-                               map.set_zoom(map.get_zoom() + 1);
-                               return true;
-                       }
-                       return false;
-               }
-
-               public boolean onScaleBegin(ScaleGestureDetector detector) {
-                       AltosDebug.debug("onScaleBegin %f\n", detector.getScaleFactor());
-                       return true;
-               }
-
-               public void onScaleEnd(ScaleGestureDetector detector) {
-                       AltosDebug.debug("onScaleEnd %f\n", detector.getScaleFactor());
-               }
-
-               @Override
-               public boolean dispatchTouchEvent(MotionEvent event) {
-                       scale_detector.onTouchEvent(event);
-
-                       if (scale_detector.isInProgress()) {
-                               scaling = true;
-                       }
+       void draw_text(AltosLatLon lat_lon, String text, int off_x, int off_y) {
+               if (lat_lon != null && map != null && map.transform != null) {
+                       AltosPointInt pt = new AltosPointInt(map.transform.screen(lat_lon));
 
 
-                       if (scaling) {
-                               if(AltosDebug.D) AltosDebug.debug("scale in progress\n");
-                               if (event.getAction() == MotionEvent.ACTION_UP) {
-                                       AltosDebug.debug("scale finished\n");
-                                       scaling = false;
-                               }
-                               return true;
-                       }
+                       Rect    bounds = new Rect();
+                       paint.getTextBounds(text, 0, text.length(), bounds);
 
 
-                       if (event.getAction() == MotionEvent.ACTION_DOWN) {
-                               AltosDebug.debug("down event %g %g\n", event.getX(), event.getY());
-                               map.touch_start((int) event.getX(), (int) event.getY(), true);
-                       } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
-                               AltosDebug.debug("continue event %g %g\n", event.getX(), event.getY());
-                               map.touch_continue((int) event.getX(), (int) event.getY(), true);
-                       }
-                       return true;
-               }
+                       int     width = bounds.right - bounds.left;
+                       int     height = bounds.bottom - bounds.top;
 
 
-               public MapView(Context context) {
-                       super(context);
-                       scale_detector = new ScaleGestureDetector(this.getContext(), this);
+                       float x = pt.x;
+                       float y = pt.y;
+                       x = x - width / 2.0f - off_x;
+                       y = y + height / 2.0f - off_y;
+                       paint.setColor(0xff000000);
+                       canvas.drawText(text, 0, text.length(), x, y, paint);
                }
        }
 
                }
        }
 
-       class MapFragment extends Fragment {
-               MapView map_view;
-
-               public View onCreateView(LayoutInflater inflator, ViewGroup container, Bundle savedInstanceState) {
-                       map_view = new MapView(container.getContext());
-                       return map_view;
-               }
+       void draw_bitmap(AltosLatLon lat_lon, Bitmap bitmap, int off_x, int off_y) {
+               if (lat_lon != null && map != null && map.transform != null) {
+                       AltosPointInt pt = new AltosPointInt(map.transform.screen(lat_lon));
 
 
-               public MapFragment() {
+                       canvas.drawBitmap(bitmap, pt.x - off_x, pt.y - off_y, paint);
                }
        }
 
                }
        }
 
-       MapFragment map_fragment;
+       HashMap<Integer,Rocket> rockets = new HashMap<Integer,Rocket>();
 
        /* AltosMapInterface */
 
 
        /* AltosMapInterface */
 
@@ -337,7 +281,6 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
                                        }
                                }
                        }
                                        }
                                }
                        }
-
                }
 
                public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
                }
 
                public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
@@ -351,39 +294,34 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
        }
 
        public int width() {
        }
 
        public int width() {
-               if (map_fragment != null && map_fragment.map_view != null)
-                       return map_fragment.map_view.getWidth();
+               if (map_view != null)
+                       return map_view.getWidth();
                return 500;
        }
 
        public int height() {
                return 500;
        }
 
        public int height() {
-               if (map_fragment != null && map_fragment.map_view != null)
-                       return map_fragment.map_view.getHeight();
+               if (map_view != null)
+                       return map_view.getHeight();
                return 500;
        }
 
        public void repaint() {
                return 500;
        }
 
        public void repaint() {
-               this.getActivity().runOnUiThread(new Runnable() {
-                               public void run() {
-                                       if (map_fragment != null && map_fragment.map_view != null)
-                                               map_fragment.map_view.invalidate();
-                               }
-                       });
+               if (map_view != null)
+                       map_view.postInvalidate();
        }
 
        }
 
-       public void repaint(AltosRectangle t_damage) {
-               final AltosRectangle damage = t_damage;
-               this.getActivity().runOnUiThread(new Runnable() {
-                               public void run() {
-                                       if (map_fragment != null && map_fragment.map_view != null)
-                                               map_fragment.map_view.invalidate(damage.x, damage.y, damage.x + damage.width, damage.y + damage.height);
-                               }
-                       });
+       public void repaint(AltosRectangle damage) {
+               if (map_view != null)
+                       map_view.postInvalidate(damage.x, damage.y, damage.x + damage.width, damage.y + damage.height);
        }
 
        public void set_zoom_label(String label) {
        }
 
        }
 
        public void set_zoom_label(String label) {
        }
 
+       public void debug(String format, Object ... arguments) {
+               AltosDebug.debug(format, arguments);
+       }
+
        @Override
        public void onAttach(Activity activity) {
                super.onAttach(activity);
        @Override
        public void onAttach(Activity activity) {
                super.onAttach(activity);
@@ -409,6 +347,11 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
                here_off_y = here_bitmap.getHeight() / 2;
        }
 
                here_off_y = here_bitmap.getHeight() / 2;
        }
 
+       @Override
+       public void onDetach() {
+               mAltosDroid = null;
+       }
+
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
@@ -416,40 +359,29 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
 
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-               View v = inflater.inflate(R.layout.tab_map, container, false);
-
-               map_fragment = new MapFragment();
-               map = new AltosMap(this);
-               mDistanceView  = (TextView)v.findViewById(R.id.distance_value);
-               mBearingView   = (TextView)v.findViewById(R.id.bearing_value);
-               mTargetLatitudeView  = (TextView)v.findViewById(R.id.target_lat_value);
-               mTargetLongitudeView = (TextView)v.findViewById(R.id.target_lon_value);
-               mReceiverLatitudeView  = (TextView)v.findViewById(R.id.receiver_lat_value);
-               mReceiverLongitudeView = (TextView)v.findViewById(R.id.receiver_lon_value);
+               View v = inflater.inflate(R.layout.tab_map_offline, container, false);
+
+               map_view = (AltosMapView)v.findViewById(R.id.map_view_offline);
+               map_view.set_tab(this);
+               mDistanceView  = (TextView)v.findViewById(R.id.distance_value_offline);
+               mBearingView   = (TextView)v.findViewById(R.id.bearing_value_offline);
+               mTargetLatitudeView  = (TextView)v.findViewById(R.id.target_lat_value_offline);
+               mTargetLongitudeView = (TextView)v.findViewById(R.id.target_lon_value_offline);
+               mReceiverLatitudeView  = (TextView)v.findViewById(R.id.receiver_lat_value_offline);
+               mReceiverLongitudeView = (TextView)v.findViewById(R.id.receiver_lon_value_offline);
                return v;
        }
 
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
                super.onActivityCreated(savedInstanceState);
                return v;
        }
 
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
                super.onActivityCreated(savedInstanceState);
-               getChildFragmentManager().beginTransaction().add(R.id.map, map_fragment).commit();
        }
        }
+
        @Override
        public void onDestroyView() {
                super.onDestroyView();
 
                mAltosDroid.unregisterTab(this);
        @Override
        public void onDestroyView() {
                super.onDestroyView();
 
                mAltosDroid.unregisterTab(this);
-               mAltosDroid = null;
-               map_fragment = null;
-
-//             Fragment fragment = (getFragmentManager().findFragmentById(R.id.map));
-//             FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
-//             ft.remove(fragment);
-//             ft.commit();
-       }
-
-       private void setupMap() {
        }
 
        private void center(double lat, double lon, double accuracy) {
        }
 
        private void center(double lat, double lon, double accuracy) {
@@ -478,6 +410,21 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
                        }
                        if (state.pad_lat != AltosLib.MISSING && pad == null)
                                pad = new AltosLatLon(state.pad_lat, state.pad_lon);
                        }
                        if (state.pad_lat != AltosLib.MISSING && pad == null)
                                pad = new AltosLatLon(state.pad_lat, state.pad_lon);
+
+                       int serial = state.serial;
+                       if (serial == AltosLib.MISSING)
+                               serial = 0;
+
+                       Rocket  rocket = null;
+
+                       if (state.gps != null && state.gps.locked) {
+                               if (!rockets.containsKey(serial)) {
+                                       rocket = new Rocket(String.format("%d", serial), this);
+                                       rockets.put(serial, rocket);
+                               } else
+                                       rocket = rockets.get(serial);
+                               rocket.set_position(new AltosLatLon(state.gps.lat, state.gps.lon));
+                       }
                }
 
                if (receiver != null) {
                }
 
                if (receiver != null) {
@@ -495,6 +442,7 @@ public class TabMapOffline extends AltosDroidTab implements AltosMapInterface {
 
        }
 
 
        }
 
+       @Override
        public void set_map_type(int map_type) {
                if (map != null)
                        map.set_maptype(map_type);
        public void set_map_type(int map_type) {
                if (map != null)
                        map.set_maptype(map_type);