WeatherInformation WP8: map improvements
authorgu.martinm@gmail.com <gu.martinm@gmail.com>
Tue, 5 Aug 2014 23:56:48 +0000 (01:56 +0200)
committergu.martinm@gmail.com <gu.martinm@gmail.com>
Tue, 5 Aug 2014 23:56:48 +0000 (01:56 +0200)
(and many doubts/TODOs)

WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml
WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/Model/Services/StoredLocation.cs
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.Designer.cs
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.es.resx
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.es.xlf
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.qps-ploc.xlf
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.resx

index 9c3e841..2aec0e7 100644 (file)
@@ -19,6 +19,7 @@
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition/>
+            <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
 
         <!--TitlePanel contiene el nombre de la aplicación y el título de la página-->
@@ -29,8 +30,9 @@
 
         <!--ContentPanel. Colocar aquí el contenido adicional-->
         <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
-            <maps:Map x:Name="mapWeatherInformation" Grid.Row="1"/>
+            <maps:Map x:Name="mapWeatherInformation" Grid.Row="1" Tap="mapWeatherInformation_Tap"/>
         </Grid>
+        <Button x:Name="SaveLocationButton" Grid.Row="2" Content="{Binding LocalizedResources.MapPageSaveLocationButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}" HorizontalAlignment="Center"  VerticalAlignment="Bottom" Click="SaveLocationButton_Click"/>
     </Grid>
 
 </phone:PhoneApplicationPage>
\ No newline at end of file
index e2b89d3..0162259 100644 (file)
@@ -60,7 +60,16 @@ namespace WeatherInformation
                 return;
             }
 
-            this.GetLocation();
+            if (!StoredLocation.IsThereCurrentLocation)
+            {
+                this.GetLocation();
+            }
+            else
+            {
+                GeoCoordinate geoCoordinate = CoordinateHelper.GetStoredGeoCoordinate();
+
+                this.UpdateMap(geoCoordinate, StoredLocation.City, StoredLocation.Country);
+            }
         }
 
         private async void GetLocation()
@@ -74,12 +83,9 @@ namespace WeatherInformation
                     maximumAge: TimeSpan.FromMinutes(5),
                     timeout: TimeSpan.FromSeconds(10)
                     );
-                GeoCoordinate currentGeoCoordinate = CoordinateConverter.ConvertGeocoordinate(geoposition.Coordinate);
+                GeoCoordinate currentGeoCoordinate = CoordinateHelper.ConvertGeocoordinate(geoposition.Coordinate);
 
-                ReverseGeocodeQuery currentReverseGeocodeQuery = new ReverseGeocodeQuery();
-                currentReverseGeocodeQuery.GeoCoordinate = currentGeoCoordinate;
-                currentReverseGeocodeQuery.QueryCompleted += QueryCompletedCallback;
-                currentReverseGeocodeQuery.QueryAsync();  
+                ReverseGeocodeAndUpdateMap(currentGeoCoordinate);
             }
             catch (Exception ex)
             {
@@ -103,6 +109,18 @@ namespace WeatherInformation
             }
         }
 
+        // TODO: problems updating Map because this method may be called when automatically retrieving
+        //       the current user's location or when user taps on map tyring to choose by herself her location.
+        //       There could be 2 threads updating Map at the same time. Solution: remove the feature
+        //       of getting the current user's location (user must always choose her/his location instead of doing
+        //       it automatically)
+        private void ReverseGeocodeAndUpdateMap(GeoCoordinate currentGeoCoordinate)
+        {
+            ReverseGeocodeQuery currentReverseGeocodeQuery = new ReverseGeocodeQuery();
+            currentReverseGeocodeQuery.GeoCoordinate = currentGeoCoordinate;
+            currentReverseGeocodeQuery.QueryCompleted += QueryCompletedCallback;
+            currentReverseGeocodeQuery.QueryAsync();
+        }
 
         private void QueryCompletedCallback(object sender, QueryCompletedEventArgs<IList<MapLocation>> eventData)
         {
@@ -122,48 +140,47 @@ namespace WeatherInformation
             {
                 if (eventData.Result.Count > 0)
                 {
+                    // TODO: What if there is no city or country. Is there null value or empty string?
                     MapAddress address = eventData.Result[0].Information.Address;
                     GeoCoordinate currentGeoCoordinate = eventData.Result[0].GeoCoordinate;
 
-                    string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", address.City, address.Country);
-                    this.LocationTextCityCountry.Text = cityCountry;
-
-                    // TODO: If I want to store more than one place I should use a database :(
-                    StoredLocation.CurrentLatitude = currentGeoCoordinate.Latitude;
-                    StoredLocation.CurrentLongitude = currentGeoCoordinate.Longitude;
-                    // TODO: If I want to store more thant one place I should use a database :(
-                    StoredLocation.City = address.City;
-                    StoredLocation.Country = address.Country;
-                    StoredLocation.IsNewLocation = true;
-
-                    // Create a small circle to mark the current location.
-                    Ellipse myCircle = new Ellipse();
-                    myCircle.Fill = new SolidColorBrush(Colors.Blue);
-                    myCircle.Height = 20;
-                    myCircle.Width = 20;
-                    myCircle.Opacity = 50;
-
-                    // Create a MapOverlay to contain the circle.
-                    MapOverlay myLocationOverlay = new MapOverlay();
-                    myLocationOverlay.Content = myCircle;
-                    myLocationOverlay.PositionOrigin = new Point(0.5, 0.5);
-                    myLocationOverlay.GeoCoordinate = currentGeoCoordinate;
-
-                    // Create a MapLayer to contain the MapOverlay.
-                    MapLayer myLocationLayer = new MapLayer();
-                    myLocationLayer.Add(myLocationOverlay);
-
-                    this.mapWeatherInformation.Center = currentGeoCoordinate;
-                    this.mapWeatherInformation.ZoomLevel = 13;
-
-                    // Add the MapLayer to the Map.
-                    this.mapWeatherInformation.Layers.Add(myLocationLayer);  
+                    UpdateMap(currentGeoCoordinate, address.City, address.Country);
                 }
             }
         }
 
