[GTK] Added Maps project (#1349)
authorJavier Suárez Ruiz <javiersuarezruiz@hotmail.com>
Sat, 9 Dec 2017 00:34:51 +0000 (01:34 +0100)
committerRui Marinho <me@ruimarinho.net>
Sat, 9 Dec 2017 00:34:51 +0000 (00:34 +0000)
* Added Xamarin.Forms.Maps.GTK project

* Updated GTK Control Gallery sample adding maps reference.

* Added pending GMap libraries

16 files changed:
Xamarin.Forms.ControlGallery.GTK/Program.cs
Xamarin.Forms.ControlGallery.GTK/Xamarin.Forms.ControlGallery.GTK.csproj
Xamarin.Forms.Maps.GTK/FormsMaps.cs [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/GeocoderBackend.cs [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/Libs/GMap.NET.Core.dll [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/Libs/GMap.NET.GtkSharp.dll [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/Location.cs [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/MapRenderer.cs [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/Properties/AssemblyInfo.cs [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/Xamarin.Forms.Maps.GTK.csproj [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/app.config [new file with mode: 0644]
Xamarin.Forms.Maps.GTK/packages.config [new file with mode: 0644]
Xamarin.Forms.Platform.GTK/Libs/GMaps/GMap.NET.Core.dll [new file with mode: 0644]
Xamarin.Forms.Platform.GTK/Libs/GMaps/GMap.NET.GTK.dll [new file with mode: 0644]
Xamarin.Forms.Platform.GTK/Xamarin.Forms.Platform.GTK.csproj
Xamarin.Forms.sln

index a6dc4de..44d6a54 100644 (file)
@@ -5,6 +5,7 @@ using System;
 using Xamarin.Forms.Platform.GTK;
 using Xamarin.Forms.Platform.GTK.Renderers;
 using Xamarin.Forms.Controls;
+using Xamarin.Forms.Maps.GTK;
 
 [assembly: ExportRenderer(typeof(DisposePage), typeof(DisposePageRenderer))]
 [assembly: ExportRenderer(typeof(DisposeLabel), typeof(DisposeLabelRenderer))]
@@ -20,7 +21,8 @@ namespace Xamarin.Forms.ControlGallery.GTK
             GtkOpenGL.Init();
             GtkThemes.Init();
             Gtk.Application.Init();
-            Forms.Init();
+                       FormsMaps.Init(string.Empty);
+                       Forms.Init();
             var app = new App();
             //var app = new BasicOpenGLApp();
             //var app = new AdvancedOpenGLApp();
index ad9d3df..7480366 100644 (file)
       <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
       <Name>Xamarin.Forms.Core</Name>
     </ProjectReference>
+    <ProjectReference Include="..\Xamarin.Forms.Maps.GTK\Xamarin.Forms.Maps.GTK.csproj">
+      <Project>{a9772bb1-0e17-42f5-a6db-60bfccbfdb9d}</Project>
+      <Name>Xamarin.Forms.Maps.GTK</Name>
+    </ProjectReference>
     <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
       <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
       <Name>Xamarin.Forms.Maps</Name>
diff --git a/Xamarin.Forms.Maps.GTK/FormsMaps.cs b/Xamarin.Forms.Maps.GTK/FormsMaps.cs
new file mode 100644 (file)
index 0000000..c874d02
--- /dev/null
@@ -0,0 +1,25 @@
+namespace Xamarin.Forms.Maps.GTK
+{
+    public static class FormsMaps
+    {
+        static bool _isInitialized;
+
+        internal static string AuthenticationToken { get; set; }
+
+        public static void Init()
+        {
+            if (_isInitialized)
+                return;
+
+            GeocoderBackend.Register();
+            _isInitialized = true;
+        }
+
+        public static void Init(string authenticationToken)
+        {
+            AuthenticationToken = authenticationToken;
+
+            Init();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Xamarin.Forms.Maps.GTK/GeocoderBackend.cs b/Xamarin.Forms.Maps.GTK/GeocoderBackend.cs
new file mode 100644 (file)
index 0000000..7e2305b
--- /dev/null
@@ -0,0 +1,49 @@
+using GMap.NET;
+using GMap.NET.MapProviders;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Xamarin.Forms.Maps.GTK
+{
+    internal class GeocoderBackend
+    {
+        public static void Register()
+        {
+            Geocoder.GetPositionsForAddressAsyncFunc = GetPositionsForAddressAsync;
+            Geocoder.GetAddressesForPositionFuncAsync = GetAddressesForPositionAsync;
+        }
+
+        public static Task<IEnumerable<Position>> GetPositionsForAddressAsync(string address)
+        {
+            var points = new List<PointLatLng>();
+            var positions = new List<Position>();
+            GMapProviders.GoogleMap.GetPoints(address, out points);
+
+            if (points != null && points.Any())
+            {
+                foreach (var point in points)
+                {
+                    positions.Add(new Position(point.Lat, point.Lng));
+                }
+            }
+
+            return Task.FromResult<IEnumerable<Position>>(positions);
+        }
+
+        public static Task<IEnumerable<string>> GetAddressesForPositionAsync(Position position)
+        {
+            var point = new PointLatLng(position.Latitude, position.Longitude);
+            var direction = new GDirections();
+            var addresses = new List<string>();
+            GMapProviders.GoogleMap.GetDirections(out direction, point, point, false, true, false, false, true);
+
+            if (!string.IsNullOrEmpty(direction.StartAddress))
+            {
+                addresses.Add(direction.StartAddress);
+            }
+            
+            return Task.FromResult<IEnumerable<string>>(addresses);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Xamarin.Forms.Maps.GTK/Libs/GMap.NET.Core.dll b/Xamarin.Forms.Maps.GTK/Libs/GMap.NET.Core.dll
new file mode 100644 (file)
index 0000000..e457ada
Binary files /dev/null and b/Xamarin.Forms.Maps.GTK/Libs/GMap.NET.Core.dll differ
diff --git a/Xamarin.Forms.Maps.GTK/Libs/GMap.NET.GtkSharp.dll b/Xamarin.Forms.Maps.GTK/Libs/GMap.NET.GtkSharp.dll
new file mode 100644 (file)
index 0000000..3b95612
Binary files /dev/null and b/Xamarin.Forms.Maps.GTK/Libs/GMap.NET.GtkSharp.dll differ
diff --git a/Xamarin.Forms.Maps.GTK/Location.cs b/Xamarin.Forms.Maps.GTK/Location.cs
new file mode 100644 (file)
index 0000000..7bca663
--- /dev/null
@@ -0,0 +1,8 @@
+namespace Xamarin.Forms.Maps.GTK
+{
+    public class Location
+    {
+        public double Latitude { get; set; }
+        public double Longitude { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Xamarin.Forms.Maps.GTK/MapRenderer.cs b/Xamarin.Forms.Maps.GTK/MapRenderer.cs
new file mode 100644 (file)
index 0000000..237d542
--- /dev/null
@@ -0,0 +1,427 @@
+using GMap.NET;
+using GMap.NET.GTK;
+using GMap.NET.MapProviders;
+using Newtonsoft.Json;
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Timers;
+using System.Windows.Forms.Markers;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Platform.GTK;
+
+namespace Xamarin.Forms.Maps.GTK
+{
+    public class MapRenderer : ViewRenderer<Map, GMapControl>
+    {
+        private const string OverlayId = "overlayId";
+        private const int MinZoom = 0;
+        private const int MaxZoom = 24;
+
+        private GMapImageMarker _userPosition;
+        private bool _disposed;
+        private Timer _timer;
+
+        protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
+        {
+            if (e.OldElement != null)
+            {
+                var mapModel = e.OldElement;
+                MessagingCenter.Unsubscribe<Map, MapSpan>(this, "MapMoveToRegion");
+                ((System.Collections.ObjectModel.ObservableCollection<Pin>)mapModel.Pins).CollectionChanged -= OnCollectionChanged;
+            }
+
+            if (e.NewElement != null)
+            {
+                var mapModel = e.NewElement;
+
+                if (Control == null)
+                {
+                    var gMapControl = new GMapControl();
+                    GMapProviders.GoogleMap.ApiKey = FormsMaps.AuthenticationToken;
+                    gMapControl.MinZoom = MinZoom;
+                    gMapControl.MaxZoom = MaxZoom;
+                    gMapControl.SelectedAreaFillColor = System.Drawing.Color.Transparent;
+
+                    gMapControl.Overlays.Add(new GMapOverlay(OverlayId));
+
+                    SetNativeControl(gMapControl);
+
+                    Control.SizeAllocated += OnSizeAllocated;
+                    Control.OnPositionChanged += OnPositionChanged;
+                    Control.OnMapZoomChanged += OnMapZoomChanged;
+                    Control.ButtonPressEvent += OnButtonPressEvent;
+                    Control.OnMarkerClick += OnMarkerClick;
+                }
+
+                MessagingCenter.Subscribe<Maps.Map, MapSpan>(this, "MapMoveToRegion", (s, a) =>
+                MoveToRegion(a), mapModel);
+
+                UpdateMapType();
+                UpdateHasScrollEnabled();
+                UpdateHasZoomEnabled();
+
+                ((System.Collections.ObjectModel.ObservableCollection<Pin>)mapModel.Pins).CollectionChanged += OnCollectionChanged;
+
+                if (mapModel.Pins.Any())
+                    LoadPins();
+
+                if (Control == null)
+                    return;
+
+                MoveToRegion(mapModel.LastMoveToRegion);
+                UpdateIsShowingUser();
+            }
+
+            base.OnElementChanged(e);
+        }
+
+        private void OnSizeAllocated(object o, Gtk.SizeAllocatedArgs args)
+        {
+            UpdateVisibleRegion();
+        }
+
+        private void OnPositionChanged(PointLatLng point)
+        {
+            UpdateVisibleRegion();
+        }
+
+        private void OnMapZoomChanged()
+        {
+            UpdateVisibleRegion();
+        }
+
+        private void OnButtonPressEvent(object o, Gtk.ButtonPressEventArgs args)
+        {
+            Control.SelectionPen = new Pen(Brushes.Black, 2);
+        }
+
+        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            base.OnElementPropertyChanged(sender, e);
+
+            if (e.PropertyName == Maps.Map.MapTypeProperty.PropertyName)
+                UpdateMapType();
+            else if (e.PropertyName == Maps.Map.IsShowingUserProperty.PropertyName)
+                UpdateIsShowingUser();
+            else if (e.PropertyName == Maps.Map.HasScrollEnabledProperty.PropertyName)
+                UpdateHasScrollEnabled();
+            else if (e.PropertyName == Maps.Map.HasZoomEnabledProperty.PropertyName)
+                UpdateHasZoomEnabled();
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && !_disposed)
+            {
+                _disposed = true;
+
+                MessagingCenter.Unsubscribe<Maps.Map, MapSpan>(this, "MapMoveToRegion");
+
+                if (Control != null)
+                {
+                    Control.SizeAllocated -= OnSizeAllocated;
+                    Control.OnPositionChanged -= OnPositionChanged;
+                    Control.OnMapZoomChanged -= OnMapZoomChanged;
+                    Control.ButtonPressEvent -= OnButtonPressEvent;
+                    Control.OnMarkerClick -= OnMarkerClick;
+                }
+
+                if (Element != null)
+                    ((System.Collections.ObjectModel.ObservableCollection<Pin>)Element.Pins).CollectionChanged -= OnCollectionChanged;
+            }
+
+            base.Dispose(disposing);
+        }
+
+        private void OnCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+        {
+            switch (e.Action)
+            {
+                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
+                    foreach (Pin pin in e.NewItems)
+                        LoadPin(pin);
+                    break;
+                case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
+                    // Do nothing
+                    break;
+                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
+                    foreach (Pin pin in e.OldItems)
+                        RemovePin(pin);
+                    break;
+                case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
+                    foreach (Pin pin in e.OldItems)
+                        RemovePin(pin);
+                    foreach (Pin pin in e.NewItems)
+                        LoadPin(pin);
+                    break;
+                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
+                    ClearPins();
+                    break;
+            }
+        }
+
+        private void LoadPins()
+        {
+            foreach (var pin in Element.Pins)
+                LoadPin(pin);
+        }
+
+        private void LoadPin(Pin pin)
+        {
+            var overlay = Control.Overlays.FirstOrDefault();
+
+            if (overlay != null)
+            {
+                var gMapImageMarker = new GMapImageMarker(
+                    new PointLatLng(
+                        pin.Position.Latitude,
+                        pin.Position.Longitude),
+                    GMapImageMarkerType.RedDot);
+
+                overlay.Markers.Add(gMapImageMarker);
+            }
+        }
+
+        private void RemovePin(Pin pinToRemove)
+        {
+            var overlay = Control.Overlays.FirstOrDefault();
+
+            if (overlay != null)
+            {
+                var positionToRemove = new PointLatLng(
+                        pinToRemove.Position.Latitude,
+                        pinToRemove.Position.Longitude);
+
+                var pins = overlay.Markers.Where(p => p.Position == positionToRemove);
+
+                foreach (var pin in pins)
+                {
+                    overlay.Markers.Remove(pin);
+                }
+            }
+        }
+
+        private void ClearPins()
+        {
+            var overlay = Control.Overlays.FirstOrDefault();
+
+            if (overlay != null)
+            {
+                overlay.Markers.Clear();
+            }
+
+            UpdateIsShowingUser();
+        }
+
+        private void UpdateMapType()
+        {
+            switch (Element.MapType)
+            {
+                case MapType.Street:
+                    Control.MapProvider = GMapProviders.GoogleMap;
+                    break;
+                case MapType.Satellite:
+                    Control.MapProvider = GMapProviders.GoogleSatelliteMap;
+                    break;
+                case MapType.Hybrid:
+                    Control.MapProvider = GMapProviders.GoogleHybridMap;
+                    break;
+            }
+        }
+
+        private void UpdateIsShowingUser(bool moveToLocation = true)
+        {
+            if (Control == null || Element == null)
+                return;
+
+            var overlay = Control.Overlays.FirstOrDefault();
+
+            if (Element.IsShowingUser)
+            {
+                var userPosition = GetUserPosition();
+
+                if (userPosition != null)
+                {
+                    LoadUserPosition(userPosition.Value, moveToLocation);
+                }
+
+                if (Control == null || Element == null) return;
+
+                if (_timer == null)
+                {
+                    _timer = new Timer();
+                    _timer.Elapsed += (s, o) => UpdateIsShowingUser();
+                    _timer.Interval = 1000;
+                }
+
+                if (!_timer.Enabled)
+                    _timer.Start();
+            }
+            else if (_userPosition != null && overlay.Markers.Contains(_userPosition))
+            {
+                _timer.Stop();
+                overlay.Markers.Remove(_userPosition);
+            }
+        }
+
+        private void LoadUserPosition(PointLatLng userCoordinate, bool center)
+        {
+            if (Control == null || Element == null) return;
+
+            if (_userPosition == null)
+            {
+                _userPosition = new GMapImageMarker(userCoordinate, GMapImageMarkerType.Red);
+            }
+
+            var overlay = Control.Overlays.FirstOrDefault();
+
+            if (overlay != null)
+            {
+                overlay.Markers.Add(_userPosition);
+            }
+
+            if (center)
+            {
+                Control.Position = userCoordinate;
+            }
+        }
+
+        private PointLatLng? GetUserPosition()
+        {
+            try
+            {
+                var ipAddress = GetPublicIpAddress();
+                var webClient = new WebClient();
+                var uri = new Uri(string.Format("http://freegeoip.net/json/{0}", ipAddress.ToString()));
+                var result = webClient.DownloadString(uri);
+                var location = JsonConvert.DeserializeObject<Location>(result);
+
+                return new PointLatLng(
+                    location.Latitude,
+                    location.Longitude);
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        private string GetPublicIpAddress()
+        {
+            string uri = "http://checkip.dyndns.org/";
+            string ip = string.Empty;
+
+            using (var client = new HttpClient())
+            {
+                var result = client.GetAsync(uri).Result.Content.ReadAsStringAsync().Result;
+
+                ip = result.Split(':')[1].Split('<')[0];
+                ip = ip.Trim();
+            }
+
+            return ip;
+        }
+
+        private void UpdateHasScrollEnabled()
+        {
+            var hasScrollEnabled = Element.HasScrollEnabled;
+
+            Control.CanDragMap = hasScrollEnabled;
+        }
+
+        private void UpdateHasZoomEnabled()
+        {
+            var hasZoomEnabled = Element.HasZoomEnabled;
+
+            Control.MouseWheelZoomEnabled = hasZoomEnabled;
+        }
+
+        private void MoveToRegion(MapSpan span)
+        {
+            try
+            {
+                if (span == null)
+                {
+                    return;
+                }
+
+                var p1 = new PointLatLng
+                {
+                    Lat = span.Center.Latitude + span.LatitudeDegrees / 2,
+                    Lng = span.Center.Longitude - span.LongitudeDegrees / 2
+                };
+
+                var p2 = new PointLatLng
+                {
+                    Lat = span.Center.Latitude - span.LatitudeDegrees / 2,
+                    Lng = span.Center.Longitude + span.LongitudeDegrees / 2
+                };
+
+                double x1 = Math.Min(p1.Lng, p2.Lng);
+                double y1 = Math.Max(p1.Lat, p2.Lat);
+                double x2 = Math.Max(p1.Lng, p2.Lng);
+                double y2 = Math.Min(p1.Lat, p2.Lat);
+
+                var region = new RectLatLng(y1, x1, x2 - x1, y1 - y2);
+
+                Control.SelectionPen = new Pen(Brushes.Transparent, 2);
+                Control.SelectedArea = region;
+                Control.SetZoomToFitRect(region);
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine("MoveToRegion exception: " + ex);
+                Log.Warning("Xamarin.Forms MapRenderer", $"MoveToRegion exception: {ex}");
+            }
+        }
+
+        private void UpdateVisibleRegion()
+        {
+            if (Control == null || Element == null)
+                return;
+
+            try
+            {
+                var region = Control.SelectedArea;
+                var topLeft = region.LocationTopLeft;
+                var center = region.LocationMiddle;
+                var rightBottom = region.LocationRightBottom;
+
+                var latitudeDelta = Math.Abs(topLeft.Lat - rightBottom.Lat);
+                var longitudeDelta = Math.Abs(topLeft.Lng - rightBottom.Lng);
+
+                               Element.SetVisibleRegion(new MapSpan(
+                                       new Position(center.Lat, center.Lng),
+                                       latitudeDelta,
+                                       longitudeDelta));
+            }
+            catch (Exception ex)
+            {
+                Debug.WriteLine("UpdateVisibleRegion exception: " + ex);
+                Log.Warning("Xamarin.Forms MapRenderer", $"UpdateVisibleRegion exception: {ex}");
+
+                return;
+            }
+        }
+
+        private void OnMarkerClick(GMap.NET.GTK.Markers.GMapMarker item)
+        {
+            var marker = item;
+
+            foreach (var pin in Element.Pins)
+            {
+                if(pin.Position.Latitude == marker.Position.Lat &&
+                    pin.Position.Longitude == marker.Position.Lng)
+                {
+                    pin.SendTap();
+                    break;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Xamarin.Forms.Maps.GTK/Properties/AssemblyInfo.cs b/Xamarin.Forms.Maps.GTK/Properties/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..4d98393
--- /dev/null
@@ -0,0 +1,19 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Xamarin.Forms;
+using Xamarin.Forms.Maps.GTK;
+
+[assembly: AssemblyTitle("Xamarin.Forms.Maps.GTK")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Xamarin Inc.")]
+[assembly: AssemblyProduct("Xamarin.Forms.Maps.GTK")]
+[assembly: AssemblyCopyright("Copyright © Xamarin Inc. 2017")]
+[assembly: AssemblyTrademark("Xamarin Inc.")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("a9772bb1-0e17-42f5-a6db-60bfccbfdb9d")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: ExportRenderer(typeof(Xamarin.Forms.Maps.Map), typeof(MapRenderer))]
\ No newline at end of file
diff --git a/Xamarin.Forms.Maps.GTK/Xamarin.Forms.Maps.GTK.csproj b/Xamarin.Forms.Maps.GTK/Xamarin.Forms.Maps.GTK.csproj
new file mode 100644 (file)
index 0000000..4fb8457
--- /dev/null
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Xamarin.Forms.Maps.GTK</RootNamespace>
+    <AssemblyName>Xamarin.Forms.Maps.GTK</AssemblyName>
+    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\gtk-sharp\gtk-sharp-2.0\atk-sharp.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\gtk-sharp\gtk-sharp-2.0\gdk-sharp.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\gtk-sharp\gtk-sharp-2.0\glade-sharp.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\gtk-sharp\gtk-sharp-2.0\glib-sharp.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="GMap.NET.Core, Version=1.7.0.0, Culture=neutral, PublicKeyToken=b85b9027b614afef, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\GMaps\GMap.NET.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="GMap.NET.GTK, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\GMaps\GMap.NET.GTK.dll</HintPath>
+    </Reference>
+    <Reference Include="gtk-dotnet, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\gtk-sharp\gtk-sharp-2.0\gtk-dotnet.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\gtk-sharp\gtk-sharp-2.0\gtk-sharp.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Xamarin.Forms.Platform.GTK\Libs\gtk-sharp\gtk-sharp-2.0\pango-sharp.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="FormsMaps.cs" />
+    <Compile Include="GeocoderBackend.cs" />
+    <Compile Include="Location.cs" />
+    <Compile Include="MapRenderer.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Xamarin.Forms.Core\Xamarin.Forms.Core.csproj">
+      <Project>{57b8b73d-c3b5-4c42-869e-7b2f17d354ac}</Project>
+      <Name>Xamarin.Forms.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Xamarin.Forms.Maps\Xamarin.Forms.Maps.csproj">
+      <Project>{7d13bac2-c6a4-416a-b07e-c169b199e52b}</Project>
+      <Name>Xamarin.Forms.Maps</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Xamarin.Forms.Platform.GTK\Xamarin.Forms.Platform.GTK.csproj">
+      <Project>{1f058504-62f9-4279-ac8f-16738e0f4417}</Project>
+      <Name>Xamarin.Forms.Platform.GTK</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Xamarin.Forms.Maps.GTK/app.config b/Xamarin.Forms.Maps.GTK/app.config
new file mode 100644 (file)
index 0000000..4777f37
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="Mono.Cairo" publicKeyToken="0738eb9f132ed756" culture="neutral"/>
+        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="OpenTK" publicKeyToken="bad199fe84eb3df4" culture="neutral"/>
+        <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/></startup></configuration>
diff --git a/Xamarin.Forms.Maps.GTK/packages.config b/Xamarin.Forms.Maps.GTK/packages.config
new file mode 100644 (file)
index 0000000..c809207
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
+</packages>
\ No newline at end of file
diff --git a/Xamarin.Forms.Platform.GTK/Libs/GMaps/GMap.NET.Core.dll b/Xamarin.Forms.Platform.GTK/Libs/GMaps/GMap.NET.Core.dll
new file mode 100644 (file)
index 0000000..92ae33f
Binary files /dev/null and b/Xamarin.Forms.Platform.GTK/Libs/GMaps/GMap.NET.Core.dll differ
diff --git a/Xamarin.Forms.Platform.GTK/Libs/GMaps/GMap.NET.GTK.dll b/Xamarin.Forms.Platform.GTK/Libs/GMaps/GMap.NET.GTK.dll
new file mode 100644 (file)
index 0000000..54eaf2e
Binary files /dev/null and b/Xamarin.Forms.Platform.GTK/Libs/GMaps/GMap.NET.GTK.dll differ
index f1c0403..5da9ca9 100644 (file)
   </ItemGroup>
   <ItemGroup>
     <None Include="app.config" />
+    <Content Include="Libs\GMaps\GMap.NET.Core.dll" />
+    <Content Include="Libs\GMaps\GMap.NET.GTK.dll" />
     <Content Include="Libs\gtk-sharp\gtk-sharp-2.0\atk-sharp.dll" />
     <Content Include="Libs\gtk-sharp\gtk-sharp-2.0\atk-sharp.pdb" />
     <Content Include="Libs\gtk-sharp\gtk-sharp-2.0\gdk-sharp.dll" />
index cbfaebd..6491bf2 100644 (file)
@@ -139,6 +139,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Forms.Platform.Tize
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.ControlGallery.GTK", "Xamarin.Forms.ControlGallery.GTK\Xamarin.Forms.ControlGallery.GTK.csproj", "{03A51E5B-0A1E-41F0-AAE3-4B19406F7340}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Maps.GTK", "Xamarin.Forms.Maps.GTK\Xamarin.Forms.Maps.GTK.csproj", "{A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}"
+EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Forms.Build.Tasks.Core", "Xamarin.Forms.Build.Tasks.Core\Xamarin.Forms.Build.Tasks.Core.csproj", "{367E2986-AA27-4FA6-AF3C-CAF98C99A839}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Forms.Platform.WPF", "Xamarin.Forms.Platform.WPF\Xamarin.Forms.Platform.WPF.csproj", "{140BC260-8B15-4D3A-B1B0-DDD8072918CC}"
@@ -2526,6 +2528,62 @@ Global
                {03A51E5B-0A1E-41F0-AAE3-4B19406F7340}.Release|x64.Build.0 = Release|Any CPU
                {03A51E5B-0A1E-41F0-AAE3-4B19406F7340}.Release|x86.ActiveCfg = Release|Any CPU
                {03A51E5B-0A1E-41F0-AAE3-4B19406F7340}.Release|x86.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|Templates.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|Templates.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|x64.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|Any CPU.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|ARM.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|ARM.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|iPhone.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|Templates.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|Templates.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|x64.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|x64.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|x86.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.AppStore|x86.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|ARM.ActiveCfg = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|ARM.Build.0 = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|iPhone.Build.0 = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|Templates.ActiveCfg = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|Templates.Build.0 = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|x64.ActiveCfg = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|x64.Build.0 = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Debug|x86.Build.0 = Debug|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|Any CPU.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|ARM.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|ARM.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|iPhone.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|iPhone.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|Templates.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|Templates.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|x64.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|x64.Build.0 = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|x86.ActiveCfg = Release|Any CPU
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D}.Release|x86.Build.0 = Release|Any CPU
                {367E2986-AA27-4FA6-AF3C-CAF98C99A839}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
                {367E2986-AA27-4FA6-AF3C-CAF98C99A839}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
                {367E2986-AA27-4FA6-AF3C-CAF98C99A839}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
@@ -2794,6 +2852,7 @@ Global
                {699C79F6-1D91-4DBF-B817-E8CFFD6263BB} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
                {83790029-272E-45AF-A41D-E7716684E5B8} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
                {03A51E5B-0A1E-41F0-AAE3-4B19406F7340} = {4F5E2D21-17F6-4A42-B8FB-D03D82E24EC8}
+               {A9772BB1-0E17-42F5-A6DB-60BFCCBFDB9D} = {132FB9A4-613F-44CE-95D5-758D32D231DD}
                {367E2986-AA27-4FA6-AF3C-CAF98C99A839} = {32F608E2-6406-4DCF-9105-E2A7CB7085CF}
                {140BC260-8B15-4D3A-B1B0-DDD8072918CC} = {29AC50BF-B4FB-450B-9386-0C5AD4B84226}
                {89B0DB73-A32E-447C-9390-A2A59D89B2E4} = {132FB9A4-613F-44CE-95D5-758D32D231DD}