+        private void UpdateMap(GeoCoordinate geoCoordinate, string city, string country)
+        {
+            // Create a small circle to mark the current location.
+            Ellipse myCircle = new Ellipse();
+            myCircle.Fill = new SolidColorBrush(Colors.Blue);
+            myCircle.Height = 20;
+            myCircle.Width = 20;
+            myCircle.Opacity = 50;
+
+            // Create a MapOverlay to contain the circle.
+            MapOverlay myLocationOverlay = new MapOverlay();
+            myLocationOverlay.Content = myCircle;
+            myLocationOverlay.PositionOrigin = new Point(0.5, 0.5);
+            myLocationOverlay.GeoCoordinate = geoCoordinate;
+
+            // Create a MapLayer to contain the MapOverlay.
+            MapLayer myLocationLayer = new MapLayer();
+            myLocationLayer.Add(myLocationOverlay);
+
+            this.mapWeatherInformation.Layers.Clear();
+
+            this.mapWeatherInformation.Center = geoCoordinate;
+            this.mapWeatherInformation.ZoomLevel = 13;
+
+            // TODO: What if there is no city or country. Is there null value or empty string?
+            string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
+            this.LocationTextCityCountry.Text = cityCountry;
+            // Add the MapLayer to the Map.
+            this.mapWeatherInformation.Layers.Add(myLocationLayer);
+        }
 
-        public static class CoordinateConverter
+        private static class CoordinateHelper
         {
             public static GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate)
             {
@@ -178,7 +195,52 @@ namespace WeatherInformation
                     geocoordinate.Heading ?? Double.NaN
                     );
             }
+
+            // TODO: database
+            // TODO: What if Double.NAN or null... Am I going to have some problem storing data in IsolatedStorageSettings?
+            public static void StoreGeoCoordinate(GeoCoordinate geocoordinate)
+            {
+                StoredLocation.CurrentLatitude = geocoordinate.Latitude;
+                StoredLocation.CurrentLongitude = geocoordinate.Longitude;
+                StoredLocation.IsNewLocation = true;
+                StoredLocation.CurrentAltitude = geocoordinate.Altitude;
+                StoredLocation.CurrentHorizontalAccuracy = geocoordinate.HorizontalAccuracy;
+                StoredLocation.CurrentVerticalAccuracy = geocoordinate.VerticalAccuracy;
+                StoredLocation.CurrentSpeed = geocoordinate.Speed;
+                StoredLocation.CurrentCourse = geocoordinate.Course;
+            }
+
+            public static GeoCoordinate GetStoredGeoCoordinate()
+            {
+                return new GeoCoordinate
+                    (
+                    StoredLocation.CurrentLatitude,
+                    StoredLocation.CurrentLongitude,
+                    StoredLocation.CurrentAltitude,
+                    StoredLocation.CurrentHorizontalAccuracy,
+                    StoredLocation.CurrentVerticalAccuracy,
+                    StoredLocation.CurrentSpeed,
+                    StoredLocation.CurrentCourse
+                    );
+            }
+        }
+
+        private void mapWeatherInformation_Tap(object sender, System.Windows.Input.GestureEventArgs e)
+        {
+            var point = e.GetPosition(this.mapWeatherInformation);
+            GeoCoordinate geocoordinate = this.mapWeatherInformation.ConvertViewportPointToGeoCoordinate(point);
+            ReverseGeocodeAndUpdateMap(geocoordinate);
         }
+      
+        private void SaveLocationButton_Click(object sender, RoutedEventArgs e)
+        {
+            // TODO: Could there some problem if user clicks button and thread is in this very moment updating map?
+            var geoCoordinate = this.mapWeatherInformation.Center;
 
+            // TODO: What if there is no city or country. Is there null value or empty string?
+            //StoredLocation.City = address.City;
+            //StoredLocation.Country = address.Country;
+            CoordinateHelper.StoreGeoCoordinate(geoCoordinate);
+        }
     }
 }
\ No newline at end of file
index e2f682e..f563909 100644 (file)
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
 namespace WeatherInformation.Model.Services
 {
     // TODO: If I want to store more than one place I should use a database :(
+    // TODO: What if Double.NAN or null... Am I going to have some problem storing data in IsolatedStorageSettings?
     class StoredLocation
     {
         public static double CurrentLatitude
@@ -44,6 +45,91 @@ namespace WeatherInformation.Model.Services
             }
         }
 
+        public static double CurrentAltitude
+        {
+            get
+            {
+                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentAltitude"))
+                {
+                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentAltitude"];
+                }
+                // TODO: what if settings does not contain this value? :/
+                return 0;
+            }
+            set
+            {
+                IsolatedStorageSettings.ApplicationSettings["CurrentAltitude"] = value;
+            }
+        }
+
+        public static double CurrentHorizontalAccuracy
+        {
+            get
+            {
+                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentHorizontalAccuracy"))
+                {
+                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentHorizontalAccuracy"];
+                }
+                // TODO: what if settings does not contain this value? :/
+                return 0;
+            }
+            set
+            {
+                IsolatedStorageSettings.ApplicationSettings["CurrentHorizontalAccuracy"] = value;
+            }
+        }
+
+        public static double CurrentVerticalAccuracy
+        {
+            get
+            {
+                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentVerticalAccuracy"))
+                {
+                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentVerticalAccuracy"];
+                }
+                // TODO: what if settings does not contain this value? :/
+                return 0;
+            }
+            set
+            {
+                IsolatedStorageSettings.ApplicationSettings["CurrentVerticalAccuracy"] = value;
+            }
+        }
+
+        public static double CurrentSpeed
+        {
+            get
+            {
+                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentSpeed"))
+                {
+                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentSpeed"];
+                }
+                // TODO: what if settings does not contain this value? :/
+                return 0;
+            }
+            set
+            {
+                IsolatedStorageSettings.ApplicationSettings["CurrentSpeed"] = value;
+            }
+        }
+
+        public static double CurrentCourse
+        {
+            get
+            {
+                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentCourse"))
+                {
+                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentCourse"];
+                }
+                // TODO: what if settings does not contain this value? :/
+                return 0;
+            }
+            set
+            {
+                IsolatedStorageSettings.ApplicationSettings["CurrentCourse"] = value;
+            }
+        }
+
         public static string City
         {
             get
index 8ce8080..ac8fb74 100644 (file)
@@ -304,6 +304,15 @@ namespace WeatherInformation.Resources {
         }
         
         /// <summary>
+        ///   Busca una cadena traducida similar a Save Location.
+        /// </summary>
+        public static string MapPageSaveLocationButton {
+            get {
+                return ResourceManager.GetString("MapPageSaveLocationButton", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Busca una cadena traducida similar a Location autodetection seems to be disabled in your phone.
         /// </summary>
         public static string NoticeErrorLocationAutodetection {
index 9ce3e98..1211412 100644 (file)
   <data name="SelectedDatePageDay" xml:space="preserve">
     <value>DÍA</value>
   </data>
+  <data name="MapPageSaveLocationButton" xml:space="preserve">
+    <value>Guardar posición</value>
+    <comment>Map page, button saves the user's chosen location</comment>
+  </data>
 </root>
\ No newline at end of file
index a60ca8f..e2ef983 100644 (file)
           <source>14</source>
           <target state="new">14</target>
           <note from="MultilingualBuild" annotates="source" priority="2">Not to be translated.</note>
-        </trans-unit>
+          </trans-unit>
+        <trans-unit id="Resx/MapPageSaveLocationButton" translate="yes" xml:space="preserve">
+          <source>Save Location</source>
+          <target state="translated">Guardar posición</target>
+          <note from="MultilingualBuild" annotates="source" priority="2">Map page, button saves the user's chosen location</note>
+          </trans-unit>
         <trans-unit id="Resx/SelectedDatePageMorning" translate="yes" xml:space="preserve">
           <source>MORNING</source>
           <target state="translated">MAÑANA</target>
index 106efef..3890ef8 100644 (file)
           <target state="new">14</target>
           <note from="MultilingualBuild" annotates="source" priority="2">Not to be translated.</note>
         </trans-unit>
+        <trans-unit id="Resx/MapPageSaveLocationButton" translate="yes" xml:space="preserve">
+          <source>Save Location</source>
+          <target state="new">Save Location</target>
+          <note from="MultilingualBuild" annotates="source" priority="2">Map page, button saves the user's chosen location</note>
+        </trans-unit>
         <trans-unit id="Resx/SelectedDatePageMorning" translate="yes" xml:space="preserve">
           <source>MORNING</source>
           <target state="new">MORNING</target>
index 596a211..5ad149f 100644 (file)
     <value>14</value>
     <comment>Not to be translated.</comment>
   </data>
+  <data name="MapPageSaveLocationButton" xml:space="preserve">
+    <value>Save Location</value>
+    <comment>Map page, button saves the user's chosen location</comment>
+  </data>
 </root>
\ No newline at end of file