From 1ba49dd2619fa68e7001a50d7ff1572076c51fbd Mon Sep 17 00:00:00 2001 From: Jurgen De Leon Date: Sat, 4 Jun 2022 09:53:31 -0500 Subject: [PATCH 1/2] GMap.NET.GtkSharp --- GMap.NET.sln | 11 + GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj | 2 +- GMap.NET/GMap.NET.Core/Internals/Core.cs | 11 +- .../GMap.NET.Core/Properties/AssemblyInfo.cs | 16 +- GMap.NET/GMap.NET.Core/StatusCodes.cs | 1 + GMap.NET/GMap.NET.GtkSharp/Class1.cs | 7 + .../GMap.NET.GtkSharp.csproj | 28 + .../GMap.NET.GtkSharp/ColorMatrixs.cs | 28 + .../GMap.NET.GtkSharp/GMapControl.cs | 2906 +++++++++++++++++ .../GMap.NET.GtkSharp/GMapImage.cs | 146 + .../GMap.NET.GtkSharp/GMapMarker.cs | 336 ++ .../GMap.NET.GtkSharp/GMapOverlay.cs | 462 +++ .../GMap.NET.GtkSharp/GMapPolygon.cs | 309 ++ .../GMap.NET.GtkSharp/GMapRoute.cs | 261 ++ .../GMap.NET.GtkSharp/GMapToolTip.cs | 177 + .../GMap.NET.GtkSharp/Markers/GMarkerCross.cs | 69 + .../Markers/GMarkerGoogle.cs | 272 ++ .../TilePrefetcher.Designer.cs | 124 + .../GMap.NET.GtkSharp/TilePrefetcher.cs | 327 ++ .../GMap.NET.GtkSharp/TilePrefetcher.resx | 120 + .../ToolTips/GMapBaloonToolTip.cs | 87 + .../ToolTips/GMapRoundedToolTip.cs | 85 + .../ObservableCollection.cs | 541 +++ .../ObservableCollectionThreadSafe.cs | 62 + .../Properties/AssemblyInfo.cs | 19 + .../Properties/Resources.Designer.cs | 357 ++ .../Properties/Resources.resx | 248 ++ .../GMap.NET.GtkSharp/Resources/arrow.png | Bin 0 -> 1015 bytes .../Resources/arrowshadow.png | Bin 0 -> 670 bytes .../Resources/black_small.png | Bin 0 -> 305 bytes .../GMap.NET.GtkSharp/Resources/blue-dot.png | Bin 0 -> 1340 bytes .../Resources/blue-pushpin.png | Bin 0 -> 1408 bytes GMap.NET/GMap.NET.GtkSharp/Resources/blue.png | Bin 0 -> 1309 bytes .../Resources/blue_small.png | Bin 0 -> 558 bytes .../Resources/brown_small.png | Bin 0 -> 598 bytes .../Resources/drag_cross_67_16.png | Bin 0 -> 246 bytes .../Resources/go-big-green.png | Bin 0 -> 3350 bytes .../Resources/gray_small.png | Bin 0 -> 567 bytes .../GMap.NET.GtkSharp/Resources/green-dot.png | Bin 0 -> 1221 bytes .../GMap.NET.GtkSharp/Resources/green.png | Bin 0 -> 1190 bytes .../Resources/green_small.png | Bin 0 -> 586 bytes .../Resources/grn-pushpin.png | Bin 0 -> 1237 bytes .../GMap.NET.GtkSharp/Resources/lightblue.png | Bin 0 -> 1269 bytes .../Resources/ltblu-pushpin.png | Bin 0 -> 1369 bytes .../Resources/ltblue-dot.png | Bin 0 -> 1301 bytes .../Resources/msmarker.shadow.png | Bin 0 -> 483 bytes .../Resources/orange-dot.png | Bin 0 -> 3443 bytes .../GMap.NET.GtkSharp/Resources/orange.png | Bin 0 -> 3413 bytes .../Resources/orange_small.png | Bin 0 -> 542 bytes .../Resources/pause-big-red.png | Bin 0 -> 2955 bytes .../GMap.NET.GtkSharp/Resources/pink-dot.png | Bin 0 -> 1349 bytes .../Resources/pink-pushpin.png | Bin 0 -> 1424 bytes GMap.NET/GMap.NET.GtkSharp/Resources/pink.png | Bin 0 -> 1321 bytes .../Resources/purple-dot.png | Bin 0 -> 1356 bytes .../Resources/purple-pushpin.png | Bin 0 -> 1418 bytes .../GMap.NET.GtkSharp/Resources/purple.png | Bin 0 -> 1324 bytes .../Resources/purple_small.png | Bin 0 -> 572 bytes .../Resources/pushpin_shadow.png | Bin 0 -> 713 bytes .../GMap.NET.GtkSharp/Resources/red-dot.png | Bin 0 -> 1337 bytes .../Resources/red-pushpin.png | Bin 0 -> 1334 bytes GMap.NET/GMap.NET.GtkSharp/Resources/red.png | Bin 0 -> 1305 bytes .../GMap.NET.GtkSharp/Resources/red_small.png | Bin 0 -> 562 bytes .../Resources/shadow_small.png | Bin 0 -> 436 bytes .../Resources/stop-big-red.png | Bin 0 -> 3150 bytes .../Resources/white_small.png | Bin 0 -> 473 bytes .../Resources/yellow-dot.png | Bin 0 -> 1341 bytes .../GMap.NET.GtkSharp/Resources/yellow.png | Bin 0 -> 1309 bytes .../Resources/yellow_small.png | Bin 0 -> 561 bytes .../Resources/ylw-pushpin.png | Bin 0 -> 1233 bytes GMap.NET/GMap.NET.GtkSharp/sn.snk | Bin 0 -> 596 bytes 70 files changed, 6998 insertions(+), 14 deletions(-) create mode 100644 GMap.NET/GMap.NET.GtkSharp/Class1.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp.csproj create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ColorMatrixs.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapControl.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapImage.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapMarker.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapOverlay.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapPolygon.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapRoute.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapToolTip.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/Markers/GMarkerCross.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/Markers/GMarkerGoogle.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.Designer.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.resx create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ToolTips/GMapBaloonToolTip.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ToolTips/GMapRoundedToolTip.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.ObjectModel/ObservableCollection.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/GMap.NET.ObjectModel/ObservableCollectionThreadSafe.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/Properties/AssemblyInfo.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/Properties/Resources.Designer.cs create mode 100644 GMap.NET/GMap.NET.GtkSharp/Properties/Resources.resx create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/arrow.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/arrowshadow.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/black_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/blue-dot.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/blue-pushpin.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/blue.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/blue_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/brown_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/drag_cross_67_16.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/go-big-green.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/gray_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/green-dot.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/green.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/green_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/grn-pushpin.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/lightblue.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/ltblu-pushpin.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/ltblue-dot.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/msmarker.shadow.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/orange-dot.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/orange.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/orange_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/pause-big-red.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/pink-dot.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/pink-pushpin.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/pink.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/purple-dot.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/purple-pushpin.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/purple.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/purple_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/pushpin_shadow.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/red-dot.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/red-pushpin.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/red.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/red_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/shadow_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/stop-big-red.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/white_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/yellow-dot.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/yellow.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/yellow_small.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/Resources/ylw-pushpin.png create mode 100644 GMap.NET/GMap.NET.GtkSharp/sn.snk diff --git a/GMap.NET.sln b/GMap.NET.sln index 577d9173..8daad47f 100644 --- a/GMap.NET.sln +++ b/GMap.NET.sln @@ -63,6 +63,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GMap.NET.WindowsForms.Utils EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.Testing", "Testing\Demo.Testing\Demo.Testing.csproj", "{CE9F0FDA-1271-4E69-9369-2634688E2FC0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GMap.NET.GtkSharp", "GMap.NET\GMap.NET.GtkSharp\GMap.NET.GtkSharp.csproj", "{DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -246,6 +248,14 @@ Global {CE9F0FDA-1271-4E69-9369-2634688E2FC0}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU {CE9F0FDA-1271-4E69-9369-2634688E2FC0}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU {CE9F0FDA-1271-4E69-9369-2634688E2FC0}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.Release|Any CPU.Build.0 = Release|Any CPU + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -273,6 +283,7 @@ Global {DD9FFD4C-32F9-4BE5-9060-9C2BFCD414EF} = {F4684AC2-C6A5-4DA4-977B-2ADD40EBE955} {839D3F3C-D762-44D8-A3C7-50B3105C61C2} = {E797B22B-142C-4068-8F18-9E7E2C7B422C} {CE9F0FDA-1271-4E69-9369-2634688E2FC0} = {CEB4956F-6094-4268-972D-D46CF6792A84} + {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0} = {E797B22B-142C-4068-8F18-9E7E2C7B422C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {121217E7-9EA2-4663-8B5C-E6E1F37A5CA9} diff --git a/GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj b/GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj index 1b608e67..f0bfbed4 100644 --- a/GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj +++ b/GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj @@ -5,7 +5,7 @@ GMap.NET.Core GMap.NET.Core GMap.NET - net46;net47;net48;netstandard2.0;netcoreapp3.1;net5.0;net6.0 + net46;net47;net48;netstandard2.0;netcoreapp3.1;net5.0;net6.0 MONO_disabled;SQLite;MySQL_disabled;PostgreSQL_disabled;$(DefineConstants) diff --git a/GMap.NET/GMap.NET.Core/Internals/Core.cs b/GMap.NET/GMap.NET.Core/Internals/Core.cs index 76317d77..5d2c4f9b 100644 --- a/GMap.NET/GMap.NET.Core/Internals/Core.cs +++ b/GMap.NET/GMap.NET.Core/Internals/Core.cs @@ -795,11 +795,11 @@ public void CancelAsyncTasks() volatile int _skipOverZoom; #if NET46 - static readonly BlockingCollection TileLoadQueue4 = + internal static readonly BlockingCollection TileLoadQueue4 = new BlockingCollection(new ConcurrentStack()); static List _tileLoadQueue4Tasks; - static int _loadWaitCount; + internal static int _loadWaitCount; void AddLoadTask(LoadTask t) { if (_tileLoadQueue4Tasks == null) @@ -846,8 +846,13 @@ void AddLoadTask(LoadTask t) TileLoadQueue4.Add(t); } + + public bool IsWaitTileLoad + { + get { return TileLoadQueue4.Count > 0 || _loadWaitCount < GThreadPoolSize; } + } #else - byte _loadWaitCount = 0; + internal byte _loadWaitCount = 0; void TileLoadThread() { diff --git a/GMap.NET/GMap.NET.Core/Properties/AssemblyInfo.cs b/GMap.NET/GMap.NET.Core/Properties/AssemblyInfo.cs index 4d668a35..f76ad5d3 100644 --- a/GMap.NET/GMap.NET.Core/Properties/AssemblyInfo.cs +++ b/GMap.NET/GMap.NET.Core/Properties/AssemblyInfo.cs @@ -3,15 +3,11 @@ // internal visibility [assembly: #if DEBUG - InternalsVisibleTo( - "ConsoleApplication, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), + InternalsVisibleTo("ConsoleApplication, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), #endif - InternalsVisibleTo( - "GMap.NET.WindowsForms, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), - InternalsVisibleTo( - "GMap.NET.WindowsMobile, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), - InternalsVisibleTo( - "GMap.NET.WindowsPresentation, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), - InternalsVisibleTo( - "GMap.NET.Avalonia, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce") + InternalsVisibleTo("GMap.NET.WindowsForms, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), + InternalsVisibleTo("GMap.NET.WindowsMobile, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), + InternalsVisibleTo("GMap.NET.WindowsPresentation, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), + InternalsVisibleTo("GMap.NET.Avalonia, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce"), + InternalsVisibleTo("GMap.NET.GtkSharp, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cd251b0b8f7079914bbe3e5655d92e5427218f3f0241537a9cb7467b6da2aa5cb20915c31400800e3081d20e6454a35164600fe8bf4f846744f211e040588260cc872c78abd91b422c60071bfda5f11d251eb09f0935944b41de2a28374ad17e8c963d642310df9050e8ae0f1a2b867bcc8f035e4b353dc699cfc7125b9661ce") ] diff --git a/GMap.NET/GMap.NET.Core/StatusCodes.cs b/GMap.NET/GMap.NET.Core/StatusCodes.cs index 7e463ade..047775bc 100644 --- a/GMap.NET/GMap.NET.Core/StatusCodes.cs +++ b/GMap.NET/GMap.NET.Core/StatusCodes.cs @@ -13,6 +13,7 @@ public enum GeoCoderStatusCode : int INVALID_REQUEST, ERROR, EXCEPTION_IN_CODE, + G_GEO_SUCCESS } /// diff --git a/GMap.NET/GMap.NET.GtkSharp/Class1.cs b/GMap.NET/GMap.NET.GtkSharp/Class1.cs new file mode 100644 index 00000000..26404d0c --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/Class1.cs @@ -0,0 +1,7 @@ +namespace GMap.NET.GtkSharp +{ + public class Class1 + { + + } +} \ No newline at end of file diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp.csproj b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp.csproj new file mode 100644 index 00000000..ccea51f9 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp.csproj @@ -0,0 +1,28 @@ + + + + GMap.NET.GtkSharp + GMap.NET.GtkSharp + GMap.NET.GtkSharp + GMap.NET + enable + latest + net46;net47;net48; + true + +- GtkSharp +History Release Notes +https://github.com/judero01col/GMap.NET/blob/master/README.md#release-notes + + + + + + + + + + + + + diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ColorMatrixs.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ColorMatrixs.cs new file mode 100644 index 00000000..2262c1ea --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ColorMatrixs.cs @@ -0,0 +1,28 @@ + +namespace GMap.NET.GtkSharp +{ + using System.Drawing.Imaging; + + public static class ColorMatrixs + { +#if !PocketPC + public static readonly ColorMatrix GrayScale = new ColorMatrix(new float[][] + { + new float[] {.3f, .3f, .3f, 0, 0}, + new float[] {.59f, .59f, .59f, 0, 0}, + new float[] {.11f, .11f, .11f, 0, 0}, + new float[] {0, 0, 0, 1, 0}, + new float[] {0, 0, 0, 0, 1} + }); + + public static readonly ColorMatrix Negative = new ColorMatrix(new float[][] + { + new float[] {-1, 0, 0, 0, 0}, + new float[] {0, -1, 0, 0, 0}, + new float[] {0, 0, -1, 0, 0}, + new float[] {0, 0, 0, 1, 0}, + new float[] {1, 1, 1, 0, 1} + }); +#endif + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapControl.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapControl.cs new file mode 100644 index 00000000..40cc0be7 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapControl.cs @@ -0,0 +1,2906 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Drawing.Text; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Threading; +using GMap.NET; +using GMap.NET.Internals; +using GMap.NET.MapProviders; +using GMap.NET.ObjectModel; +using GMap.NET.Projections; + +namespace GMap.NET.GtkSharp +{ + + + /// + /// GMap.NET control for Windows Forms + /// + [System.ComponentModel.ToolboxItem (true)] + public partial class GMapControl : Gtk.DrawingArea, Interface + { + /// + /// occurs when clicked on marker + /// + //public event MarkerClick OnMarkerClick; + + /// + /// occurs when clicked on polygon + /// + //public event PolygonClick OnPolygonClick; + + /// + /// occurs when clicked on route + /// + //public event RouteClick OnRouteClick; + + /// + /// occurs on mouse enters route area + /// + public event RouteEnter OnRouteEnter; + + /// + /// occurs on mouse leaves route area + /// + public event RouteLeave OnRouteLeave; + + /// + /// occurs when mouse selection is changed + /// + public event SelectionChange OnSelectionChange; + + /// + /// occurs on mouse enters marker area + /// + public event MarkerEnter OnMarkerEnter; + + /// + /// occurs on mouse leaves marker area + /// + public event MarkerLeave OnMarkerLeave; + + /// + /// occurs on mouse enters Polygon area + /// + public event PolygonEnter OnPolygonEnter; + + /// + /// occurs on mouse leaves Polygon area + /// + public event PolygonLeave OnPolygonLeave; + + /// + /// list of overlays, should be thread safe + /// + public readonly ObservableCollectionThreadSafe Overlays = new ObservableCollectionThreadSafe(); + + /// + /// max zoom + /// + [Category("GMap.NET")] + [Description("maximum zoom level of map")] + public int MaxZoom + { + get + { + return Core.MaxZoom; + } + set + { + Core.MaxZoom = value; + } + } + + /// + /// min zoom + /// + [Category("GMap.NET")] + [Description("minimum zoom level of map")] + public int MinZoom + { + get + { + return Core.MinZoom; + } + set + { + Core.MinZoom = value; + } + } + + /// + /// map zooming type for mouse wheel + /// + [Category("GMap.NET")] + [Description("map zooming type for mouse wheel")] + public MouseWheelZoomType MouseWheelZoomType + { + get + { + return Core.MouseWheelZoomType; + } + set + { + Core.MouseWheelZoomType = value; + } + } + + /// + /// enable map zoom on mouse wheel + /// + [Category("GMap.NET")] + [Description("enable map zoom on mouse wheel")] + public bool MouseWheelZoomEnabled + { + get + { + return Core.MouseWheelZoomEnabled; + } + set + { + Core.MouseWheelZoomEnabled = value; + } + } + + /// + /// text on empty tiles + /// + public string EmptyTileText = "We are sorry, but we don't\nhave imagery at this zoom\nlevel for this region."; + + /// + /// pen for empty tile borders + /// + public Pen EmptyTileBorders = new Pen(Brushes.White, 1); + + public bool ShowCenter = true; + + /// + /// pen for scale info + /// + public Pen ScalePen = new Pen(Brushes.Blue, 1); + public Pen CenterPen = new Pen(Brushes.Red, 1); + + /// + /// area selection pen + /// + public Pen SelectionPen = new Pen(Brushes.Blue, 2); + + Brush SelectedAreaFill = new SolidBrush(Color.FromArgb(33, Color.RoyalBlue)); + Color selectedAreaFillColor = Color.FromArgb(33, Color.RoyalBlue); + + /// + /// background of selected area + /// + [Category("GMap.NET")] + [Description("background color od the selected area")] + public Color SelectedAreaFillColor + { + get + { + return selectedAreaFillColor; + } + set + { + if (selectedAreaFillColor != value) + { + selectedAreaFillColor = value; + + if (SelectedAreaFill != null) + { + SelectedAreaFill.Dispose(); + SelectedAreaFill = null; + } + SelectedAreaFill = new SolidBrush(selectedAreaFillColor); + } + } + } + + HelperLineOptions helperLineOption = HelperLineOptions.DontShow; + + /// + /// draw lines at the mouse pointer position + /// + [Browsable(false)] + public HelperLineOptions HelperLineOption + { + get + { + return helperLineOption; + } + set + { + helperLineOption = value; + renderHelperLine = (helperLineOption == HelperLineOptions.ShowAlways); + if (Core.IsStarted) + { + Invalidate(); + } + } + } + + public Pen HelperLinePen = new Pen(Color.Blue, 1); + bool renderHelperLine = false; + + protected override bool OnKeyPressEvent(Gdk.EventKey e) + { + if (HelperLineOption == HelperLineOptions.ShowOnModifierKey) + { + renderHelperLine = (e.State.HasFlag(Gdk.ModifierType.ShiftMask) || e.State.HasFlag(Gdk.ModifierType.Mod1Mask)); // Mod1Mask == Altkey + if (renderHelperLine) + { + Invalidate(); + } + } + + return base.OnKeyPressEvent(e); + } + + protected override bool OnKeyReleaseEvent(Gdk.EventKey e) + { + if (HelperLineOption == HelperLineOptions.ShowOnModifierKey) + { + renderHelperLine = (e.State.HasFlag(Gdk.ModifierType.ShiftMask) || e.State.HasFlag(Gdk.ModifierType.Mod1Mask)); // Mod1Mask == Altkey + if (!renderHelperLine) + { + Invalidate(); + } + } + return base.OnKeyReleaseEvent(e); + } + + Brush EmptytileBrush = new SolidBrush(Color.Navy); + Color emptyTileColor = Color.Navy; + + /// + /// color of empty tile background + /// + [Category("GMap.NET")] + [Description("background color of the empty tile")] + public Color EmptyTileColor + { + get + { + return emptyTileColor; + } + set + { + if (emptyTileColor != value) + { + emptyTileColor = value; + + if (EmptytileBrush != null) + { + EmptytileBrush.Dispose(); + EmptytileBrush = null; + } + EmptytileBrush = new SolidBrush(emptyTileColor); + } + } + } + + /// + /// show map scale info + /// + public bool MapScaleInfoEnabled = false; + + /// + /// enables filling empty tiles using lower level images + /// + public bool FillEmptyTiles = true; + + /// + /// if true, selects area just by holding mouse and moving + /// + public bool DisableAltForSelection = false; + + /// + /// retry count to get tile + /// + [Browsable(false)] + public int RetryLoadTile + { + get + { + return Core.RetryLoadTile; + } + set + { + Core.RetryLoadTile = value; + } + } + + /// + /// how many levels of tiles are staying decompresed in memory + /// + [Browsable(false)] + public int LevelsKeepInMemmory + { + get + { + return Core.LevelsKeepInMemory; + } + + set + { + Core.LevelsKeepInMemory = value; + } + } + + /// + /// map dragg button + /// + [Category("GMap.NET")] + public uint DragButton = 3; //Right button + + private bool showTileGridLines = false; + + /// + /// shows tile gridlines + /// + [Category("GMap.NET")] + [Description("shows tile gridlines")] + public bool ShowTileGridLines + { + get + { + return showTileGridLines; + } + set + { + showTileGridLines = value; + Invalidate(); + } + } + + /// + /// current selected area in map + /// + private RectLatLng selectedArea; + + [Browsable(false)] + public RectLatLng SelectedArea + { + get + { + return selectedArea; + } + set + { + selectedArea = value; + + if (Core.IsStarted) + { + Invalidate(); + } + } + } + + /// + /// map boundaries + /// + public RectLatLng? BoundsOfMap = null; + + /// + /// enables integrated DoubleBuffer for running on windows mobile + /// + //FIXME Убрать полностью мобильную версию. + public bool ForceDoubleBuffer = false; + readonly bool MobileMode = false; + + /// + /// stops immediate marker/route/polygon invalidations; + /// call Refresh to perform single refresh and reset invalidation state + /// + public bool HoldInvalidation = false; + + /// + /// call this to stop HoldInvalidation and perform single forced instant refresh + /// + public void Refresh() + { + HoldInvalidation = false; + + lock (Core.InvalidationLock) + { + Core.LastInvalidation = DateTime.Now; + } + + #if DEBUG + Console.WriteLine(String.Format("Tread: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); + #endif + base.QueueDraw(); + } + + /// + /// enque built-in thread safe invalidation + /// + public void Invalidate() + { + if (Core.Refresh != null) + { + Core.Refresh.Set(); + } + } + + private bool _GrayScale = false; + + [Category("GMap.NET")] + public bool GrayScaleMode + { + get + { + return _GrayScale; + } + set + { + _GrayScale = value; + ColorMatrix = (value == true ? ColorMatrixs.GrayScale : null); + } + } + + private bool _Negative = false; + + [Category("GMap.NET")] + public bool NegativeMode + { + get + { + return _Negative; + } + set + { + _Negative = value; + ColorMatrix = (value == true ? ColorMatrixs.Negative : null); + } + } + + ColorMatrix colorMatrix; + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public ColorMatrix ColorMatrix + { + get + { + return colorMatrix; + } + set + { + colorMatrix = value; + if (GMapProvider.TileImageProxy != null && GMapProvider.TileImageProxy is GMapImageProxy) + { + (GMapProvider.TileImageProxy as GMapImageProxy).ColorMatrix = value; + if (Core.IsStarted) + { + ReloadMap(); + } + } + } + } + + public GPoint RenderOffset{ + get{ + return Core.RenderOffset; + } + } + + // internal stuff + internal readonly Core Core = new Core(); + + internal readonly Font CopyrightFont = new Font(FontFamily.GenericSansSerif, 7, FontStyle.Regular); + internal readonly Font MissingDataFont = new Font(FontFamily.GenericSansSerif, 11, FontStyle.Bold); + Font ScaleFont = new Font(FontFamily.GenericSansSerif, 5, FontStyle.Italic); + internal readonly StringFormat CenterFormat = new StringFormat(); + internal readonly StringFormat BottomFormat = new StringFormat(); + readonly ImageAttributes TileFlipXYAttributes = new ImageAttributes(); + double zoomReal; + Bitmap backBuffer; + Graphics gxOff; + + #if DEBUG + public Thread GuiThread; //Only for Debug + #endif + +#if !DESIGN + /// + /// construct + /// + public GMapControl() + { + #if DEBUG + GuiThread = Thread.CurrentThread; + Console.WriteLine(String.Format("Tread: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); + #endif + if (!IsDesignerHosted) + { + AddEvents ((int) Gdk.EventMask.ButtonPressMask); + AddEvents ((int) Gdk.EventMask.ButtonReleaseMask); + AddEvents ((int) Gdk.EventMask.PointerMotionMask); + AddEvents ((int) Gdk.EventMask.ScrollMask); + + //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); + //this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); + //this.SetStyle(ControlStyles.UserPaint, true); + //this.SetStyle(ControlStyles.Opaque, true); + //ResizeRedraw = true; + + TileFlipXYAttributes.SetWrapMode(WrapMode.TileFlipXY); + + // only one mode will be active, to get mixed mode create new ColorMatrix + GrayScaleMode = GrayScaleMode; + NegativeMode = NegativeMode; + + Core.SystemType = "WindowsForms"; + + RenderMode = RenderMode.GDI_PLUS; + + CenterFormat.Alignment = StringAlignment.Center; + CenterFormat.LineAlignment = StringAlignment.Center; + + BottomFormat.Alignment = StringAlignment.Center; + + BottomFormat.LineAlignment = StringAlignment.Far; + + if (GMaps.Instance.IsRunningOnMono) + { + // no imports to move pointer + MouseWheelZoomType = GMap.NET.MouseWheelZoomType.MousePositionWithoutCenter; + } + + Overlays.CollectionChanged += new NotifyCollectionChangedEventHandler(Overlays_CollectionChanged); + } + } + +#endif + + static GMapControl() + { + GMapImageProxy.Enable(); + GMaps.Instance.SQLitePing(); + } + + void Overlays_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.NewItems != null) + { + foreach (GMapOverlay obj in e.NewItems) + { + if (obj != null) + { + obj.Control = this; + } + } + + if (Core.IsStarted && !HoldInvalidation) + { + Invalidate(); + } + } + } + + void invalidatorEngage(object sender, ProgressChangedEventArgs e) + { + Console.WriteLine(String.Format("Get invaladation from Tread: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); + Gtk.Application.Invoke(delegate { + base.QueueDraw(); + }); + } + + /// + /// update objects when map is draged/zoomed + /// + internal void ForceUpdateOverlays() + { + Console.WriteLine(String.Format("Tread: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); + try + { + HoldInvalidation = true; + + foreach (GMapOverlay o in Overlays) + { + if (o.IsVisibile) + { + o.ForceUpdate(); + } + } + } + finally + { + Refresh(); + } + } + + /// + /// updates markers local position + /// + /// + public void UpdateMarkerLocalPosition(GMapMarker marker) + { + GPoint p = FromLatLngToLocal(marker.Position); + { + if (!MobileMode) + { + p.OffsetNegative(Core.RenderOffset); + } + marker.LocalPosition = new System.Drawing.Point((int)(p.X + marker.Offset.X), (int)(p.Y + marker.Offset.Y)); + } + } + + /// + /// updates routes local position + /// + /// + public void UpdateRouteLocalPosition(GMapRoute route) + { + route.LocalPoints.Clear(); + + for (int i = 0; i < route.Points.Count; i++) + { + GPoint p = FromLatLngToLocal(route.Points[i]); + + if (!MobileMode) + { + p.OffsetNegative(Core.RenderOffset); + } + route.LocalPoints.Add(p); + } + route.UpdateGraphicsPath(); + } + + /// + /// updates polygons local position + /// + /// + public void UpdatePolygonLocalPosition(GMapPolygon polygon) + { + polygon.LocalPoints.Clear(); + + for (int i = 0; i < polygon.Points.Count; i++) + { + GPoint p = FromLatLngToLocal(polygon.Points[i]); + if (!MobileMode) + { + p.OffsetNegative(Core.RenderOffset); + } + polygon.LocalPoints.Add(p); + } + polygon.UpdateGraphicsPath(); + } + + /// + /// sets zoom to max to fit rect + /// + /// + /// + public bool SetZoomToFitRect(RectLatLng rect) + { + if (lazyEvents) + { + lazySetZoomToFitRect = rect; + } + else + { + int maxZoom = Core.GetMaxZoomToFitRect(rect); + if (maxZoom > 0) + { + PointLatLng center = new PointLatLng(rect.Lat - (rect.HeightLat / 2), rect.Lng + (rect.WidthLng / 2)); + Position = center; + + if (maxZoom > MaxZoom) + { + maxZoom = MaxZoom; + } + + if ((int)Zoom != maxZoom) + { + Zoom = maxZoom; + } + + return true; + } + } + + return false; + } + + RectLatLng? lazySetZoomToFitRect = null; + bool lazyEvents = true; + + /// + /// sets to max zoom to fit all markers and centers them in map + /// + /// overlay id or null to check all + /// + public bool ZoomAndCenterMarkers(string overlayId) + { + RectLatLng? rect = GetRectOfAllMarkers(overlayId); + if (rect.HasValue) + { + return SetZoomToFitRect(rect.Value); + } + + return false; + } + + /// + /// zooms and centers all route + /// + /// overlay id or null to check all + /// + public bool ZoomAndCenterRoutes(string overlayId) + { + RectLatLng? rect = GetRectOfAllRoutes(overlayId); + if (rect.HasValue) + { + return SetZoomToFitRect(rect.Value); + } + + return false; + } + + /// + /// zooms and centers route + /// + /// + /// + public bool ZoomAndCenterRoute(MapRoute route) + { + RectLatLng? rect = GetRectOfRoute(route); + if (rect.HasValue) + { + return SetZoomToFitRect(rect.Value); + } + + return false; + } + + /// + /// gets rectangle with all objects inside + /// + /// overlay id or null to check all + /// + public RectLatLng? GetRectOfAllMarkers(string overlayId) + { + RectLatLng? ret = null; + + double left = double.MaxValue; + double top = double.MinValue; + double right = double.MinValue; + double bottom = double.MaxValue; + + foreach (GMapOverlay o in Overlays) + { + if (overlayId == null || o.Id == overlayId) + { + if (o.IsVisibile && o.Markers.Count > 0) + { + foreach (GMapMarker m in o.Markers) + { + if (m.IsVisible) + { + // left + if (m.Position.Lng < left) + { + left = m.Position.Lng; + } + + // top + if (m.Position.Lat > top) + { + top = m.Position.Lat; + } + + // right + if (m.Position.Lng > right) + { + right = m.Position.Lng; + } + + // bottom + if (m.Position.Lat < bottom) + { + bottom = m.Position.Lat; + } + } + } + } + } + } + + if (left != double.MaxValue && right != double.MinValue && top != double.MinValue && bottom != double.MaxValue) + { + ret = RectLatLng.FromLTRB(left, top, right, bottom); + } + + return ret; + } + + /// + /// gets rectangle with all objects inside + /// + /// overlay id or null to check all + /// + public RectLatLng? GetRectOfAllRoutes(string overlayId) + { + RectLatLng? ret = null; + + double left = double.MaxValue; + double top = double.MinValue; + double right = double.MinValue; + double bottom = double.MaxValue; + + foreach (GMapOverlay o in Overlays) + { + if (overlayId == null || o.Id == overlayId) + { + if (o.IsVisibile && o.Routes.Count > 0) + { + foreach (GMapRoute route in o.Routes) + { + if (route.IsVisible && route.From.HasValue && route.To.HasValue) + { + foreach (PointLatLng p in route.Points) + { + // left + if (p.Lng < left) + { + left = p.Lng; + } + + // top + if (p.Lat > top) + { + top = p.Lat; + } + + // right + if (p.Lng > right) + { + right = p.Lng; + } + + // bottom + if (p.Lat < bottom) + { + bottom = p.Lat; + } + } + } + } + } + } + } + + if (left != double.MaxValue && right != double.MinValue && top != double.MinValue && bottom != double.MaxValue) + { + ret = RectLatLng.FromLTRB(left, top, right, bottom); + } + + return ret; + } + + /// + /// gets rect of route + /// + /// + /// + public RectLatLng? GetRectOfRoute(MapRoute route) + { + RectLatLng? ret = null; + + double left = double.MaxValue; + double top = double.MinValue; + double right = double.MinValue; + double bottom = double.MaxValue; + + if (route.From.HasValue && route.To.HasValue) + { + foreach (PointLatLng p in route.Points) + { + // left + if (p.Lng < left) + { + left = p.Lng; + } + + // top + if (p.Lat > top) + { + top = p.Lat; + } + + // right + if (p.Lng > right) + { + right = p.Lng; + } + + // bottom + if (p.Lat < bottom) + { + bottom = p.Lat; + } + } + ret = RectLatLng.FromLTRB(left, top, right, bottom); + } + return ret; + } + + /// + /// gets image of the current view + /// + /// + public Image ToImage() + { + Image ret = null; + + bool r = ForceDoubleBuffer; + try + { + UpdateBackBuffer(); + + if (!r) + { + ForceDoubleBuffer = true; + } + + Refresh(); + // Application.DoEvents(); + + using (MemoryStream ms = new MemoryStream()) + { + using (var frame = (backBuffer.Clone() as Bitmap)) + { + frame.Save(ms, ImageFormat.Png); + } + ret = Image.FromStream(ms); + } + } + catch (Exception) + { + throw; + } + finally + { + if (!r) + { + ForceDoubleBuffer = false; + ClearBackBuffer(); + } + } + return ret; + } + + public Bitmap ToBitmap(Action waitTilesCount = null, bool runningFromMainThreed = true) + { + bool r = ForceDoubleBuffer; + Bitmap result; + try { + UpdateBackBuffer(); + + if(!r) + { + ForceDoubleBuffer = true; + } + + int lastCount = 0; + Console.WriteLine($"Start waiting {Core._loadWaitCount}"); + + while(Core.IsWaitTileLoad) + { + Console.WriteLine($"waiting {Core._loadWaitCount}"); + + #if NET46 + if (lastCount != Core.TileLoadQueue4.Count) + waitTilesCount?.Invoke(Core.TileLoadQueue4.Count); + #endif + + if(runningFromMainThreed) + Gtk.Main.Iteration(); + else + Thread.Sleep(200); + } + + DrawGraphics(gxOff); + + result = backBuffer.Clone() as Bitmap; + } catch(Exception) { + throw; + } finally { + if(!r) { + ForceDoubleBuffer = false; + ClearBackBuffer(); + } + } + return result; + } + + /// + /// offset position in pixels + /// + /// + /// + public void Offset(int x, int y) + { + if (IsRotated) + { + System.Drawing.Point[] p = new System.Drawing.Point[] { new System.Drawing.Point(x, y) }; + rotationMatrixInvert.TransformVectors(p); + x = (int)p[0].X; + y = (int)p[0].Y; + } + Core.DragOffset(new GPoint(x, y)); + + ForceUpdateOverlays(); + } + +#region UserControl Events + + public readonly static bool IsDesignerHosted = LicenseManager.UsageMode == LicenseUsageMode.Designtime; + + protected override void OnShown() // OnLoad + { + base.OnShown(); + + if (!IsDesignerHosted) + { + //MethodInvoker m = delegate + //{ + // Thread.Sleep(444); + + //OnSizeChanged(null); + + if (lazyEvents) + { + lazyEvents = false; + + if (lazySetZoomToFitRect.HasValue) + { + SetZoomToFitRect(lazySetZoomToFitRect.Value); + lazySetZoomToFitRect = null; + } + } + Core.OnMapOpen().ProgressChanged += new ProgressChangedEventHandler(invalidatorEngage); + ForceUpdateOverlays(); + //}; + //this.BeginInvoke(m); + } + } + + /* protected override void OnCreateControl() + { + base.OnCreateControl(); + + if (!IsDesignerHosted) + { + var f = ParentForm; + if (f != null) + { + while (f.ParentForm != null) + { + f = f.ParentForm; + } + + if (f != null) + { + f.FormClosing += new FormClosingEventHandler(ParentForm_FormClosing); + } + } + } + } + + void ParentForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (e.CloseReason == CloseReason.WindowsShutDown || e.CloseReason == CloseReason.TaskManagerClosing) + { + Manager.CancelTileCaching(); + } + }*/ + + public override void Destroy() + { + Core.OnMapClose(); + + Overlays.CollectionChanged -= new NotifyCollectionChangedEventHandler(Overlays_CollectionChanged); + + foreach (var o in Overlays) + { + o.Dispose(); + } + Overlays.Clear(); + + ScaleFont.Dispose(); + ScalePen.Dispose(); + CenterFormat.Dispose(); + CenterPen.Dispose(); + BottomFormat.Dispose(); + CopyrightFont.Dispose(); + EmptyTileBorders.Dispose(); + EmptytileBrush.Dispose(); + + SelectedAreaFill.Dispose(); + SelectionPen.Dispose(); + ClearBackBuffer(); + + base.Destroy(); + } + + PointLatLng selectionStart; + PointLatLng selectionEnd; + + float? MapRenderTransform = null; + + public Color EmptyMapBackground = Color.WhiteSmoke; + + [Category("GMap.NET")] + [Description("Widget has frame")] + public bool HasFrame { get; set;} + + protected override bool OnExposeEvent(Gdk.EventExpose e) + { + Console.WriteLine(String.Format("Tread: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); + if (ForceDoubleBuffer) + { + if (gxOff != null) + { + DrawGraphics(gxOff); + //throw new NotSupportedException(); + //e.Graphics.DrawImage(backBuffer, 0, 0); + } + } + else + { + Graphics g = null; + try { + g = Gtk.DotNet.Graphics.FromDrawable(e.Window); + } catch(NullReferenceException) { + return base.OnExposeEvent(e); + } + g.SetClip(new Rectangle(e.Area.X, e.Area.Y, e.Area.Width, e.Area.Height)); + DrawGraphics(g); + g.Dispose(); + } + + if(HasFrame) + { + var gc = new Gdk.GC(e.Window); + e.Window.DrawRectangle(gc, false, e.Area.X, e.Area.Y, e.Area.Width - 1, e.Area.Height - 1); + } + + return base.OnExposeEvent(e); + } + + void DrawGraphics(Graphics g) + { + // render white background + g.Clear(EmptyMapBackground); + + if (MapRenderTransform.HasValue) + { +#region -- scale -- + if (!MobileMode) + { + var center = new GPoint(Allocation.Width / 2, Allocation.Height / 2); + var delta = center; + delta.OffsetNegative(Core.RenderOffset); + var pos = center; + pos.OffsetNegative(delta); + + g.ScaleTransform(MapRenderTransform.Value, MapRenderTransform.Value, MatrixOrder.Append); + g.TranslateTransform(pos.X, pos.Y, MatrixOrder.Append); + + DrawMap(g); + g.ResetTransform(); + + g.TranslateTransform(pos.X, pos.Y, MatrixOrder.Append); + } + else + { + DrawMap(g); + g.ResetTransform(); + } + OnPaintOverlays(g); +#endregion + } + else + { + if (IsRotated) + { +#region -- rotation -- + + g.TextRenderingHint = TextRenderingHint.AntiAlias; + g.SmoothingMode = SmoothingMode.AntiAlias; + + g.TranslateTransform((float)(Core.Width / 2.0), (float)(Core.Height / 2.0)); + g.RotateTransform(-Bearing); + g.TranslateTransform((float)(-Core.Width / 2.0), (float)(-Core.Height / 2.0)); + + g.TranslateTransform(Core.RenderOffset.X, Core.RenderOffset.Y); + + DrawMap(g); + + g.ResetTransform(); + g.TranslateTransform(Core.RenderOffset.X, Core.RenderOffset.Y); + + OnPaintOverlays(g); + +#endregion + } + else + { + if (!MobileMode) + { + g.TranslateTransform(Core.RenderOffset.X, Core.RenderOffset.Y); + } + DrawMap(g); + OnPaintOverlays(g); + } + } + } + + void DrawMap(Graphics g) + { + if (Core.UpdatingBounds || MapProvider == EmptyProvider.Instance || MapProvider == null) + { + Debug.WriteLine("Core.UpdatingBounds"); + return; + } + + Core.TileDrawingListLock.AcquireReaderLock(); + Core.Matrix.EnterReadLock(); + + //g.TextRenderingHint = TextRenderingHint.AntiAlias; + //g.SmoothingMode = SmoothingMode.AntiAlias; + //g.CompositingQuality = CompositingQuality.HighQuality; + //g.InterpolationMode = InterpolationMode.HighQualityBicubic; + + try + { + foreach (var tilePoint in Core.TileDrawingList) + { + { + Core.TileRect.Location = tilePoint.PosPixel; + if (ForceDoubleBuffer) + { + if (MobileMode) + { + Core.TileRect.Offset(Core.RenderOffset); + } + } + Core.TileRect.OffsetNegative(Core.CompensationOffset); + + //if(Core.currentRegion.IntersectsWith(Core.tileRect) || IsRotated) + { + bool found = false; + + Tile t = Core.Matrix.GetTileWithNoLock(Core.Zoom, tilePoint.PosXY); + if (t.NotEmpty) + { + // render tile + { + foreach (GMapImage img in t.Overlays) + { + if (img != null && img.Img != null) + { + if (!found) + found = true; + + if (!img.IsParent) + { + if (!MapRenderTransform.HasValue && !IsRotated) + { + g.DrawImage(img.Img, Core.TileRect.X, Core.TileRect.Y, Core.TileRect.Width, Core.TileRect.Height); + } + else + { + g.DrawImage(img.Img, new Rectangle((int)Core.TileRect.X, (int)Core.TileRect.Y, (int)Core.TileRect.Width, (int)Core.TileRect.Height), 0, 0, Core.TileRect.Width, Core.TileRect.Height, GraphicsUnit.Pixel, TileFlipXYAttributes); + } + } + else + { + // TODO: move calculations to loader thread + System.Drawing.RectangleF srcRect = new System.Drawing.RectangleF((float)(img.Xoff * (img.Img.Width / img.Ix)), (float)(img.Yoff * (img.Img.Height / img.Ix)), (img.Img.Width / img.Ix), (img.Img.Height / img.Ix)); + System.Drawing.Rectangle dst = new System.Drawing.Rectangle((int)Core.TileRect.X, (int)Core.TileRect.Y, (int)Core.TileRect.Width, (int)Core.TileRect.Height); + + g.DrawImage(img.Img, dst, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, GraphicsUnit.Pixel, TileFlipXYAttributes); + } + } + } + } + } + else if (FillEmptyTiles && MapProvider.Projection is MercatorProjection) + { +#region -- fill empty lines -- + int zoomOffset = 1; + Tile parentTile = Tile.Empty; + long Ix = 0; + + while (!parentTile.NotEmpty && zoomOffset < Core.Zoom && zoomOffset <= LevelsKeepInMemmory) + { + Ix = (long)Math.Pow(2, zoomOffset); + parentTile = Core.Matrix.GetTileWithNoLock(Core.Zoom - zoomOffset++, new GPoint((int)(tilePoint.PosXY.X / Ix), (int)(tilePoint.PosXY.Y / Ix))); + } + + if (parentTile.NotEmpty) + { + long Xoff = Math.Abs(tilePoint.PosXY.X - (parentTile.Pos.X * Ix)); + long Yoff = Math.Abs(tilePoint.PosXY.Y - (parentTile.Pos.Y * Ix)); + + // render tile + { + foreach (GMapImage img in parentTile.Overlays) + { + if (img != null && img.Img != null && !img.IsParent) + { + if (!found) + found = true; + + System.Drawing.RectangleF srcRect = new System.Drawing.RectangleF((float)(Xoff * (img.Img.Width / Ix)), (float)(Yoff * (img.Img.Height / Ix)), (img.Img.Width / Ix), (img.Img.Height / Ix)); + System.Drawing.Rectangle dst = new System.Drawing.Rectangle((int)Core.TileRect.X, (int)Core.TileRect.Y, (int)Core.TileRect.Width, (int)Core.TileRect.Height); + + g.DrawImage(img.Img, dst, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, GraphicsUnit.Pixel, TileFlipXYAttributes); + g.FillRectangle(SelectedAreaFill, dst); + } + } + } + } +#endregion + } + // add text if tile is missing + if (!found) + { + lock (Core.FailedLoads) + { + var lt = new LoadTask(tilePoint.PosXY, Core.Zoom); + if (Core.FailedLoads.ContainsKey(lt)) + { + var ex = Core.FailedLoads[lt]; + + g.FillRectangle(EmptytileBrush, new RectangleF(Core.TileRect.X, Core.TileRect.Y, Core.TileRect.Width, Core.TileRect.Height)); + + g.DrawString("Exception: " + ex.Message, MissingDataFont, Brushes.Red, new RectangleF(Core.TileRect.X + 11, Core.TileRect.Y + 11, Core.TileRect.Width - 11, Core.TileRect.Height - 11)); + + g.DrawString(EmptyTileText, MissingDataFont, Brushes.Blue, new RectangleF(Core.TileRect.X, Core.TileRect.Y, Core.TileRect.Width, Core.TileRect.Height), CenterFormat); + + g.DrawRectangle(EmptyTileBorders, (int)Core.TileRect.X, (int)Core.TileRect.Y, (int)Core.TileRect.Width, (int)Core.TileRect.Height); + } + } + } + + if (ShowTileGridLines) + { + g.DrawRectangle(EmptyTileBorders, (int)Core.TileRect.X, (int)Core.TileRect.Y, (int)Core.TileRect.Width, (int)Core.TileRect.Height); + { + g.DrawString((tilePoint.PosXY == Core.CenterTileXYLocation ? "CENTER: " : "TILE: ") + tilePoint, MissingDataFont, Brushes.Red, new RectangleF(Core.TileRect.X, Core.TileRect.Y, Core.TileRect.Width, Core.TileRect.Height), CenterFormat); + } + } + } + } + } + } + finally + { + Core.Matrix.LeaveReadLock(); + Core.TileDrawingListLock.ReleaseReaderLock(); + } + } + + /// + /// override, to render something more + /// + /// + protected virtual void OnPaintOverlays(Graphics g) + { +#if DEBUG + if(GuiThread != Thread.CurrentThread) + { + Debug.WriteLine("Paint from not Gui thread."); + return; + } +#endif + + g.SmoothingMode = SmoothingMode.HighQuality; + foreach (GMapOverlay o in Overlays) + { + if (o.IsVisibile) + { + o.OnRender(g); + } + } + + // center in virtual space... +#if DEBUG + if (!IsRotated) + { + g.DrawLine(ScalePen, -20, 0, 20, 0); + g.DrawLine(ScalePen, 0, -20, 0, 20); + g.DrawString("debug build", CopyrightFont, Brushes.Blue, 2, CopyrightFont.Height); + } +#endif + + if (!MobileMode) + { + g.ResetTransform(); + } + + if (!SelectedArea.IsEmpty) + { + GPoint p1 = FromLatLngToLocal(SelectedArea.LocationTopLeft); + GPoint p2 = FromLatLngToLocal(SelectedArea.LocationRightBottom); + + long x1 = p1.X; + long y1 = p1.Y; + long x2 = p2.X; + long y2 = p2.Y; + + g.DrawRectangle(SelectionPen, x1, y1, x2 - x1, y2 - y1); + g.FillRectangle(SelectedAreaFill, x1, y1, x2 - x1, y2 - y1); + } + + if (renderHelperLine) + { + int mouseX, mouseY; + base.GetPointer(out mouseX, out mouseY); + + g.DrawLine(HelperLinePen, mouseX, 0, mouseX, Allocation.Height); + g.DrawLine(HelperLinePen, 0, mouseY, Allocation.Width, mouseY); + } + if (ShowCenter) + { + g.DrawLine(CenterPen, Allocation.Width / 2 - 5, Allocation.Height / 2, Allocation.Width / 2 + 5, Allocation.Height / 2); + g.DrawLine(CenterPen, Allocation.Width / 2, Allocation.Height / 2 - 5, Allocation.Width / 2, Allocation.Height / 2 + 5); + } + +#region -- copyright -- + + if (!string.IsNullOrEmpty(Core.Provider.Copyright)) + { + g.DrawString(Core.Provider.Copyright, CopyrightFont, Brushes.Navy, 3, Allocation.Height - CopyrightFont.Height - 5); + } + +#endregion + +#region -- draw scale -- + if (MapScaleInfoEnabled) + { + if (Allocation.Width > Core.PxRes5000Km) + { + g.DrawRectangle(ScalePen, 10, 10, Core.PxRes5000Km, 10); + g.DrawString("5000Km", ScaleFont, Brushes.Blue, Core.PxRes5000Km + 10, 11); + } + if (Allocation.Width > Core.PxRes1000Km) + { + g.DrawRectangle(ScalePen, 10, 10, Core.PxRes1000Km, 10); + g.DrawString("1000Km", ScaleFont, Brushes.Blue, Core.PxRes1000Km + 10, 11); + } + if (Allocation.Width > Core.PxRes100Km && Zoom > 2) + { + g.DrawRectangle(ScalePen, 10, 10, Core.PxRes100Km, 10); + g.DrawString("100Km", ScaleFont, Brushes.Blue, Core.PxRes100Km + 10, 11); + } + if (Allocation.Width > Core.PxRes10Km && Zoom > 5) + { + g.DrawRectangle(ScalePen, 10, 10, Core.PxRes10Km, 10); + g.DrawString("10Km", ScaleFont, Brushes.Blue, Core.PxRes10Km + 10, 11); + } + if (Allocation.Width > Core.PxRes1000M && Zoom >= 10) + { + g.DrawRectangle(ScalePen, 10, 10, Core.PxRes1000M, 10); + g.DrawString("1000m", ScaleFont, Brushes.Blue, Core.PxRes1000M + 10, 11); + } + if (Allocation.Width > Core.PxRes100M && Zoom > 11) + { + g.DrawRectangle(ScalePen, 10, 10, Core.PxRes100M, 10); + g.DrawString("100m", ScaleFont, Brushes.Blue, Core.PxRes100M + 9, 11); + } + } +#endregion + } + + readonly Matrix rotationMatrix = new Matrix(); + readonly Matrix rotationMatrixInvert = new Matrix(); + + /// + /// updates rotation matrix + /// + void UpdateRotationMatrix() + { + PointF center = new PointF(Core.Width / 2, Core.Height / 2); + + rotationMatrix.Reset(); + rotationMatrix.RotateAt(-Bearing, center); + + rotationMatrixInvert.Reset(); + rotationMatrixInvert.RotateAt(-Bearing, center); + rotationMatrixInvert.Invert(); + } + + /// + /// returs true if map bearing is not zero + /// + [Browsable(false)] + public bool IsRotated + { + get + { + return Core.IsRotated; + } + } + + /// + /// bearing for rotation of the map + /// + [Category("GMap.NET")] + public float Bearing + { + get + { + return Core.Bearing; + } + set + { + if (Core.Bearing != value) + { + bool resize = Core.Bearing == 0; + Core.Bearing = value; + + //if(VirtualSizeEnabled) + //{ + // c.X += (Width - Core.vWidth) / 2; + // c.Y += (Height - Core.vHeight) / 2; + //} + + UpdateRotationMatrix(); + + if (value != 0 && value % 360 != 0) + { + Core.IsRotated = true; + + if (Core.TileRectBearing.Size == Core.TileRect.Size) + { + Core.TileRectBearing = Core.TileRect; + Core.TileRectBearing.Inflate(1, 1); + } + } + else + { + Core.IsRotated = false; + Core.TileRectBearing = Core.TileRect; + } + + if (resize) + { + Core.OnMapSizeChanged(Allocation.Width, Allocation.Height); + } + + if (!HoldInvalidation && Core.IsStarted) + { + ForceUpdateOverlays(); + } + } + } + } + + /// + /// shrinks map area, useful just for testing + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public bool VirtualSizeEnabled + { + get + { + return Core.VirtualSizeEnabled; + } + set + { + Core.VirtualSizeEnabled = value; + } + } + + protected override void OnSizeAllocated(Gdk.Rectangle box) + { + base.OnSizeAllocated(box); + Console.WriteLine(String.Format("Allocation Tread: {0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); + if (box.Width == 0 || box.Height == 0) + { + Debug.WriteLine("minimized"); + return; + } + + if (box.Width == Core.Width && box.Height == Core.Height) + { + Debug.WriteLine("maximized"); + return; + } + + if (!IsDesignerHosted) + { + if (ForceDoubleBuffer) + { + UpdateBackBuffer(); + } + + if (VirtualSizeEnabled) + { + Core.OnMapSizeChanged(Core.VWidth, Core.VHeight); + } + else + { + Core.OnMapSizeChanged(box.Width, box.Height); + } + //Core.currentRegion = new GRect(-50, -50, Core.Width + 50, Core.Height + 50); + + if (Visible && Core.IsStarted) + { + if (IsRotated) + { + UpdateRotationMatrix(); + } + ForceUpdateOverlays(); + } + } + } + + public void SetFakeAllocationSize(Gdk.Rectangle box) + { + + if(!Core.IsStarted) { + lazyEvents = false; + Core.OnMapOpen(); + ForceUpdateOverlays(); + //Core.ReloadMap(); + } + + Allocation = box; + OnSizeAllocated(box); + } + + void UpdateBackBuffer() + { + ClearBackBuffer(); + + backBuffer = new Bitmap(Allocation.Width, Allocation.Height); + gxOff = Graphics.FromImage(backBuffer); + } + + private void ClearBackBuffer() + { + if (backBuffer != null) + { + backBuffer.Dispose(); + backBuffer = null; + } + if (gxOff != null) + { + gxOff.Dispose(); + gxOff = null; + } + } + + bool isSelected = false; + protected override bool OnButtonPressEvent(Gdk.EventButton e) + { + if (!IsMouseOverMarker) + { + if (e.Button == DragButton && CanDragMap) + { + Core.MouseDown = ApplyRotationInversion((int)e.X, (int)e.Y); + this.Invalidate(); + } + else if (!isSelected) + { + isSelected = true; + SelectedArea = RectLatLng.Empty; + selectionEnd = PointLatLng.Empty; + selectionStart = FromLocalToLatLng((int)e.X, (int)e.Y); + } + } + return base.OnButtonPressEvent(e); + } + + protected override bool OnButtonReleaseEvent(Gdk.EventButton e) + { + if (isSelected) + { + isSelected = false; + } + + if (Core.IsDragging) + { + if (isDragging) + { + isDragging = false; + Debug.WriteLine("IsDragging = " + isDragging); + currentCursorType = Gdk.CursorType.LeftPtr; + this.GdkWindow.Cursor = new Gdk.Cursor(currentCursorType); + } + Core.EndDrag(); + + if (BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position)) + { + if (Core.LastLocationInBounds.HasValue) + { + Position = Core.LastLocationInBounds.Value; + } + } + } + else + { + if (e.Button == DragButton) + { + Core.MouseDown = GPoint.Empty; + } + + if (!selectionEnd.IsEmpty && !selectionStart.IsEmpty) + { + bool zoomtofit = false; + + if (!SelectedArea.IsEmpty && e.State.HasFlag(Gdk.ModifierType.ShiftMask)) + { + zoomtofit = SetZoomToFitRect(SelectedArea); + } + + if (OnSelectionChange != null) + { + OnSelectionChange(SelectedArea, zoomtofit); + } + } + else + { + Invalidate(); + } + } + return base.OnButtonReleaseEvent(e); + } + + /// + /// apply transformation if in rotation mode + /// + GPoint ApplyRotationInversion(int x, int y) + { + GPoint ret = new GPoint(x, y); + + if (IsRotated) + { + System.Drawing.Point[] tt = new System.Drawing.Point[] { new System.Drawing.Point(x, y) }; + rotationMatrixInvert.TransformPoints(tt); + var f = tt[0]; + + ret.X = f.X; + ret.Y = f.Y; + } + + return ret; + } + + /// + /// apply transformation if in rotation mode + /// + GPoint ApplyRotation(int x, int y) + { + GPoint ret = new GPoint(x, y); + + if (IsRotated) + { + System.Drawing.Point[] tt = new System.Drawing.Point[] { new System.Drawing.Point(x, y) }; + rotationMatrix.TransformPoints(tt); + var f = tt[0]; + + ret.X = f.X; + ret.Y = f.Y; + } + + return ret; + } + + Gdk.CursorType currentCursorType; + + /// + /// Gets the width and height of a rectangle centered on the point the mouse + /// button was pressed, within which a drag operation will not begin. + /// + public Size DragSize = new Size(4, 4); + + protected override bool OnMotionNotifyEvent(Gdk.EventMotion e) + { + if (!Core.IsDragging && !Core.MouseDown.IsEmpty) + { + GPoint p = ApplyRotationInversion((int)e.X, (int)e.Y); + if (Math.Abs(p.X - Core.MouseDown.X) * 2 >= DragSize.Width || Math.Abs(p.Y - Core.MouseDown.Y) * 2 >= DragSize.Height) + { + Core.BeginDrag(Core.MouseDown); + } + } + + if (Core.IsDragging) + { + if (!isDragging) + { + isDragging = true; + Debug.WriteLine("IsDragging = " + isDragging); + + currentCursorType = Gdk.CursorType.Fleur; + this.GdkWindow.Cursor = new Gdk.Cursor(currentCursorType); + } + + if (BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position)) + { + // ... + } + else + { + Core.MouseCurrent = ApplyRotationInversion((int)e.X, (int)e.Y); + Core.Drag(Core.MouseCurrent); + if (MobileMode || IsRotated) + { + ForceUpdateOverlays(); + } + base.QueueDraw(); + } + } + else + { + if (isSelected && !selectionStart.IsEmpty && (e.State.HasFlag(Gdk.ModifierType.ShiftMask) || e.State.HasFlag(Gdk.ModifierType.Mod1Mask) || DisableAltForSelection)) + { + selectionEnd = FromLocalToLatLng((int)e.X, (int)e.Y); + { + GMap.NET.PointLatLng p1 = selectionStart; + GMap.NET.PointLatLng p2 = selectionEnd; + + 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); + + SelectedArea = new RectLatLng(y1, x1, x2 - x1, y1 - y2); + } + } + else + if (Core.MouseDown.IsEmpty) + { + for (int i = Overlays.Count - 1; i >= 0; i--) + { + GMapOverlay o = Overlays[i]; + if (o != null && o.IsVisibile) + { + foreach (GMapMarker m in o.Markers) + { + if (m.IsVisible && m.IsHitTestVisible) + { +#region -- check -- + + GPoint rp = new GPoint((long)e.X, (long)e.Y); + if (!MobileMode) + { + rp.OffsetNegative(Core.RenderOffset); + } + if (m.LocalArea.Contains((int)rp.X, (int)rp.Y)) + { + if (!m.IsMouseOver) + { + SetCursorHandOnEnter(); + + m.IsMouseOver = true; + IsMouseOverMarker = true; + + if (OnMarkerEnter != null) + { + OnMarkerEnter(m); + } + + Invalidate(); + } + } + else if (m.IsMouseOver) + { + m.IsMouseOver = false; + IsMouseOverMarker = false; + RestoreCursorOnLeave(); + if (OnMarkerLeave != null) + { + OnMarkerLeave(m); + } + + Invalidate(); + } +#endregion + } + } + + foreach (GMapRoute m in o.Routes) + { + if (m.IsVisible && m.IsHitTestVisible) + { +#region -- check -- + + GPoint rp = new GPoint((long)e.X, (long)e.Y); + if (!MobileMode) + { + rp.OffsetNegative(Core.RenderOffset); + } + if (m.IsInside((int)rp.X, (int)rp.Y)) + { + if (!m.IsMouseOver) + { + SetCursorHandOnEnter(); + m.IsMouseOver = true; + IsMouseOverRoute = true; + + if (OnRouteEnter != null) + { + OnRouteEnter(m); + } + + Invalidate(); + } + } + else + { + if (m.IsMouseOver) + { + m.IsMouseOver = false; + IsMouseOverRoute = false; + RestoreCursorOnLeave(); + if (OnRouteLeave != null) + { + OnRouteLeave(m); + } + + Invalidate(); + } + } +#endregion + } + } + + foreach (GMapPolygon m in o.Polygons) + { + if (m.IsVisible && m.IsHitTestVisible) + { +#region -- check -- + GPoint rp = new GPoint((long)e.X, (long)e.Y); + + if (!MobileMode) + { + rp.OffsetNegative(Core.RenderOffset); + } + + if (m.IsInsideLocal((int)rp.X, (int)rp.Y)) + { + if (!m.IsMouseOver) + { + SetCursorHandOnEnter(); + m.IsMouseOver = true; + IsMouseOverPolygon = true; + + if (OnPolygonEnter != null) + { + OnPolygonEnter(m); + } + + Invalidate(); + } + } + else + { + if (m.IsMouseOver) + { + m.IsMouseOver = false; + IsMouseOverPolygon = false; + RestoreCursorOnLeave(); + if (OnPolygonLeave != null) + { + OnPolygonLeave(m); + } + + Invalidate(); + } + } +#endregion + } + } + } + } + } + + if (renderHelperLine) + { + base.QueueDraw(); + } + } + return base.OnMotionNotifyEvent(e); + } + + internal void RestoreCursorOnLeave() + { + if (overObjectCount <= 0 && currentCursorType != Gdk.CursorType.LeftPtr) + { + overObjectCount = 0; + currentCursorType = Gdk.CursorType.LeftPtr; + this.GdkWindow.Cursor = new Gdk.Cursor(currentCursorType); + } + } + + internal void SetCursorHandOnEnter() + { + if (overObjectCount <= 0 && currentCursorType != Gdk.CursorType.Hand1) + { + overObjectCount = 0; + currentCursorType = Gdk.CursorType.Hand1; + this.GdkWindow.Cursor = new Gdk.Cursor(currentCursorType); + } + } + + /// + /// prevents focusing map if mouse enters it's area + /// + public bool DisableFocusOnMouseEnter = false; + + protected override bool OnEnterNotifyEvent(Gdk.EventCrossing e) + { + if (!DisableFocusOnMouseEnter) + { + GrabFocus(); + } + return base.OnEnterNotifyEvent(e); + } + + /// + /// reverses MouseWheel zooming direction + /// + public bool InvertedMouseWheelZooming = false; + + /// + /// lets you zoom by MouseWheel even when pointer is in area of marker + /// + public bool IgnoreMarkerOnMouseWheel = false; + + protected override bool OnScrollEvent(Gdk.EventScroll e) + { + if (MouseWheelZoomEnabled && (!IsMouseOverMarker || IgnoreMarkerOnMouseWheel) && !Core.IsDragging) + { + if (Core.MouseLastZoom.X != (int)e.X && Core.MouseLastZoom.Y != (int)e.Y) + { + if (MouseWheelZoomType == MouseWheelZoomType.MousePositionAndCenter) + { + Core.Position = FromLocalToLatLng((int)e.X, (int)e.Y); + } + else if (MouseWheelZoomType == MouseWheelZoomType.ViewCenter) + { + Core.Position = FromLocalToLatLng((int)Allocation.Width / 2, (int)Allocation.Height / 2); + } + else if (MouseWheelZoomType == MouseWheelZoomType.MousePositionWithoutCenter) + { + Core.Position = FromLocalToLatLng((int)e.X, (int)e.Y); + } + + Core.MouseLastZoom.X = (int)e.X; + Core.MouseLastZoom.Y = (int)e.Y; + } + + // set mouse position to map center + if (MouseWheelZoomType != MouseWheelZoomType.MousePositionWithoutCenter) + { + if (!GMaps.Instance.IsRunningOnMono) + { + //FIXME + //System.Drawing.Point p = PointToScreen(new System.Drawing.Point(Width / 2, Height / 2)); + //Stuff.SetCursorPos((int)p.X, (int)p.Y); + } + } + + Core.MouseWheelZooming = true; + + if (e.Direction == Gdk.ScrollDirection.Up) + { + if (!InvertedMouseWheelZooming) + { + Zoom = ((int)Zoom) + 1; + } + else + { + Zoom = ((int)(Zoom + 0.99)) - 1; + } + } + else if (e.Direction == Gdk.ScrollDirection.Down) + { + if (!InvertedMouseWheelZooming) + { + Zoom = ((int)(Zoom + 0.99)) - 1; + } + else + { + Zoom = ((int)Zoom) + 1; + } + } + + Core.MouseWheelZooming = false; + } + return base.OnScrollEvent(e); + } +#endregion + +#region IGControl Members + + /// + /// Call it to empty tile cache & reload tiles + /// + public void ReloadMap() + { + Core.ReloadMap(); + } + + /// + /// set current position using keywords + /// + /// + /// true if successfull + public GeoCoderStatusCode SetPositionByKeywords(string keys) + { + GeoCoderStatusCode status = GeoCoderStatusCode.UNKNOWN_ERROR; + + GeocodingProvider gp = MapProvider as GeocodingProvider; + if (gp == null) + { + gp = GMapProviders.OpenStreetMap as GeocodingProvider; + } + + if (gp != null) + { + var pt = gp.GetPoint(keys, out status); + if (status == GeoCoderStatusCode.G_GEO_SUCCESS && pt.HasValue) + { + Position = pt.Value; + } + } + + return status; + } + + public PointLatLng FromLocalToLatLng (GPoint point) + { + return FromLocalToLatLng ((int)point.X, (int)point.Y); + } + + /// + /// gets world coordinate from local control coordinate + /// + /// + /// + /// + public PointLatLng FromLocalToLatLng(int x, int y) + { + if (MapRenderTransform.HasValue) + { + //var xx = (int)(Core.RenderOffset.X + ((x - Core.RenderOffset.X) / MapRenderTransform.Value)); + //var yy = (int)(Core.RenderOffset.Y + ((y - Core.RenderOffset.Y) / MapRenderTransform.Value)); + + //PointF center = new PointF(Core.Width / 2, Core.Height / 2); + + //Matrix m = new Matrix(); + //m.Translate(-Core.RenderOffset.X, -Core.RenderOffset.Y); + //m.Scale(MapRenderTransform.Value, MapRenderTransform.Value); + + //System.Drawing.Point[] tt = new System.Drawing.Point[] { new System.Drawing.Point(x, y) }; + //m.TransformPoints(tt); + //var z = tt[0]; + + // + + x = (int)(Core.RenderOffset.X + ((x - Core.RenderOffset.X) / MapRenderTransform.Value)); + y = (int)(Core.RenderOffset.Y + ((y - Core.RenderOffset.Y) / MapRenderTransform.Value)); + } + + if (IsRotated) + { + System.Drawing.Point[] tt = new System.Drawing.Point[] { new System.Drawing.Point(x, y) }; + rotationMatrixInvert.TransformPoints(tt); + var f = tt[0]; + + if (VirtualSizeEnabled) + { + f.X += (Allocation.Width - Core.VWidth) / 2; + f.Y += (Allocation.Height - Core.VHeight) / 2; + } + + x = f.X; + y = f.Y; + } + return Core.FromLocalToLatLng(x, y); + } + + /// + /// gets local coordinate from world coordinate + /// + /// + /// + public GPoint FromLatLngToLocal(PointLatLng point) + { + GPoint ret = Core.FromLatLngToLocal(point); + + if (MapRenderTransform.HasValue) + { + ret.X = (int)(Core.RenderOffset.X + ((Core.RenderOffset.X - ret.X) * -MapRenderTransform.Value)); + ret.Y = (int)(Core.RenderOffset.Y + ((Core.RenderOffset.Y - ret.Y) * -MapRenderTransform.Value)); + } + + if (IsRotated) + { + System.Drawing.Point[] tt = new System.Drawing.Point[] { new System.Drawing.Point((int)ret.X, (int)ret.Y) }; + rotationMatrix.TransformPoints(tt); + var f = tt[0]; + + if (VirtualSizeEnabled) + { + f.X += (Allocation.Width - Core.VWidth) / 2; + f.Y += (Allocation.Height - Core.VHeight) / 2; + } + + ret.X = f.X; + ret.Y = f.Y; + } + + return ret; + } + + /// + /// shows map db export dialog + /// + /// + public bool ShowExportDialog() + { +/* using (FileDialog dlg = new SaveFileDialog()) + { + dlg.CheckPathExists = true; + dlg.CheckFileExists = false; + dlg.AddExtension = true; + dlg.DefaultExt = "gmdb"; + dlg.ValidateNames = true; + dlg.Title = "GMap.NET: Export map to db, if file exsist only new data will be added"; + dlg.FileName = "DataExp"; + dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + dlg.Filter = "GMap.NET DB files (*.gmdb)|*.gmdb"; + dlg.FilterIndex = 1; + dlg.RestoreDirectory = true; + + if (dlg.ShowDialog() == DialogResult.OK) + { + bool ok = GMaps.Instance.ExportToGMDB(dlg.FileName); + if (ok) + { + MessageBox.Show("Complete!", "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBox.Show("Failed!", "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + + return ok; + } + } +*/ + return false; + } + /// + /// shows map dbimport dialog + /// + /// + public bool ShowImportDialog() + { +/* using (FileDialog dlg = new OpenFileDialog()) + { + dlg.CheckPathExists = true; + dlg.CheckFileExists = false; + dlg.AddExtension = true; + dlg.DefaultExt = "gmdb"; + dlg.ValidateNames = true; + dlg.Title = "GMap.NET: Import to db, only new data will be added"; + dlg.FileName = "DataImport"; + dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + dlg.Filter = "GMap.NET DB files (*.gmdb)|*.gmdb"; + dlg.FilterIndex = 1; + dlg.RestoreDirectory = true; + + if (dlg.ShowDialog() == DialogResult.OK) + { + bool ok = GMaps.Instance.ImportFromGMDB(dlg.FileName); + if (ok) + { + MessageBox.Show("Complete!", "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Information); + ReloadMap(); + } + else + { + MessageBox.Show("Failed!", "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + + return ok; + } + } +*/ + return false; + } + + private ScaleModes scaleMode = ScaleModes.Integer; + + [Category("GMap.NET")] + [Description("map scale type")] + public ScaleModes ScaleMode + { + get + { + return scaleMode; + } + set + { + scaleMode = value; + } + } + + [Category("GMap.NET"), DefaultValue(0)] + public double Zoom + { + get + { + return zoomReal; + } + set + { + if (zoomReal != value) + { + //FIXME May be this line crash in Tread on mono. + //Debug.WriteLine("ZoomPropertyChanged: " + zoomReal + " -> " + value); + + if (value > MaxZoom) + { + zoomReal = MaxZoom; + } + else if (value < MinZoom) + { + zoomReal = MinZoom; + } + else + { + zoomReal = value; + } + + double remainder = value % 1; + if (ScaleMode == ScaleModes.Fractional && remainder != 0) + { + float scaleValue = (float)Math.Pow(2d, remainder); + { + MapRenderTransform = scaleValue; + } + + ZoomStep = Convert.ToInt32(value - remainder); + } + else + { + MapRenderTransform = null; + ZoomStep = (int)Math.Floor(value); + //zoomReal = ZoomStep; + } + + if (Core.IsStarted && !IsDragging) + { + ForceUpdateOverlays(); + } + } + } + } + + /// + /// map zoom level + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + internal int ZoomStep + { + get + { + return Core.Zoom; + } + set + { + if (value > MaxZoom) + { + Core.Zoom = MaxZoom; + } + else if (value < MinZoom) + { + Core.Zoom = MinZoom; + } + else + { + Core.Zoom = value; + } + } + } + + /// + /// current map center position + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public PointLatLng Position + { + get + { + return Core.Position; + } + set + { + Core.Position = value; + + if (Core.IsStarted) + { + ForceUpdateOverlays(); + } + } + } + + /// + /// current position in pixel coordinates + /// + [Browsable(false)] + public GPoint PositionPixel + { + get + { + return Core.PositionPixel; + } + } + + /// + /// location of cache + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public string CacheLocation + { + get + { +#if !DESIGN + return CacheLocator.Location; +#else + return string.Empty; +#endif + } + set + { +#if !DESIGN + CacheLocator.Location = value; +#endif + } + } + + bool isDragging = false; + + /// + /// is user dragging map + /// + [Browsable(false)] + public bool IsDragging + { + get + { + return isDragging; + } + } + + bool isMouseOverMarker; + internal int overObjectCount = 0; + + /// + /// is mouse over marker + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public bool IsMouseOverMarker + { + get + { + return isMouseOverMarker; + } + internal set + { + isMouseOverMarker = value; + overObjectCount += value ? 1 : -1; + } + } + + bool isMouseOverRoute; + + /// + /// is mouse over route + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public bool IsMouseOverRoute + { + get + { + return isMouseOverRoute; + } + internal set + { + isMouseOverRoute = value; + overObjectCount += value ? 1 : -1; + } + } + + bool isMouseOverPolygon; + + /// + /// is mouse over polygon + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public bool IsMouseOverPolygon + { + get + { + return isMouseOverPolygon; + } + internal set + { + isMouseOverPolygon = value; + overObjectCount += value ? 1 : -1; + } + } + + /// + /// gets current map view top/left coordinate, width in Lng, height in Lat + /// + [Browsable(false)] + public RectLatLng ViewArea + { + get + { + if (!IsRotated) + { + return Core.ViewArea; + } + else if (Core.Provider.Projection != null) + { + var p = FromLocalToLatLng(0, 0); + var p2 = FromLocalToLatLng(Allocation.Width, Allocation.Height); + + return RectLatLng.FromLTRB(p.Lng, p.Lat, p2.Lng, p2.Lat); + } + return RectLatLng.Empty; + } + } + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public GMapProvider MapProvider + { + get + { + return Core.Provider; + } + set + { + if (Core.Provider == null || !Core.Provider.Equals(value)) + { + Debug.WriteLine("MapType: " + Core.Provider.Name + " -> " + value.Name); + + RectLatLng viewarea = SelectedArea; + if (viewarea != RectLatLng.Empty) + { + Position = new PointLatLng(viewarea.Lat - viewarea.HeightLat / 2, viewarea.Lng + viewarea.WidthLng / 2); + } + else + { + viewarea = ViewArea; + } + + Core.Provider = value; + + if (Core.IsStarted) + { + if (Core.ZoomToArea) + { + // restore zoomrect as close as possible + if (viewarea != RectLatLng.Empty && viewarea != ViewArea) + { + int bestZoom = Core.GetMaxZoomToFitRect(viewarea); + if (bestZoom > 0 && Zoom != bestZoom) + { + Zoom = bestZoom; + } + } + } + else + { + ForceUpdateOverlays(); + } + } + } + } + } + + /// + /// is routes enabled + /// + [Category("GMap.NET")] + public bool RoutesEnabled + { + get + { + return Core.RoutesEnabled; + } + set + { + Core.RoutesEnabled = value; + } + } + + /// + /// is polygons enabled + /// + [Category("GMap.NET")] + public bool PolygonsEnabled + { + get + { + return Core.PolygonsEnabled; + } + set + { + Core.PolygonsEnabled = value; + } + } + + /// + /// is markers enabled + /// + [Category("GMap.NET")] + public bool MarkersEnabled + { + get + { + return Core.MarkersEnabled; + } + set + { + Core.MarkersEnabled = value; + } + } + + /// + /// can user drag map + /// + [Category("GMap.NET")] + public bool CanDragMap + { + get + { + return Core.CanDragMap; + } + set + { + Core.CanDragMap = value; + } + } + + /// + /// map render mode + /// + [Browsable(false)] + public RenderMode RenderMode + { + get + { + return Core.RenderMode; + } + internal set + { + Core.RenderMode = value; + } + } + + /// + /// gets map manager + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [Browsable(false)] + public GMaps Manager + { + get + { + return GMaps.Instance; + } + } + +#endregion + +#region IGControl event Members + + /// + /// occurs when current position is changed + /// + public event PositionChanged OnPositionChanged + { + add + { + Core.OnCurrentPositionChanged += value; + } + remove + { + Core.OnCurrentPositionChanged -= value; + } + } + + /// + /// occurs when tile set load is complete + /// + public event TileLoadComplete OnTileLoadComplete + { + add + { + Core.OnTileLoadComplete += value; + } + remove + { + Core.OnTileLoadComplete -= value; + } + } + + /// + /// occurs when tile set is starting to load + /// + public event TileLoadStart OnTileLoadStart + { + add + { + Core.OnTileLoadStart += value; + } + remove + { + Core.OnTileLoadStart -= value; + } + } + + /// + /// occurs on map drag + /// + public event MapDrag OnMapDrag + { + add + { + Core.OnMapDrag += value; + } + remove + { + Core.OnMapDrag -= value; + } + } + + /// + /// occurs on map zoom changed + /// + public event MapZoomChanged OnMapZoomChanged + { + add + { + Core.OnMapZoomChanged += value; + } + remove + { + Core.OnMapZoomChanged -= value; + } + } + + /// + /// occures on map type changed + /// + public event MapTypeChanged OnMapTypeChanged + { + add + { + Core.OnMapTypeChanged += value; + } + remove + { + Core.OnMapTypeChanged -= value; + } + } + + /// + /// occurs on empty tile displayed + /// + public event EmptyTileError OnEmptyTileError + { + add + { + Core.OnEmptyTileError += value; + } + remove + { + Core.OnEmptyTileError -= value; + } + } + +#endregion + +#region Serialization + + static readonly BinaryFormatter BinaryFormatter = new BinaryFormatter(); + + /// + /// Serializes the overlays. + /// + /// The stream. + public void SerializeOverlays(Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + // Create an array from the overlays + GMapOverlay[] overlayArray = new GMapOverlay[this.Overlays.Count]; + this.Overlays.CopyTo(overlayArray, 0); + + // Serialize the overlays + BinaryFormatter.Serialize(stream, overlayArray); + } + + /// + /// De-serializes the overlays. + /// + /// The stream. + public void DeserializeOverlays(Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + // De-serialize the overlays + GMapOverlay[] overlayArray = BinaryFormatter.Deserialize(stream) as GMapOverlay[]; + + // Populate the collection of overlays. + foreach (GMapOverlay overlay in overlayArray) + { + overlay.Control = this; + this.Overlays.Add(overlay); + } + + this.ForceUpdateOverlays(); + } + +#endregion + } + + public enum ScaleModes + { + /// + /// no scaling + /// + Integer, + + /// + /// scales to fractional level, CURRENT VERSION DOESN'T HANDLE OBJECT POSITIONS CORRECLTY, + /// http://greatmaps.codeplex.com/workitem/16046 + /// + Fractional, + } + + public enum HelperLineOptions + { + DontShow = 0, + ShowAlways = 1, + ShowOnModifierKey = 2 + } + + public delegate void SelectionChange(RectLatLng Selection, bool ZoomToFit); +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapImage.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapImage.cs new file mode 100644 index 00000000..2191146f --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapImage.cs @@ -0,0 +1,146 @@ + +namespace GMap.NET.GtkSharp +{ + using System.Drawing; + using System.IO; + using System.Drawing.Imaging; + using System; + using System.Diagnostics; + using GMap.NET.Internals; + using GMap.NET.MapProviders; + + /// + /// image abstraction + /// + public class GMapImage : PureImage + { + public System.Drawing.Image Img; + + public override void Dispose() + { + if(Img != null) + { + Img.Dispose(); + Img = null; + } + + if(Data != null) + { + Data.Dispose(); + Data = null; + } + } + } + + /// + /// image abstraction proxy + /// + public class GMapImageProxy : PureImageProxy + { + GMapImageProxy() + { + + } + + public static void Enable() + { + GMapProvider.TileImageProxy = Instance; + } + + public static readonly GMapImageProxy Instance = new GMapImageProxy(); + +#if !PocketPC + internal ColorMatrix ColorMatrix; +#endif + + static readonly bool Win7OrLater = Stuff.IsRunningOnWin7orLater(); + + public override PureImage FromStream(Stream stream) + { + GMapImage ret = null; + try + { +#if !PocketPC + Image m = Image.FromStream(stream, true, Win7OrLater ? false : true); +#else + Image m = new Bitmap(stream); +#endif + if(m != null) + { + ret = new GMapImage(); +#if !PocketPC + ret.Img = ColorMatrix != null ? ApplyColorMatrix(m, ColorMatrix) : m; +#else + ret.Img = m; +#endif + } + + } + catch(Exception ex) + { + ret = null; + Debug.WriteLine("FromStream: " + ex.ToString()); + } + + return ret; + } + + public override bool Save(Stream stream, GMap.NET.PureImage image) + { + GMapImage ret = image as GMapImage; + bool ok = true; + + if(ret.Img != null) + { + // try png + try + { + ret.Img.Save(stream, System.Drawing.Imaging.ImageFormat.Png); + } + catch + { + // try jpeg + try + { + stream.Seek(0, SeekOrigin.Begin); + ret.Img.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); + } + catch + { + ok = false; + } + } + } + else + { + ok = false; + } + + return ok; + } + +#if !PocketPC + Bitmap ApplyColorMatrix(Image original, ColorMatrix matrix) + { + // create a blank bitmap the same size as original + Bitmap newBitmap = new Bitmap(original.Width, original.Height); + + using(original) // destroy original + { + // get a graphics object from the new image + using(Graphics g = Graphics.FromImage(newBitmap)) + { + // set the color matrix attribute + using(ImageAttributes attributes = new ImageAttributes()) + { + attributes.SetColorMatrix(matrix); + g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height), 0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes); + } + } + } + + return newBitmap; + } +#endif + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapMarker.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapMarker.cs new file mode 100644 index 00000000..870da577 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapMarker.cs @@ -0,0 +1,336 @@ + +namespace GMap.NET.GtkSharp +{ + using System; + using System.Drawing; + using System.Runtime.Serialization; + using GMap.NET.GtkSharp.ToolTips; + + /// + /// GMap.NET marker + /// + [Serializable] + public abstract class GMapMarker : ISerializable, IDisposable + { + GMapOverlay overlay; + public GMapOverlay Overlay + { + get + { + return overlay; + } + internal set + { + overlay = value; + } + } + + private PointLatLng position; + public PointLatLng Position + { + get + { + return position; + } + set + { + if(position != value) + { + position = value; + + if(IsVisible) + { + if(Overlay != null && Overlay.Control != null) + { + Overlay.Control.UpdateMarkerLocalPosition(this); + } + } + } + } + } + + public object Tag; + + Point offset; + public Point Offset + { + get + { + return offset; + } + set + { + if(offset != value) + { + offset = value; + + if(IsVisible) + { + if(Overlay != null && Overlay.Control != null) + { + Overlay.Control.UpdateMarkerLocalPosition(this); + } + } + } + } + } + + Rectangle area; + + /// + /// marker position in local coordinates, internal only, do not set it manualy + /// + public Point LocalPosition + { + get + { + return area.Location; + } + set + { + if(area.Location != value) + { + area.Location = value; + { + if(Overlay != null && Overlay.Control != null) + { + if(!Overlay.Control.HoldInvalidation) + { + Overlay.Control.Invalidate(); + } + } + } + } + } + } + + /// + /// ToolTip position in local coordinates + /// + public Point ToolTipPosition + { + get + { + Point ret = area.Location; + ret.Offset(-Offset.X, -Offset.Y); + return ret; + } + } + + public Size Size + { + get + { + return area.Size; + } + set + { + area.Size = value; + } + } + + public Rectangle LocalArea + { + get + { + return area; + } + } + + public GMapToolTip ToolTip; + + public MarkerTooltipMode ToolTipMode = MarkerTooltipMode.OnMouseOver; + + string toolTipText; + public string ToolTipText + { + get + { + return toolTipText; + } + + set + { + if(ToolTip == null && !string.IsNullOrEmpty(value)) + { + ToolTip = new GMapRoundedToolTip(this); + } + toolTipText = value; + } + } + + private bool visible = true; + + /// + /// is marker visible + /// + public bool IsVisible + { + get + { + return visible; + } + set + { + if(value != visible) + { + visible = value; + + if(Overlay != null && Overlay.Control != null) + { + if(visible) + { + Overlay.Control.UpdateMarkerLocalPosition(this); + } + else + { + if (Overlay.Control.IsMouseOverMarker) + { + Overlay.Control.IsMouseOverMarker = false; + Overlay.Control.RestoreCursorOnLeave(); + } + } + + { + if(!Overlay.Control.HoldInvalidation) + { + Overlay.Control.Invalidate(); + } + } + } + } + } + } + + /// + /// if true, marker will be rendered even if it's outside current view + /// + public bool DisableRegionCheck = false; + + /// + /// can maker receive input + /// + public bool IsHitTestVisible = true; + + private bool isMouseOver = false; + + /// + /// is mouse over marker + /// + public bool IsMouseOver + { + get + { + return isMouseOver; + } + internal set + { + isMouseOver = value; + } + } + + public GMapMarker(PointLatLng pos) + { + this.Position = pos; + } + + public virtual void OnRender(Graphics g) + { + // + } + +#if PocketPC + protected void DrawImageUnscaled(Graphics g, Bitmap inBmp, int x, int y) + { + g.DrawImage(inBmp, new Rectangle(x, y, inBmp.Width, inBmp.Height), 0, 0, inBmp.Width, inBmp.Height, GraphicsUnit.Pixel, attr); + } +#endif + +#if !PocketPC + #region ISerializable Members + + /// + /// Populates a with the data needed to serialize the target object. + /// + /// The to populate with data. + /// The destination (see ) for this serialization. + /// + /// The caller does not have the required permission. + /// + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Position", this.Position); + info.AddValue("Tag", this.Tag); + info.AddValue("Offset", this.Offset); + info.AddValue("Area", this.area); + info.AddValue("ToolTip", this.ToolTip); + info.AddValue("ToolTipMode", this.ToolTipMode); + info.AddValue("ToolTipText", this.ToolTipText); + info.AddValue("Visible", this.IsVisible); + info.AddValue("DisableregionCheck", this.DisableRegionCheck); + info.AddValue("IsHitTestVisible", this.IsHitTestVisible); + } + + /// + /// Initializes a new instance of the class. + /// + /// The info. + /// The context. + protected GMapMarker(SerializationInfo info, StreamingContext context) + { + this.Position = Extensions.GetStruct(info, "Position", PointLatLng.Empty); + this.Tag = Extensions.GetValue(info, "Tag", null); + this.Offset = Extensions.GetStruct(info, "Offset", Point.Empty); + this.area = Extensions.GetStruct(info, "Area", Rectangle.Empty); + + this.ToolTip = Extensions.GetValue(info, "ToolTip", null); + if (this.ToolTip != null) this.ToolTip.Marker = this; + + this.ToolTipMode = Extensions.GetStruct(info, "ToolTipMode", MarkerTooltipMode.OnMouseOver); + this.ToolTipText = info.GetString("ToolTipText"); + this.IsVisible = info.GetBoolean("Visible"); + this.DisableRegionCheck = info.GetBoolean("DisableregionCheck"); + this.IsHitTestVisible = info.GetBoolean("IsHitTestVisible"); + } + + #endregion +#endif + + #region IDisposable Members + + bool disposed = false; + + public virtual void Dispose() + { + if(!disposed) + { + disposed = true; + + Tag = null; + + if(ToolTip != null) + { + toolTipText = null; + ToolTip.Dispose(); + ToolTip = null; + } + } + } + + #endregion + } + + //public delegate void MarkerClick(GMapMarker item, MouseEventArgs e); + public delegate void MarkerEnter(GMapMarker item); + public delegate void MarkerLeave(GMapMarker item); + + /// + /// modeof tooltip + /// + public enum MarkerTooltipMode + { + OnMouseOver, + Never, + Always, + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapOverlay.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapOverlay.cs new file mode 100644 index 00000000..50e20f15 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapOverlay.cs @@ -0,0 +1,462 @@ + +namespace GMap.NET.GtkSharp +{ + using System; + using System.Drawing; + using System.Runtime.Serialization; + using System.Windows.Forms; + using GMap.NET.ObjectModel; + + /// + /// GMap.NET overlay + /// + [Serializable] +#if !PocketPC + public class GMapOverlay : ISerializable, IDeserializationCallback, IDisposable +#else + public class GMapOverlay: IDisposable +#endif + { + bool isVisibile = true; + + /// + /// is overlay visible + /// + public bool IsVisibile + { + get + { + return isVisibile; + } + set + { + if(value != isVisibile) + { + isVisibile = value; + + if(Control != null) + { + if(isVisibile) + { + Control.HoldInvalidation = true; + { + ForceUpdate(); + } + Control.Refresh(); + } + else + { + if (Control.IsMouseOverMarker) + { + Control.IsMouseOverMarker = false; + } + + if (Control.IsMouseOverPolygon) + { + Control.IsMouseOverPolygon = false; + } + + if (Control.IsMouseOverRoute) + { + Control.IsMouseOverRoute = false; + } +#if !PocketPC + Control.RestoreCursorOnLeave(); +#endif + + if(!Control.HoldInvalidation) + { + Control.Invalidate(); + } + } + } + } + } + } + + /// + /// overlay Id + /// + public string Id; + + /// + /// list of markers, should be thread safe + /// + public readonly ObservableCollectionThreadSafe Markers = new ObservableCollectionThreadSafe(); + + /// + /// list of routes, should be thread safe + /// + public readonly ObservableCollectionThreadSafe Routes = new ObservableCollectionThreadSafe(); + + /// + /// list of polygons, should be thread safe + /// + public readonly ObservableCollectionThreadSafe Polygons = new ObservableCollectionThreadSafe(); + + GMapControl control; + public GMapControl Control + { + get + { + return control; + } + internal set + { + control = value; + } + } + + public GMapOverlay() + { + CreateEvents(); + } + + public GMapOverlay(string id) + { + Id = id; + CreateEvents(); + } + + void CreateEvents() + { + Markers.CollectionChanged += new NotifyCollectionChangedEventHandler(Markers_CollectionChanged); + Routes.CollectionChanged += new NotifyCollectionChangedEventHandler(Routes_CollectionChanged); + Polygons.CollectionChanged += new NotifyCollectionChangedEventHandler(Polygons_CollectionChanged); + } + + void ClearEvents() + { + Markers.CollectionChanged -= new NotifyCollectionChangedEventHandler(Markers_CollectionChanged); + Routes.CollectionChanged -= new NotifyCollectionChangedEventHandler(Routes_CollectionChanged); + Polygons.CollectionChanged -= new NotifyCollectionChangedEventHandler(Polygons_CollectionChanged); + } + + public void Clear() + { + Markers.Clear(); + Routes.Clear(); + Polygons.Clear(); + } + + void Polygons_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if(e.NewItems != null) + { + foreach(GMapPolygon obj in e.NewItems) + { + if(obj != null) + { + obj.Overlay = this; + if(Control != null) + { + Control.UpdatePolygonLocalPosition(obj); + } + } + } + } + + if(Control != null) + { + if(e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Reset) + { + if(Control.IsMouseOverPolygon) + { + Control.IsMouseOverPolygon = false; +#if !PocketPC + Control.RestoreCursorOnLeave(); +#endif + } + } + + if(!Control.HoldInvalidation) + { + Control.Invalidate(); + } + } + } + + void Routes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if(e.NewItems != null) + { + foreach(GMapRoute obj in e.NewItems) + { + if(obj != null) + { + obj.Overlay = this; + if(Control != null) + { + Control.UpdateRouteLocalPosition(obj); + } + } + } + } + + if(Control != null) + { + if(e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Reset) + { + if(Control.IsMouseOverRoute) + { + Control.IsMouseOverRoute = false; +#if !PocketPC + Control.RestoreCursorOnLeave(); +#endif + } + } + + if(!Control.HoldInvalidation) + { + Control.Invalidate(); + } + } + } + + void Markers_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if(e.NewItems != null) + { + foreach(GMapMarker obj in e.NewItems) + { + if(obj != null) + { + obj.Overlay = this; + if(Control != null) + { + Control.UpdateMarkerLocalPosition(obj); + } + } + } + } + + if(Control != null) + { + if(e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Reset) + { + if(Control.IsMouseOverMarker) + { + Control.IsMouseOverMarker = false; +#if !PocketPC + Control.RestoreCursorOnLeave(); +#endif + } + } + + if(!Control.HoldInvalidation) + { + Control.Invalidate(); + } + } + } + + /// + /// updates local positions of objects + /// + internal void ForceUpdate() + { + if(Control != null) + { + foreach(GMapMarker obj in Markers) + { + if(obj.IsVisible) + { + Control.UpdateMarkerLocalPosition(obj); + } + } + + foreach(GMapPolygon obj in Polygons) + { + if(obj.IsVisible) + { + Control.UpdatePolygonLocalPosition(obj); + } + } + + foreach(GMapRoute obj in Routes) + { + if(obj.IsVisible) + { + Control.UpdateRouteLocalPosition(obj); + } + } + } + } + + /// + /// renders objects/routes/polygons + /// + /// + public virtual void OnRender(Graphics g) + { + if(Control != null) + { + if(Control.RoutesEnabled) + { + foreach(GMapRoute r in Routes) + { + if(r.IsVisible) + { + r.OnRender(g); + } + } + } + + if(Control.PolygonsEnabled) + { + foreach(GMapPolygon r in Polygons) + { + if(r.IsVisible) + { + r.OnRender(g); + } + } + } + + if(Control.MarkersEnabled) + { + // markers + foreach(GMapMarker m in Markers) + { + //if(m.IsVisible && (m.DisableRegionCheck || Control.Core.currentRegion.Contains(m.LocalPosition.X, m.LocalPosition.Y))) + if(m.IsVisible || m.DisableRegionCheck) + { + m.OnRender(g); + } + } + + // tooltips above + foreach(GMapMarker m in Markers) + { + //if(m.ToolTip != null && m.IsVisible && Control.Core.currentRegion.Contains(m.LocalPosition.X, m.LocalPosition.Y)) + if(m.ToolTip != null && m.IsVisible) + { + if(!string.IsNullOrEmpty(m.ToolTipText) && (m.ToolTipMode == MarkerTooltipMode.Always || (m.ToolTipMode == MarkerTooltipMode.OnMouseOver && m.IsMouseOver))) + { + m.ToolTip.OnRender(g); + } + } + } + } + } + } + +#if !PocketPC + #region ISerializable Members + + /// + /// Populates a with the data needed to serialize the target object. + /// + /// The to populate with data. + /// The destination (see ) for this serialization. + /// + /// The caller does not have the required permission. + /// + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Id", this.Id); + info.AddValue("IsVisible", this.IsVisibile); + + GMapMarker[] markerArray = new GMapMarker[this.Markers.Count]; + this.Markers.CopyTo(markerArray, 0); + info.AddValue("Markers", markerArray); + + GMapRoute[] routeArray = new GMapRoute[this.Routes.Count]; + this.Routes.CopyTo(routeArray, 0); + info.AddValue("Routes", routeArray); + + GMapPolygon[] polygonArray = new GMapPolygon[this.Polygons.Count]; + this.Polygons.CopyTo(polygonArray, 0); + info.AddValue("Polygons", polygonArray); + } + + private GMapMarker[] deserializedMarkerArray; + private GMapRoute[] deserializedRouteArray; + private GMapPolygon[] deserializedPolygonArray; + + /// + /// Initializes a new instance of the class. + /// + /// The info. + /// The context. + protected GMapOverlay(SerializationInfo info, StreamingContext context) + { + this.Id = info.GetString("Id"); + this.IsVisibile = info.GetBoolean("IsVisible"); + + this.deserializedMarkerArray = Extensions.GetValue(info, "Markers", new GMapMarker[0]); + this.deserializedRouteArray = Extensions.GetValue(info, "Routes", new GMapRoute[0]); + this.deserializedPolygonArray = Extensions.GetValue(info, "Polygons", new GMapPolygon[0]); + + CreateEvents(); + } + + #endregion + + #region IDeserializationCallback Members + + /// + /// Runs when the entire object graph has been deserialized. + /// + /// The object that initiated the callback. The functionality for this parameter is not currently implemented. + public void OnDeserialization(object sender) + { + // Populate Markers + foreach(GMapMarker marker in deserializedMarkerArray) + { + marker.Overlay = this; + this.Markers.Add(marker); + } + + // Populate Routes + foreach(GMapRoute route in deserializedRouteArray) + { + route.Overlay = this; + this.Routes.Add(route); + } + + // Populate Polygons + foreach(GMapPolygon polygon in deserializedPolygonArray) + { + polygon.Overlay = this; + this.Polygons.Add(polygon); + } + } + + #endregion +#endif + + #region IDisposable Members + + bool disposed = false; + + public void Dispose() + { + if(!disposed) + { + disposed = true; + + ClearEvents(); + + foreach(var m in Markers) + { + m.Dispose(); + } + + foreach(var r in Routes) + { + r.Dispose(); + } + + foreach(var p in Polygons) + { + p.Dispose(); + } + + Clear(); + } + } + + #endregion + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapPolygon.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapPolygon.cs new file mode 100644 index 00000000..b142655c --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapPolygon.cs @@ -0,0 +1,309 @@ + +namespace GMap.NET.GtkSharp +{ + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Drawing2D; + using System.Runtime.Serialization; + using GMap.NET; + using System; + + /// + /// GMap.NET polygon + /// + [System.Serializable] + public class GMapPolygon : MapRoute, ISerializable, IDeserializationCallback, IDisposable + { + private bool visible = true; + + /// + /// is polygon visible + /// + public bool IsVisible + { + get + { + return visible; + } + set + { + if(value != visible) + { + visible = value; + + if(Overlay != null && Overlay.Control != null) + { + if(visible) + { + Overlay.Control.UpdatePolygonLocalPosition(this); + } + else + { + if (Overlay.Control.IsMouseOverPolygon) + { + Overlay.Control.IsMouseOverPolygon = false; + Overlay.Control.RestoreCursorOnLeave(); + } + } + + { + if(!Overlay.Control.HoldInvalidation) + { + Overlay.Control.Invalidate(); + } + } + } + } + } + } + + /// + /// can receive input + /// + public bool IsHitTestVisible = false; + + private bool isMouseOver = false; + + /// + /// is mouse over + /// + public bool IsMouseOver + { + get + { + return isMouseOver; + } + internal set + { + isMouseOver = value; + } + } + + GMapOverlay overlay; + public GMapOverlay Overlay + { + get + { + return overlay; + } + internal set + { + overlay = value; + } + } + + /// + /// Indicates whether the specified point is contained within this System.Drawing.Drawing2D.GraphicsPath + /// + /// + /// + /// + internal bool IsInsideLocal(int x, int y) + { + if (graphicsPath != null) + { + return graphicsPath.IsVisible(x, y); + } + + return false; + } + + GraphicsPath graphicsPath; + internal void UpdateGraphicsPath() + { + if (graphicsPath == null) + { + graphicsPath = new GraphicsPath(); + } + else + { + graphicsPath.Reset(); + } + + { + Point[] pnts = new Point[LocalPoints.Count]; + for (int i = 0; i < LocalPoints.Count; i++) + { + Point p2 = new Point((int)LocalPoints[i].X, (int)LocalPoints[i].Y); + pnts[pnts.Length - 1 - i] = p2; + } + + if (pnts.Length > 2) + { + graphicsPath.AddPolygon(pnts); + } + else if (pnts.Length == 2) + { + graphicsPath.AddLines(pnts); + } + } + } + + + public virtual void OnRender(Graphics g) + { + if(IsVisible) + { + if (IsVisible) + { + if (graphicsPath != null) + { + g.FillPath(Fill, graphicsPath); + g.DrawPath(Stroke, graphicsPath); + } + } + } + } + + //public double Area + //{ + // get + // { + // return 0; + // } + //} + + public static readonly Pen DefaultStroke = new Pen(Color.FromArgb(155, Color.MidnightBlue)); + + /// + /// specifies how the outline is painted + /// + [NonSerialized] + public Pen Stroke = DefaultStroke; + + public static readonly Brush DefaultFill = new SolidBrush(Color.FromArgb(155, Color.AliceBlue)); + + /// + /// background color + /// + [NonSerialized] + public Brush Fill = DefaultFill; + + public readonly List LocalPoints = new List(); + + static GMapPolygon() + { + DefaultStroke.LineJoin = LineJoin.Round; + DefaultStroke.Width = 5; + } + + public GMapPolygon(List points, string name) + : base(points, name) + { + LocalPoints.Capacity = Points.Count; + } + + /// + /// checks if point is inside the polygon, + /// info.: http://greatmaps.codeplex.com/discussions/279437#post700449 + /// + /// + /// + public bool IsInside(PointLatLng p) + { + int count = Points.Count; + + if(count < 3) + { + return false; + } + + bool result = false; + + for(int i = 0, j = count - 1; i < count; i++) + { + var p1 = Points[i]; + var p2 = Points[j]; + + if(p1.Lat < p.Lat && p2.Lat >= p.Lat || p2.Lat < p.Lat && p1.Lat >= p.Lat) + { + if(p1.Lng + (p.Lat - p1.Lat) / (p2.Lat - p1.Lat) * (p2.Lng - p1.Lng) < p.Lng) + { + result = !result; + } + } + j = i; + } + return result; + } + + #region ISerializable Members + + /// + /// Populates a with the data needed to serialize the target object. + /// + /// The to populate with data. + /// The destination (see ) for this serialization. + /// + /// The caller does not have the required permission. + /// + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + + info.AddValue("LocalPoints", this.LocalPoints.ToArray()); + info.AddValue("Visible", this.IsVisible); + } + + // Temp store for de-serialization. + private GPoint[] deserializedLocalPoints; + + /// + /// Initializes a new instance of the class. + /// + /// The info. + /// The context. + protected GMapPolygon(SerializationInfo info, StreamingContext context) + : base(info, context) + { + this.deserializedLocalPoints = Extensions.GetValue(info, "LocalPoints"); + this.IsVisible = Extensions.GetStruct(info, "Visible", true); + } + + #endregion + + #region IDeserializationCallback Members + + /// + /// Runs when the entire object graph has been de-serialized. + /// + /// The object that initiated the callback. The functionality for this parameter is not currently implemented. + public override void OnDeserialization(object sender) + { + base.OnDeserialization(sender); + + // Accounts for the de-serialization being breadth first rather than depth first. + LocalPoints.AddRange(deserializedLocalPoints); + LocalPoints.Capacity = Points.Count; + } + + #endregion + + #region IDisposable Members + + bool disposed = false; + + public virtual void Dispose() + { + if(!disposed) + { + disposed = true; + + LocalPoints.Clear(); + + if (graphicsPath != null) + { + graphicsPath.Dispose(); + graphicsPath = null; + } + base.Clear(); + } + } + + #endregion + } + + //public delegate void PolygonClick(GMapPolygon item, MouseEventArgs e); + public delegate void PolygonEnter(GMapPolygon item); + public delegate void PolygonLeave(GMapPolygon item); +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapRoute.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapRoute.cs new file mode 100644 index 00000000..39a64ede --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapRoute.cs @@ -0,0 +1,261 @@ + +namespace GMap.NET.GtkSharp +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Drawing2D; + using System.Runtime.Serialization; + using System.Windows.Forms; + using GMap.NET; + + /// + /// GMap.NET route + /// + [Serializable] + public class GMapRoute : MapRoute, ISerializable, IDeserializationCallback, IDisposable + { + GMapOverlay overlay; + public GMapOverlay Overlay + { + get + { + return overlay; + } + internal set + { + overlay = value; + } + } + + private bool visible = true; + + /// + /// is marker visible + /// + public bool IsVisible + { + get + { + return visible; + } + set + { + if (value != visible) + { + visible = value; + + if (Overlay != null && Overlay.Control != null) + { + if (visible) + { + Overlay.Control.UpdateRouteLocalPosition(this); + } + else + { + if (Overlay.Control.IsMouseOverRoute) + { + Overlay.Control.IsMouseOverRoute = false; + Overlay.Control.RestoreCursorOnLeave(); + } + } + + { + if (!Overlay.Control.HoldInvalidation) + { + Overlay.Control.Invalidate(); + } + } + } + } + } + } + + /// + /// can receive input + /// + public bool IsHitTestVisible = false; + + private bool isMouseOver = false; + + /// + /// is mouse over + /// + public bool IsMouseOver + { + get + { + return isMouseOver; + } + internal set + { + isMouseOver = value; + } + } + + /// + /// Indicates whether the specified point is contained within this System.Drawing.Drawing2D.GraphicsPath + /// + /// + /// + /// + internal bool IsInside(int x, int y) + { + if (graphicsPath != null) + { + return graphicsPath.IsOutlineVisible(x, y, Stroke); + } + + return false; + } + + GraphicsPath graphicsPath; + internal void UpdateGraphicsPath() + { + if(graphicsPath == null) + { + graphicsPath = new GraphicsPath(); + } + else + { + graphicsPath.Reset(); + } + + { + for(int i = 0; i < LocalPoints.Count; i++) + { + GPoint p2 = LocalPoints[i]; + + if(i == 0) + { + graphicsPath.AddLine(p2.X, p2.Y, p2.X, p2.Y); + } + else + { + System.Drawing.PointF p = graphicsPath.GetLastPoint(); + graphicsPath.AddLine(p.X, p.Y, p2.X, p2.Y); + } + } + } + } + + public virtual void OnRender(Graphics g) + { + if(IsVisible) + { + if(graphicsPath != null) + { + g.DrawPath(Stroke, graphicsPath); + } + } + } + + public static readonly Pen DefaultStroke = new Pen(Color.FromArgb(144, Color.MidnightBlue)); + + /// + /// specifies how the outline is painted + /// + [NonSerialized] + public Pen Stroke = DefaultStroke; + + public readonly List LocalPoints = new List(); + + static GMapRoute() + { + DefaultStroke.LineJoin = LineJoin.Round; + DefaultStroke.Width = 5; + } + + public GMapRoute(string name) + : base(name) + { + + } + + public GMapRoute(IEnumerable points, string name) + : base(points, name) + { + + } + + #region ISerializable Members + + // Temp store for de-serialization. + private GPoint[] deserializedLocalPoints; + + /// + /// Populates a with the data needed to serialize the target object. + /// + /// The to populate with data. + /// The destination (see ) for this serialization. + /// + /// The caller does not have the required permission. + /// + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + + info.AddValue("Visible", this.IsVisible); + info.AddValue("LocalPoints", this.LocalPoints.ToArray()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The info. + /// The context. + protected GMapRoute(SerializationInfo info, StreamingContext context) + : base(info, context) + { + //this.Stroke = Extensions.GetValue(info, "Stroke", new Pen(Color.FromArgb(144, Color.MidnightBlue))); + this.IsVisible = Extensions.GetStruct(info, "Visible", true); + this.deserializedLocalPoints = Extensions.GetValue(info, "LocalPoints"); + } + + #endregion + + #region IDeserializationCallback Members + + /// + /// Runs when the entire object graph has been de-serialized. + /// + /// The object that initiated the callback. The functionality for this parameter is not currently implemented. + public override void OnDeserialization(object sender) + { + base.OnDeserialization(sender); + + // Accounts for the de-serialization being breadth first rather than depth first. + LocalPoints.AddRange(deserializedLocalPoints); + LocalPoints.Capacity = Points.Count; + } + + #endregion + + #region IDisposable Members + + bool disposed = false; + + public virtual void Dispose() + { + if (!disposed) + { + disposed = true; + + LocalPoints.Clear(); + + if (graphicsPath != null) + { + graphicsPath.Dispose(); + graphicsPath = null; + } + base.Clear(); + } + } + + #endregion + } + + //public delegate void RouteClick(GMapRoute item, MouseEventArgs e); + public delegate void RouteEnter(GMapRoute item); + public delegate void RouteLeave(GMapRoute item); +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapToolTip.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapToolTip.cs new file mode 100644 index 00000000..7786445d --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapToolTip.cs @@ -0,0 +1,177 @@ + +namespace GMap.NET.GtkSharp +{ + using System; + using System.Drawing; + using System.Drawing.Drawing2D; + using System.Runtime.Serialization; +using System.Collections; + using System.Collections.Generic; + + /// + /// GMap.NET marker + /// + [Serializable] +#if !PocketPC + public class GMapToolTip : ISerializable, IDisposable +#else + public class GMapToolTip: IDisposable +#endif + { + GMapMarker marker; + public GMapMarker Marker + { + get + { + return marker; + } + internal set + { + marker = value; + } + } + + public Point Offset; + + public static readonly StringFormat DefaultFormat = new StringFormat(); + + /// + /// string format + /// + [NonSerialized] + public readonly StringFormat Format = DefaultFormat; + +#if !PocketPC + public static readonly Font DefaultFont = new Font(FontFamily.GenericSansSerif, 14, FontStyle.Bold, GraphicsUnit.Pixel); +#else + public static readonly Font DefaultFont = new Font(FontFamily.GenericSansSerif, 6, FontStyle.Bold); +#endif + + /// + /// font + /// + [NonSerialized] + public Font Font = DefaultFont; + +#if !PocketPC + public static readonly Pen DefaultStroke = new Pen(Color.FromArgb(140, Color.MidnightBlue)); +#else + public static readonly Pen DefaultStroke = new Pen(Color.MidnightBlue); +#endif + + /// + /// specifies how the outline is painted + /// + [NonSerialized] + public Pen Stroke = DefaultStroke; + +#if !PocketPC + public static readonly Brush DefaultFill = new SolidBrush(Color.FromArgb(222, Color.AliceBlue)); +#else + public static readonly Brush DefaultFill = new System.Drawing.SolidBrush(Color.AliceBlue); +#endif + + /// + /// background color + /// + [NonSerialized] + public Brush Fill = DefaultFill; + + public static readonly Brush DefaultForeground = new SolidBrush(Color.Navy); + + /// + /// text foreground + /// + [NonSerialized] + public Brush Foreground = DefaultForeground; + + /// + /// text padding + /// + public Size TextPadding = new Size(10, 10); + + static GMapToolTip() + { + DefaultStroke.Width = 2; + +#if !PocketPC + DefaultStroke.LineJoin = LineJoin.Round; + DefaultStroke.StartCap = LineCap.RoundAnchor; +#endif + +#if !PocketPC + DefaultFormat.LineAlignment = StringAlignment.Center; +#endif + DefaultFormat.Alignment = StringAlignment.Center; + } + + public GMapToolTip(GMapMarker marker) + { + this.Marker = marker; + this.Offset = new Point(14, -44); + } + + public virtual void OnRender(Graphics g) + { + System.Drawing.Size st = g.MeasureString(Marker.ToolTipText, Font).ToSize(); + System.Drawing.Rectangle rect = new System.Drawing.Rectangle(Marker.ToolTipPosition.X, Marker.ToolTipPosition.Y - st.Height, st.Width + TextPadding.Width, st.Height + TextPadding.Height); + rect.Offset(Offset.X, Offset.Y); + + g.DrawLine(Stroke, Marker.ToolTipPosition.X, Marker.ToolTipPosition.Y, rect.X, rect.Y + rect.Height / 2); + + g.FillRectangle(Fill, rect); + g.DrawRectangle(Stroke, rect); + +#if PocketPC + rect.Offset(0, (rect.Height - st.Height) / 2); +#endif + + g.DrawString(Marker.ToolTipText, Font, Foreground, rect, Format); + } + +#if !PocketPC + #region ISerializable Members + + /// + /// Initializes a new instance of the class. + /// + /// The info. + /// The context. + protected GMapToolTip(SerializationInfo info, StreamingContext context) + { + this.Offset = Extensions.GetStruct(info, "Offset", Point.Empty); + this.TextPadding = Extensions.GetStruct(info, "TextPadding", new Size(10, 10)); + } + + /// + /// Populates a with the data needed to serialize the target object. + /// + /// The to populate with data. + /// The destination (see ) for this serialization. + /// + /// The caller does not have the required permission. + /// + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Offset", this.Offset); + info.AddValue("TextPadding", this.TextPadding); + } + + #endregion +#endif + + #region IDisposable Members + + bool disposed = false; + + public void Dispose() + { + if(!disposed) + { + disposed = true; + } + } + + #endregion + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/Markers/GMarkerCross.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/Markers/GMarkerCross.cs new file mode 100644 index 00000000..b21be486 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/Markers/GMarkerCross.cs @@ -0,0 +1,69 @@ + +namespace GMap.NET.GtkSharp.Markers +{ + using System.Drawing; + using System.Runtime.Serialization; + using System; + +#if !PocketPC + [Serializable] + public class GMarkerCross : GMapMarker, ISerializable +#else + public class GMarkerCross : GMapMarker +#endif + { +#if !PocketPC + public static readonly Pen DefaultPen = new Pen(Brushes.Red, 1); +#else + public static readonly Pen DefaultPen = new Pen(Color.Red, 1); +#endif + + [NonSerialized] + public Pen Pen = DefaultPen; + + public GMarkerCross(PointLatLng p) + : base(p) + { + IsHitTestVisible = false; + } + + public override void OnRender(Graphics g) + { + System.Drawing.Point p1 = new System.Drawing.Point(LocalPosition.X, LocalPosition.Y); + p1.Offset(0, -10); + System.Drawing.Point p2 = new System.Drawing.Point(LocalPosition.X, LocalPosition.Y); + p2.Offset(0, 10); + + System.Drawing.Point p3 = new System.Drawing.Point(LocalPosition.X, LocalPosition.Y); + p3.Offset(-10, 0); + System.Drawing.Point p4 = new System.Drawing.Point(LocalPosition.X, LocalPosition.Y); + p4.Offset(10, 0); + + g.DrawLine(Pen, p1.X, p1.Y, p2.X, p2.Y); + g.DrawLine(Pen, p3.X, p3.Y, p4.X, p4.Y); + } + + public override void Dispose() + { + base.Dispose(); + } + +#if !PocketPC + + #region ISerializable Members + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + + protected GMarkerCross(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + + #endregion + +#endif + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/Markers/GMarkerGoogle.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/Markers/GMarkerGoogle.cs new file mode 100644 index 00000000..9429c55c --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/Markers/GMarkerGoogle.cs @@ -0,0 +1,272 @@ + +namespace GMap.NET.GtkSharp.Markers +{ + using System.Drawing; + using System.Collections.Generic; + +#if !PocketPC + using System.Windows.Forms.Properties; + using System; + using System.Runtime.Serialization; +#else + using GMap.NET.WindowsMobile.Properties; +#endif + + public enum GMarkerGoogleType + { + none = 0, + arrow, + blue, + blue_small, + blue_dot, + blue_pushpin, + brown_small, + gray_small, + green, + green_small, + green_dot, + green_pushpin, + green_big_go, + yellow, + yellow_small, + yellow_dot, + yellow_big_pause, + yellow_pushpin, + lightblue, + lightblue_dot, + lightblue_pushpin, + orange, + orange_small, + orange_dot, + pink, + pink_dot, + pink_pushpin, + purple, + purple_small, + purple_dot, + purple_pushpin, + red, + red_small, + red_dot, + red_pushpin, + red_big_stop, + black_small, + white_small, + } + +#if !PocketPC + [Serializable] + public class GMarkerGoogle : GMapMarker, ISerializable, IDeserializationCallback +#else + public class GMarkerGoogle : GMapMarker +#endif + { + Bitmap Bitmap; + Bitmap BitmapShadow; + + static Bitmap arrowshadow; + static Bitmap msmarker_shadow; + static Bitmap shadow_small; + static Bitmap pushpin_shadow; + + public readonly GMarkerGoogleType Type; + + public GMarkerGoogle(PointLatLng p, GMarkerGoogleType type) + : base(p) + { + this.Type = type; + + if(type != GMarkerGoogleType.none) + { + LoadBitmap(); + } + } + + void LoadBitmap() + { + Bitmap = GetIcon(Type.ToString()); + Size = new System.Drawing.Size(Bitmap.Width, Bitmap.Height); + + switch(Type) + { + case GMarkerGoogleType.arrow: + { + Offset = new Point(-11, -Size.Height); + + if(arrowshadow == null) + { + arrowshadow = Resources.arrowshadow; + } + BitmapShadow = arrowshadow; + } + break; + + case GMarkerGoogleType.blue: + case GMarkerGoogleType.blue_dot: + case GMarkerGoogleType.green: + case GMarkerGoogleType.green_dot: + case GMarkerGoogleType.yellow: + case GMarkerGoogleType.yellow_dot: + case GMarkerGoogleType.lightblue: + case GMarkerGoogleType.lightblue_dot: + case GMarkerGoogleType.orange: + case GMarkerGoogleType.orange_dot: + case GMarkerGoogleType.pink: + case GMarkerGoogleType.pink_dot: + case GMarkerGoogleType.purple: + case GMarkerGoogleType.purple_dot: + case GMarkerGoogleType.red: + case GMarkerGoogleType.red_dot: + { + Offset = new Point(-Size.Width / 2 + 1, -Size.Height + 1); + + if(msmarker_shadow == null) + { + msmarker_shadow = Resources.msmarker_shadow; + } + BitmapShadow = msmarker_shadow; + } + break; + + case GMarkerGoogleType.black_small: + case GMarkerGoogleType.blue_small: + case GMarkerGoogleType.brown_small: + case GMarkerGoogleType.gray_small: + case GMarkerGoogleType.green_small: + case GMarkerGoogleType.yellow_small: + case GMarkerGoogleType.orange_small: + case GMarkerGoogleType.purple_small: + case GMarkerGoogleType.red_small: + case GMarkerGoogleType.white_small: + { + Offset = new Point(-Size.Width / 2, -Size.Height + 1); + + if(shadow_small == null) + { + shadow_small = Resources.shadow_small; + } + BitmapShadow = shadow_small; + } + break; + + case GMarkerGoogleType.green_big_go: + case GMarkerGoogleType.yellow_big_pause: + case GMarkerGoogleType.red_big_stop: + { + Offset = new Point(-Size.Width / 2, -Size.Height + 1); + if(msmarker_shadow == null) + { + msmarker_shadow = Resources.msmarker_shadow; + } + BitmapShadow = msmarker_shadow; + } + break; + + case GMarkerGoogleType.blue_pushpin: + case GMarkerGoogleType.green_pushpin: + case GMarkerGoogleType.yellow_pushpin: + case GMarkerGoogleType.lightblue_pushpin: + case GMarkerGoogleType.pink_pushpin: + case GMarkerGoogleType.purple_pushpin: + case GMarkerGoogleType.red_pushpin: + { + Offset = new Point(-9, -Size.Height + 1); + + if(pushpin_shadow == null) + { + pushpin_shadow = Resources.pushpin_shadow; + } + BitmapShadow = pushpin_shadow; + } + break; + } + } + + /// + /// marker using manual bitmap, NonSerialized + /// + /// + /// + public GMarkerGoogle(PointLatLng p, Bitmap Bitmap) + : base(p) + { + this.Bitmap = Bitmap; + Size = new System.Drawing.Size(Bitmap.Width, Bitmap.Height); + Offset = new Point(-Size.Width / 2, -Size.Height); + } + + static readonly Dictionary iconCache = new Dictionary(); + + public static Bitmap GetIcon(string name) + { + Bitmap ret; + if(!iconCache.TryGetValue(name, out ret)) + { + ret = Resources.ResourceManager.GetObject(name, Resources.Culture) as Bitmap; + iconCache.Add(name, ret); + } + return ret; + } + + + public override void OnRender(Graphics g) + { + if (Bitmap == null) + return; + if (BitmapShadow != null) + { + g.DrawImage(BitmapShadow, LocalPosition.X, LocalPosition.Y, BitmapShadow.Width, BitmapShadow.Height); + } + g.DrawImage(Bitmap, LocalPosition.X, LocalPosition.Y, Size.Width, Size.Height); + } + + public override void Dispose() + { + if(Bitmap != null) + { + if(!iconCache.ContainsValue(Bitmap)) + { + Bitmap.Dispose(); + Bitmap = null; + } + } + + base.Dispose(); + } + +#if !PocketPC + + #region ISerializable Members + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("type", this.Type); + //info.AddValue("Bearing", this.Bearing); + + base.GetObjectData(info, context); + } + + protected GMarkerGoogle(SerializationInfo info, StreamingContext context) + : base(info, context) + { + this.Type = Extensions.GetStruct(info, "type", GMarkerGoogleType.none); + //this.Bearing = Extensions.GetStruct(info, "Bearing", null); + } + + #endregion + + #region IDeserializationCallback Members + + public void OnDeserialization(object sender) + { + if(Type != GMarkerGoogleType.none) + { + LoadBitmap(); + } + } + + #endregion + +#endif + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.Designer.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.Designer.cs new file mode 100644 index 00000000..7b7ff8dd --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.Designer.cs @@ -0,0 +1,124 @@ +namespace GMap.NET +{ + partial class TilePrefetcher + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.progressBarDownload = new System.Windows.Forms.ProgressBar(); + this.label2 = new System.Windows.Forms.Label(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; + this.label1.Location = new System.Drawing.Point(4, 0); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(406, 17); + this.label1.TabIndex = 1; + this.label1.Text = "label1"; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 2; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 125F)); + this.tableLayoutPanel1.Controls.Add(this.progressBarDownload, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.label2, 1, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(5, 5); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(539, 62); + this.tableLayoutPanel1.TabIndex = 2; + // + // progressBarDownload + // + this.progressBarDownload.Dock = System.Windows.Forms.DockStyle.Fill; + this.progressBarDownload.Location = new System.Drawing.Point(4, 21); + this.progressBarDownload.Margin = new System.Windows.Forms.Padding(4); + this.progressBarDownload.Name = "progressBarDownload"; + this.progressBarDownload.Size = new System.Drawing.Size(406, 37); + this.progressBarDownload.Style = System.Windows.Forms.ProgressBarStyle.Continuous; + this.progressBarDownload.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Dock = System.Windows.Forms.DockStyle.Fill; + this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(418, 17); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(117, 45); + this.label2.TabIndex = 2; + this.label2.Text = "please wait..."; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // TilePrefetcher + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.AliceBlue; + this.ClientSize = new System.Drawing.Size(549, 72); + this.ControlBox = false; + this.Controls.Add(this.tableLayoutPanel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.KeyPreview = true; + this.Margin = new System.Windows.Forms.Padding(4); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "TilePrefetcher"; + this.Padding = new System.Windows.Forms.Padding(5); + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "GMap.NET - esc to cancel fetching"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Prefetch_FormClosed); + this.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.Prefetch_PreviewKeyDown); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.ProgressBar progressBarDownload; + private System.Windows.Forms.Label label2; + } +} \ No newline at end of file diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.cs new file mode 100644 index 00000000..e560d7f2 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.cs @@ -0,0 +1,327 @@ + +namespace GMap.NET +{ + using System.Collections.Generic; + using System.ComponentModel; + using System.Windows.Forms; + using GMap.NET.Internals; + using System; + using GMap.NET.MapProviders; + using System.Threading; + using GMap.NET.GtkSharp; + using GMap.NET.GtkSharp.Markers; +using System.Drawing; + + /// + /// form helping to prefetch tiles on local db + /// + public partial class TilePrefetcher : Form + { + BackgroundWorker worker = new BackgroundWorker(); + List list; + int zoom; + GMapProvider provider; + int sleep; + int all; + public bool ShowCompleteMessage = false; + RectLatLng area; + GMap.NET.GSize maxOfTiles; + public GMapOverlay Overlay; + int retry; + public bool Shuffle = true; + + public TilePrefetcher() + { + InitializeComponent(); + + GMaps.Instance.OnTileCacheComplete += new TileCacheComplete(OnTileCacheComplete); + GMaps.Instance.OnTileCacheStart += new TileCacheStart(OnTileCacheStart); + GMaps.Instance.OnTileCacheProgress += new TileCacheProgress(OnTileCacheProgress); + + worker.WorkerReportsProgress = true; + worker.WorkerSupportsCancellation = true; + worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); + worker.DoWork += new DoWorkEventHandler(worker_DoWork); + worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); + } + + readonly AutoResetEvent done = new AutoResetEvent(true); + + void OnTileCacheComplete() + { + if(!IsDisposed) + { + done.Set(); + + MethodInvoker m = delegate + { + label2.Text = "all tiles saved"; + }; + Invoke(m); + } + } + + void OnTileCacheStart() + { + if(!IsDisposed) + { + done.Reset(); + + MethodInvoker m = delegate + { + label2.Text = "saving tiles..."; + }; + Invoke(m); + } + } + + void OnTileCacheProgress(int left) + { + if(!IsDisposed) + { + MethodInvoker m = delegate + { + label2.Text = left + " tile to save..."; + }; + Invoke(m); + } + } + + public void Start(RectLatLng area, int zoom, GMapProvider provider, int sleep, int retry) + { + if(!worker.IsBusy) + { + this.label1.Text = "..."; + this.progressBarDownload.Value = 0; + + this.area = area; + this.zoom = zoom; + this.provider = provider; + this.sleep = sleep; + this.retry = retry; + + GMaps.Instance.UseMemoryCache = false; + GMaps.Instance.CacheOnIdleRead = false; + GMaps.Instance.BoostCacheEngine = true; + + if (Overlay != null) + { + Overlay.Markers.Clear(); + } + + worker.RunWorkerAsync(); + + this.ShowDialog(); + } + } + + public void Stop() + { + GMaps.Instance.OnTileCacheComplete -= new TileCacheComplete(OnTileCacheComplete); + GMaps.Instance.OnTileCacheStart -= new TileCacheStart(OnTileCacheStart); + GMaps.Instance.OnTileCacheProgress -= new TileCacheProgress(OnTileCacheProgress); + + done.Set(); + + if(worker.IsBusy) + { + worker.CancelAsync(); + } + + GMaps.Instance.CancelTileCaching(); + + done.Close(); + } + + void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + { + if(ShowCompleteMessage) + { + if(!e.Cancelled) + { + MessageBox.Show(this, "Prefetch Complete! => " + ((int)e.Result).ToString() + " of " + all); + } + else + { + MessageBox.Show(this, "Prefetch Canceled! => " + ((int)e.Result).ToString() + " of " + all); + } + } + + list.Clear(); + + GMaps.Instance.UseMemoryCache = true; + GMaps.Instance.CacheOnIdleRead = true; + GMaps.Instance.BoostCacheEngine = false; + + worker.Dispose(); + + this.Close(); + } + + bool CacheTiles(int zoom, GPoint p) + { + foreach(var pr in provider.Overlays) + { + Exception ex; + PureImage img; + + // tile number inversion(BottomLeft -> TopLeft) + if(pr.InvertedAxisY) + { + img = GMaps.Instance.GetImageFrom(pr, new GPoint(p.X, maxOfTiles.Height - p.Y), zoom, out ex); + } + else // ok + { + img = GMaps.Instance.GetImageFrom(pr, p, zoom, out ex); + } + + if(img != null) + { + img.Dispose(); + img = null; + } + else + { + return false; + } + } + return true; + } + + public readonly Queue CachedTiles = new Queue(); + + void worker_DoWork(object sender, DoWorkEventArgs e) + { + if(list != null) + { + list.Clear(); + list = null; + } + list = provider.Projection.GetAreaTileList(area, zoom, 0); + maxOfTiles = provider.Projection.GetTileMatrixMaxXY(zoom); + all = list.Count; + + int countOk = 0; + int retryCount = 0; + + if(Shuffle) + { + Stuff.Shuffle(list); + } + + lock(this) + { + CachedTiles.Clear(); + } + + for(int i = 0; i < all; i++) + { + if(worker.CancellationPending) + break; + + GPoint p = list[i]; + { + if(CacheTiles(zoom, p)) + { + if (Overlay != null) + { + lock (this) + { + CachedTiles.Enqueue(p); + } + } + countOk++; + retryCount = 0; + } + else + { + if(++retryCount <= retry) // retry only one + { + i--; + System.Threading.Thread.Sleep(1111); + continue; + } + else + { + retryCount = 0; + } + } + } + + worker.ReportProgress((int)((i + 1) * 100 / all), i + 1); + + if (sleep > 0) + { + System.Threading.Thread.Sleep(sleep); + } + } + + e.Result = countOk; + + if(!IsDisposed) + { + done.WaitOne(); + } + } + + void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) + { + this.label1.Text = "Fetching tile at zoom (" + zoom + "): " + ((int)e.UserState).ToString() + " of " + all + ", complete: " + e.ProgressPercentage.ToString() + "%"; + this.progressBarDownload.Value = e.ProgressPercentage; + + if (Overlay != null) + { + GPoint? l = null; + + lock (this) + { + if (CachedTiles.Count > 0) + { + l = CachedTiles.Dequeue(); + } + } + + if (l.HasValue) + { + var px = Overlay.Control.MapProvider.Projection.FromTileXYToPixel(l.Value); + var p = Overlay.Control.MapProvider.Projection.FromPixelToLatLng(px, zoom); + + var r1 = Overlay.Control.MapProvider.Projection.GetGroundResolution(zoom, p.Lat); + var r2 = Overlay.Control.MapProvider.Projection.GetGroundResolution((int)Overlay.Control.Zoom, p.Lat); + var sizeDiff = r2 / r1; + + GMapMarkerTile m = new GMapMarkerTile(p, (int)(Overlay.Control.MapProvider.Projection.TileSize.Width / sizeDiff)); + Overlay.Markers.Add(m); + } + } + } + + private void Prefetch_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) + { + if(e.KeyCode == Keys.Escape) + { + this.Close(); + } + } + + private void Prefetch_FormClosed(object sender, FormClosedEventArgs e) + { + this.Stop(); + } + } + + class GMapMarkerTile : GMapMarker + { + static Brush Fill = new SolidBrush(Color.FromArgb(155, Color.Blue)); + + public GMapMarkerTile(PointLatLng p, int size) : base(p) + { + Size = new System.Drawing.Size(size, size); + } + + public override void OnRender(Graphics g) + { + g.FillRectangle(Fill, new System.Drawing.Rectangle(LocalPosition.X, LocalPosition.Y, Size.Width, Size.Height)); + } + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.resx b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.resx new file mode 100644 index 00000000..19dc0dd8 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/TilePrefetcher.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ToolTips/GMapBaloonToolTip.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ToolTips/GMapBaloonToolTip.cs new file mode 100644 index 00000000..2e4204f0 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ToolTips/GMapBaloonToolTip.cs @@ -0,0 +1,87 @@ + +namespace GMap.NET.GtkSharp.ToolTips +{ + using System.Drawing; + using System.Drawing.Drawing2D; + using System; + using System.Runtime.Serialization; + +#if !PocketPC + /// + /// GMap.NET marker + /// + [Serializable] + public class GMapBaloonToolTip : GMapToolTip, ISerializable + { + public float Radius = 10f; + + public static readonly Pen DefaultStroke = new Pen(Color.FromArgb(140, Color.Navy)); + + static GMapBaloonToolTip() + { + DefaultStroke.Width = 3; + +#if !PocketPC + DefaultStroke.LineJoin = LineJoin.Round; + DefaultStroke.StartCap = LineCap.RoundAnchor; +#endif + } + + public GMapBaloonToolTip(GMapMarker marker) + : base(marker) + { + Stroke = DefaultStroke; + Fill = Brushes.Yellow; + } + + public override void OnRender(Graphics g) + { + System.Drawing.Size st = g.MeasureString(Marker.ToolTipText, Font).ToSize(); + System.Drawing.Rectangle rect = new System.Drawing.Rectangle(Marker.ToolTipPosition.X, Marker.ToolTipPosition.Y - st.Height, st.Width + TextPadding.Width, st.Height + TextPadding.Height); + rect.Offset(Offset.X, Offset.Y); + + using(GraphicsPath objGP = new GraphicsPath()) + { + objGP.AddLine(rect.X + 2 * Radius, rect.Y + rect.Height, rect.X + Radius, rect.Y + rect.Height + Radius); + objGP.AddLine(rect.X + Radius, rect.Y + rect.Height + Radius, rect.X + Radius, rect.Y + rect.Height); + + objGP.AddArc(rect.X, rect.Y + rect.Height - (Radius * 2), Radius * 2, Radius * 2, 90, 90); + objGP.AddLine(rect.X, rect.Y + rect.Height - (Radius * 2), rect.X, rect.Y + Radius); + objGP.AddArc(rect.X, rect.Y, Radius * 2, Radius * 2, 180, 90); + objGP.AddLine(rect.X + Radius, rect.Y, rect.X + rect.Width - (Radius * 2), rect.Y); + objGP.AddArc(rect.X + rect.Width - (Radius * 2), rect.Y, Radius * 2, Radius * 2, 270, 90); + objGP.AddLine(rect.X + rect.Width, rect.Y + Radius, rect.X + rect.Width, rect.Y + rect.Height - (Radius * 2)); + objGP.AddArc(rect.X + rect.Width - (Radius * 2), rect.Y + rect.Height - (Radius * 2), Radius * 2, Radius * 2, 0, 90); // Corner + + objGP.CloseFigure(); + + g.FillPath(Fill, objGP); + g.DrawPath(Stroke, objGP); + } + +#if !PocketPC + g.DrawString(Marker.ToolTipText, Font, Foreground, rect, Format); +#else + g.DrawString(ToolTipText, ToolTipFont, TooltipForeground, rect, ToolTipFormat); +#endif + } + + #region ISerializable Members + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Radius", this.Radius); + + base.GetObjectData(info, context); + } + + protected GMapBaloonToolTip(SerializationInfo info, StreamingContext context) + : base(info, context) + { + this.Radius = Extensions.GetStruct(info, "Radius", 10f); + } + + #endregion + } +#endif +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ToolTips/GMapRoundedToolTip.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ToolTips/GMapRoundedToolTip.cs new file mode 100644 index 00000000..65f5f0c0 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/ToolTips/GMapRoundedToolTip.cs @@ -0,0 +1,85 @@ + +namespace GMap.NET.GtkSharp.ToolTips +{ + using System.Drawing; + using System.Drawing.Drawing2D; + using System; + using System.Runtime.Serialization; + +#if !PocketPC + /// + /// GMap.NET marker + /// + [Serializable] + public class GMapRoundedToolTip : GMapToolTip, ISerializable + { + public float Radius = 10f; + + public GMapRoundedToolTip(GMapMarker marker) + : base(marker) + { + TextPadding = new Size((int)Radius, (int)Radius); + } + + public void DrawRoundRectangle(Graphics g, Pen pen, float h, float v, float width, float height, float radius) + { + using(GraphicsPath gp = new GraphicsPath()) + { + gp.AddLine(h + radius, v, h + width - (radius * 2), v); + gp.AddArc(h + width - (radius * 2), v, radius * 2, radius * 2, 270, 90); + gp.AddLine(h + width, v + radius, h + width, v + height - (radius * 2)); + gp.AddArc(h + width - (radius * 2), v + height - (radius * 2), radius * 2, radius * 2, 0, 90); // Corner + gp.AddLine(h + width - (radius * 2), v + height, h + radius, v + height); + gp.AddArc(h, v + height - (radius * 2), radius * 2, radius * 2, 90, 90); + gp.AddLine(h, v + height - (radius * 2), h, v + radius); + gp.AddArc(h, v, radius * 2, radius * 2, 180, 90); + + gp.CloseFigure(); + + g.FillPath(Fill, gp); + g.DrawPath(pen, gp); + } + } + + public override void OnRender(Graphics g) + { + System.Drawing.Size st = g.MeasureString(Marker.ToolTipText, Font).ToSize(); + + System.Drawing.Rectangle rect = new System.Drawing.Rectangle(Marker.ToolTipPosition.X, Marker.ToolTipPosition.Y - st.Height, st.Width + TextPadding.Width * 2, st.Height + TextPadding.Height); + rect.Offset(Offset.X, Offset.Y); + + g.DrawLine(Stroke, Marker.ToolTipPosition.X, Marker.ToolTipPosition.Y, rect.X + Radius / 2, rect.Y + rect.Height - Radius / 2); + + DrawRoundRectangle(g, Stroke, rect.X, rect.Y, rect.Width, rect.Height, Radius); + +#if !PocketPC + if(Format.Alignment == StringAlignment.Near) + { + rect.Offset(TextPadding.Width, 0); + } + g.DrawString(Marker.ToolTipText, Font, Foreground, rect, Format); +#else + g.DrawString(ToolTipText, ToolTipFont, TooltipForeground, rect, ToolTipFormat); +#endif + } + + + #region ISerializable Members + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Radius", this.Radius); + + base.GetObjectData(info, context); + } + + protected GMapRoundedToolTip(SerializationInfo info, StreamingContext context) + : base(info, context) + { + this.Radius = Extensions.GetStruct(info, "Radius", 10f); + } + + #endregion + } +#endif +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.ObjectModel/ObservableCollection.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.ObjectModel/ObservableCollection.cs new file mode 100644 index 00000000..cd7c075b --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.ObjectModel/ObservableCollection.cs @@ -0,0 +1,541 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; + +namespace GMap.NET.ObjectModel +{ + public delegate void NotifyCollectionChangedEventHandler(object sender, NotifyCollectionChangedEventArgs e); + + public interface INotifyCollectionChanged + { + // Events + event NotifyCollectionChangedEventHandler CollectionChanged; + } + + public interface INotifyPropertyChanged + { + // Events + event PropertyChangedEventHandler PropertyChanged; + } + + public enum NotifyCollectionChangedAction + { + Add, + Remove, + Replace, + Move, + Reset + } + + public class NotifyCollectionChangedEventArgs : EventArgs + { + // Fields + private NotifyCollectionChangedAction _action; + private IList _newItems; + private int _newStartingIndex; + private IList _oldItems; + private int _oldStartingIndex; + + // Methods + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(action != NotifyCollectionChangedAction.Reset) + { + throw new ArgumentException("WrongActionForCtor", "action"); + } + this.InitializeAdd(action, null, -1); + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset)) + { + throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor", "action"); + } + if(action == NotifyCollectionChangedAction.Reset) + { + if(changedItems != null) + { + throw new ArgumentException("ResetActionRequiresNullItem", "action"); + } + this.InitializeAdd(action, null, -1); + } + else + { + if(changedItems == null) + { + throw new ArgumentNullException("changedItems"); + } + this.InitializeAddOrRemove(action, changedItems, -1); + } + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset)) + { + throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor", "action"); + } + if(action == NotifyCollectionChangedAction.Reset) + { + if(changedItem != null) + { + throw new ArgumentException("ResetActionRequiresNullItem", "action"); + } + this.InitializeAdd(action, null, -1); + } + else + { + this.InitializeAddOrRemove(action, new object[] { changedItem }, -1); + } + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(action != NotifyCollectionChangedAction.Replace) + { + throw new ArgumentException("WrongActionForCtor", "action"); + } + if(newItems == null) + { + throw new ArgumentNullException("newItems"); + } + if(oldItems == null) + { + throw new ArgumentNullException("oldItems"); + } + this.InitializeMoveOrReplace(action, newItems, oldItems, -1, -1); + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int startingIndex) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset)) + { + throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor", "action"); + } + if(action == NotifyCollectionChangedAction.Reset) + { + if(changedItems != null) + { + throw new ArgumentException("ResetActionRequiresNullItem", "action"); + } + if(startingIndex != -1) + { + throw new ArgumentException("ResetActionRequiresIndexMinus1", "action"); + } + this.InitializeAdd(action, null, -1); + } + else + { + if(changedItems == null) + { + throw new ArgumentNullException("changedItems"); + } + if(startingIndex < -1) + { + throw new ArgumentException("IndexCannotBeNegative", "startingIndex"); + } + this.InitializeAddOrRemove(action, changedItems, startingIndex); + } + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset)) + { + throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor", "action"); + } + if(action == NotifyCollectionChangedAction.Reset) + { + if(changedItem != null) + { + throw new ArgumentException("ResetActionRequiresNullItem", "action"); + } + if(index != -1) + { + throw new ArgumentException("ResetActionRequiresIndexMinus1", "action"); + } + this.InitializeAdd(action, null, -1); + } + else + { + this.InitializeAddOrRemove(action, new object[] { changedItem }, index); + } + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(action != NotifyCollectionChangedAction.Replace) + { + throw new ArgumentException("WrongActionForCtor", "action"); + } + this.InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, -1, -1); + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(action != NotifyCollectionChangedAction.Replace) + { + throw new ArgumentException("WrongActionForCtor", "action"); + } + if(newItems == null) + { + throw new ArgumentNullException("newItems"); + } + if(oldItems == null) + { + throw new ArgumentNullException("oldItems"); + } + this.InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex); + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(action != NotifyCollectionChangedAction.Move) + { + throw new ArgumentException("WrongActionForCtor", "action"); + } + if(index < 0) + { + throw new ArgumentException("IndexCannotBeNegative", "index"); + } + this.InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex); + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(action != NotifyCollectionChangedAction.Move) + { + throw new ArgumentException("WrongActionForCtor", "action"); + } + if(index < 0) + { + throw new ArgumentException("IndexCannotBeNegative", "index"); + } + object[] newItems = new object[] { changedItem }; + this.InitializeMoveOrReplace(action, newItems, newItems, index, oldIndex); + } + + public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem, int index) + { + this._newStartingIndex = -1; + this._oldStartingIndex = -1; + if(action != NotifyCollectionChangedAction.Replace) + { + throw new ArgumentException("WrongActionForCtor", "action"); + } + this.InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, index, index); + } + + private void InitializeAdd(NotifyCollectionChangedAction action, IList newItems, int newStartingIndex) + { + this._action = action; +#if !PocketPC + this._newItems = (newItems == null) ? null : ArrayList.ReadOnly(newItems); +#else + this._newItems = (newItems == null) ? null : newItems; +#endif + this._newStartingIndex = newStartingIndex; + } + + private void InitializeAddOrRemove(NotifyCollectionChangedAction action, IList changedItems, int startingIndex) + { + if(action == NotifyCollectionChangedAction.Add) + { + this.InitializeAdd(action, changedItems, startingIndex); + } + else if(action == NotifyCollectionChangedAction.Remove) + { + this.InitializeRemove(action, changedItems, startingIndex); + } + else + { + throw new ArgumentException(string.Format("InvariantFailure, Unsupported action: {0}", action.ToString())); + } + } + + private void InitializeMoveOrReplace(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex, int oldStartingIndex) + { + this.InitializeAdd(action, newItems, startingIndex); + this.InitializeRemove(action, oldItems, oldStartingIndex); + } + + private void InitializeRemove(NotifyCollectionChangedAction action, IList oldItems, int oldStartingIndex) + { + this._action = action; +#if !PocketPC + this._oldItems = (oldItems == null) ? null : ArrayList.ReadOnly(oldItems); +#else + this._oldItems = (oldItems == null) ? null : oldItems; +#endif + this._oldStartingIndex = oldStartingIndex; + } + + // Properties + public NotifyCollectionChangedAction Action + { + get + { + return this._action; + } + } + + public IList NewItems + { + get + { + return this._newItems; + } + } + + public int NewStartingIndex + { + get + { + return this._newStartingIndex; + } + } + + public IList OldItems + { + get + { + return this._oldItems; + } + } + + public int OldStartingIndex + { + get + { + return this._oldStartingIndex; + } + } + } + + [Serializable] + public class ObservableCollection : Collection, INotifyCollectionChanged, INotifyPropertyChanged + { + // Fields + private SimpleMonitor _monitor; + private const string CountString = "Count"; + private const string IndexerName = "Item[]"; + + // Events + [field: NonSerialized] + public virtual event NotifyCollectionChangedEventHandler CollectionChanged; + + [field: NonSerialized] + protected event PropertyChangedEventHandler PropertyChanged; + + event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged + { + add + { + PropertyChanged += value; + } + remove + { + PropertyChanged -= value; + } + } + + // Methods + public ObservableCollection() + { + this._monitor = new SimpleMonitor(); + } + + public ObservableCollection(IEnumerable collection) + { + this._monitor = new SimpleMonitor(); + if(collection == null) + { + throw new ArgumentNullException("collection"); + } + this.CopyFrom(collection); + } + + public ObservableCollection(List list) + : base((list != null) ? new List(list.Count) : list) + { + this._monitor = new SimpleMonitor(); + this.CopyFrom(list); + } + + protected IDisposable BlockReentrancy() + { + this._monitor.Enter(); + return this._monitor; + } + + protected void CheckReentrancy() + { + if((this._monitor.Busy && (this.CollectionChanged != null)) && (this.CollectionChanged.GetInvocationList().Length > 1)) + { + throw new InvalidOperationException("ObservableCollectionReentrancyNotAllowed"); + } + } + + protected override void ClearItems() + { + this.CheckReentrancy(); + base.ClearItems(); + this.OnPropertyChanged(CountString); + this.OnPropertyChanged(IndexerName); + this.OnCollectionReset(); + } + + private void CopyFrom(IEnumerable collection) + { + IList items = base.Items; + if((collection != null) && (items != null)) + { + using(IEnumerator enumerator = collection.GetEnumerator()) + { + while(enumerator.MoveNext()) + { + items.Add(enumerator.Current); + } + } + } + } + + protected override void InsertItem(int index, T item) + { + this.CheckReentrancy(); + base.InsertItem(index, item); + this.OnPropertyChanged(CountString); + this.OnPropertyChanged(IndexerName); + this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index); + } + + public void Move(int oldIndex, int newIndex) + { + this.MoveItem(oldIndex, newIndex); + } + + protected virtual void MoveItem(int oldIndex, int newIndex) + { + this.CheckReentrancy(); + T item = base[oldIndex]; + base.RemoveItem(oldIndex); + base.InsertItem(newIndex, item); + this.OnPropertyChanged(IndexerName); + this.OnCollectionChanged(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex); + } + + protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) + { + if(this.CollectionChanged != null) + { + using(this.BlockReentrancy()) + { + this.CollectionChanged(this, e); + } + } + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index) + { + this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index, int oldIndex) + { + this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index) + { + this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index)); + } + + private void OnCollectionReset() + { + this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) + { + if(this.PropertyChanged != null) + { + this.PropertyChanged(this, e); + } + } + + private void OnPropertyChanged(string propertyName) + { + this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); + } + + protected override void RemoveItem(int index) + { + this.CheckReentrancy(); + T item = base[index]; + base.RemoveItem(index); + this.OnPropertyChanged(CountString); + this.OnPropertyChanged(IndexerName); + this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index); + } + + protected override void SetItem(int index, T item) + { + this.CheckReentrancy(); + T oldItem = base[index]; + base.SetItem(index, item); + this.OnPropertyChanged(IndexerName); + this.OnCollectionChanged(NotifyCollectionChangedAction.Replace, oldItem, item, index); + } + + // Nested Types + [Serializable] + private class SimpleMonitor : IDisposable + { + // Fields + private int _busyCount; + + // Methods + public void Dispose() + { + this._busyCount--; + } + + public void Enter() + { + this._busyCount++; + } + + // Properties + public bool Busy + { + get + { + return (this._busyCount > 0); + } + } + } + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.ObjectModel/ObservableCollectionThreadSafe.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.ObjectModel/ObservableCollectionThreadSafe.cs new file mode 100644 index 00000000..0bb4be72 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.ObjectModel/ObservableCollectionThreadSafe.cs @@ -0,0 +1,62 @@ +using System; + +namespace GMap.NET.ObjectModel +{ + public class ObservableCollectionThreadSafe : ObservableCollection + { + NotifyCollectionChangedEventHandler collectionChanged; + public override event NotifyCollectionChangedEventHandler CollectionChanged + { + add + { + collectionChanged += value; + } + remove + { + collectionChanged -= value; + } + } + + protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) + { + // Be nice - use BlockReentrancy like MSDN said + using(BlockReentrancy()) + { + if(collectionChanged != null) + { + Delegate[] delegates = collectionChanged.GetInvocationList(); + + // Walk thru invocation list + foreach(NotifyCollectionChangedEventHandler handler in delegates) + { +#if !PocketPC + //System.Windows.Forms.Control dispatcherObject = handler.Target as System.Windows.Forms.Control; + + // If the subscriber is a DispatcherObject and different thread + //if(dispatcherObject != null && dispatcherObject.InvokeRequired) + { + // Invoke handler in the target dispatcher's thread + // dispatcherObject.Invoke(handler, this, e); + } + // else // Execute handler as is + { + collectionChanged(this, e); + } +#else + // If the subscriber is a DispatcherObject and different thread + if(handler != null) + { + // Invoke handler in the target dispatcher's thread + handler.Invoke(handler, e); + } + else // Execute handler as is + { + collectionChanged(this, e); + } +#endif + } + } + } + } + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/Properties/AssemblyInfo.cs b/GMap.NET/GMap.NET.GtkSharp/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..32b9aca9 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/Properties/AssemblyInfo.cs @@ -0,0 +1,19 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +//[assembly: AssemblyTitle("GMap.NET.GtkSharp")] +//[assembly: AssemblyDescription("GMap.NET - Great Maps for Gtk#")] +//[assembly: AssemblyProduct("GMap.NET.GtkSharp")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(true)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("82e283ec-0096-4b55-baaf-89f671fa56d5")] + diff --git a/GMap.NET/GMap.NET.GtkSharp/Properties/Resources.Designer.cs b/GMap.NET/GMap.NET.GtkSharp/Properties/Resources.Designer.cs new file mode 100644 index 00000000..a6e65c62 --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/Properties/Resources.Designer.cs @@ -0,0 +1,357 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3634 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace System.Windows.Forms.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Windows.Forms.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap arrow { + get { + object obj = ResourceManager.GetObject("arrow", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap arrowshadow { + get { + object obj = ResourceManager.GetObject("arrowshadow", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap black_small { + get { + object obj = ResourceManager.GetObject("black_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap blue { + get { + object obj = ResourceManager.GetObject("blue", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap blue_dot { + get { + object obj = ResourceManager.GetObject("blue_dot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap blue_pushpin { + get { + object obj = ResourceManager.GetObject("blue_pushpin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap blue_small { + get { + object obj = ResourceManager.GetObject("blue_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap brown_small { + get { + object obj = ResourceManager.GetObject("brown_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap drag_cross_67_16 { + get { + object obj = ResourceManager.GetObject("drag_cross_67_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap gray_small { + get { + object obj = ResourceManager.GetObject("gray_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap green { + get { + object obj = ResourceManager.GetObject("green", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap green_big_go { + get { + object obj = ResourceManager.GetObject("green_big_go", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap green_dot { + get { + object obj = ResourceManager.GetObject("green_dot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap green_pushpin { + get { + object obj = ResourceManager.GetObject("green_pushpin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap green_small { + get { + object obj = ResourceManager.GetObject("green_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap lightblue { + get { + object obj = ResourceManager.GetObject("lightblue", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap lightblue_dot { + get { + object obj = ResourceManager.GetObject("lightblue_dot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap lightblue_pushpin { + get { + object obj = ResourceManager.GetObject("lightblue_pushpin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap msmarker_shadow { + get { + object obj = ResourceManager.GetObject("msmarker_shadow", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap orange { + get { + object obj = ResourceManager.GetObject("orange", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap orange_dot { + get { + object obj = ResourceManager.GetObject("orange_dot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap orange_small { + get { + object obj = ResourceManager.GetObject("orange_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap pink { + get { + object obj = ResourceManager.GetObject("pink", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap pink_dot { + get { + object obj = ResourceManager.GetObject("pink_dot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap pink_pushpin { + get { + object obj = ResourceManager.GetObject("pink_pushpin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap purple { + get { + object obj = ResourceManager.GetObject("purple", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap purple_dot { + get { + object obj = ResourceManager.GetObject("purple_dot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap purple_pushpin { + get { + object obj = ResourceManager.GetObject("purple_pushpin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap purple_small { + get { + object obj = ResourceManager.GetObject("purple_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap pushpin_shadow { + get { + object obj = ResourceManager.GetObject("pushpin_shadow", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap red { + get { + object obj = ResourceManager.GetObject("red", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap red_big_stop { + get { + object obj = ResourceManager.GetObject("red_big_stop", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap red_dot { + get { + object obj = ResourceManager.GetObject("red_dot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap red_pushpin { + get { + object obj = ResourceManager.GetObject("red_pushpin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap red_small { + get { + object obj = ResourceManager.GetObject("red_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap shadow_small { + get { + object obj = ResourceManager.GetObject("shadow_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap white_small { + get { + object obj = ResourceManager.GetObject("white_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap yellow { + get { + object obj = ResourceManager.GetObject("yellow", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap yellow_big_pause { + get { + object obj = ResourceManager.GetObject("yellow_big_pause", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap yellow_dot { + get { + object obj = ResourceManager.GetObject("yellow_dot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap yellow_pushpin { + get { + object obj = ResourceManager.GetObject("yellow_pushpin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + internal static System.Drawing.Bitmap yellow_small { + get { + object obj = ResourceManager.GetObject("yellow_small", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/GMap.NET/GMap.NET.GtkSharp/Properties/Resources.resx b/GMap.NET/GMap.NET.GtkSharp/Properties/Resources.resx new file mode 100644 index 00000000..f0c30bdc --- /dev/null +++ b/GMap.NET/GMap.NET.GtkSharp/Properties/Resources.resx @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\arrow.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\arrowshadow.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + + ..\Resources\black_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\blue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\blue-dot.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\blue-pushpin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\blue_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\brown_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\drag_cross_67_16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\gray_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\go-big-green.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\green-dot.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\grn-pushpin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\green_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\lightblue.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ltblue-dot.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ltblu-pushpin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\msmarker.shadow.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\orange.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\orange-dot.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\orange_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pink.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pink-dot.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pink-pushpin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\purple.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\purple-dot.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\purple-pushpin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\purple_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pushpin_shadow.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\stop-big-red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\red-dot.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\red-pushpin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\red_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\shadow_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\white_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\yellow.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pause-big-red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\yellow-dot.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ylw-pushpin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\yellow_small.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/arrow.png b/GMap.NET/GMap.NET.GtkSharp/Resources/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..8d34603a5a12063e64232d7e3d179e2b7b2ea847 GIT binary patch literal 1015 zcmVJ+_F(nWAu7%r7AE?hu#iN{#ECk zeslkG&pAa%`m+GS61p!Hj4`GXGTQZsVVND_0&OnbztFTz<=vhg;TVQNMw^ZvEa>6C57C;m3O&ONlg*b7*tenYCVTsF)J#A zd^v?Ht+yjzV{z)uvw>q(Y{~&|gIyUos4rwLHD(1@;5Hzk)u}98p+7$>IJ4KN3|v{K zTMaem2f!$tKn?s>?S_^zz%8erHM#O?Jp1iY$iqWEO-|tKA@fbBmoM-G7&-ukn!_p` zht+yjN{LHRQMk@)wSS)>&yzT4A*ueys+e_KS-~A@I3eL20k}1CLeneTA$FyeKPSp^ z%y)lN@f0;&?L?5&${;l2pB-1?RB%UT>oCJHzx<8GlO%6W;D}sN>nyQnXt5WF)8)H@J9w^=T!ODv$Gw&R=c8{WV}VWb)Y&c&d&eHM$pV{LI*c_&HFm|V zSGVTMnXUiq4XX5J%{yq!vf#)q*BaFy07kbpSI$q42yWXr+&Vmbw^b61oGz3BhUR@% zEDt>#Oo(kt3Y@MW^XXOh`G}<-VT?aVHzM<5}+oV6^08)3NFTbXsDauh}AHvKEd~_R4g?d*}J3!_RU!Z z(js67QX`M8s;M3`@J_GOBtw>2q9DmKjPVBcF$ zFP)v&YcZ@>Kca(tL8e&6;fPGmycZQco)lboz>f_!-D^2cub)YnlmYsplA#*BT397#EG)Nqjje@0au^Olf)*LFFU`U3+NSICLm6F3k9 zJKn00aKTc^ev9<`xjli44)d}Em*AD&qQ#)Ma$^+lb7{eact|WYyA4m}#!$nBdP`*q lrogL>0AV93?r9wB9e7+ zCo{ks;bmY0CM^msNZ?_Y5_kFO&Fn12BqD?RdZfWUK680<(jRh_7gRTF|U zuob|5VeFQ|yK^r!bc>U`qI1u)1gB=ICy>F7alHV<9dk$cO za?QbJ!LJFdFBVb-%7=auw&MCi^&DXCmO*{AgjcBT!5`DLjFbrFOY96=gzr5Pekpr? zpOzYi^tI|0&JF6Ft<0|8@il=vRlPwd-zv~q*Z;o$0l~TY#Ypb4c>n+a07*qoM6N<$ Ef~6}pv;Y7A literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/black_small.png b/GMap.NET/GMap.NET.GtkSharp/Resources/black_small.png new file mode 100644 index 0000000000000000000000000000000000000000..d9cb30f9b13688b020e695151c463261a933694f GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eM!3HFEez+qDq*&4&eH|GX)}JtE?Rp91OP07s zlmzFem6RtIr7}3CYuGQ(^lfQVDtRsSQRCgQr^jj|MCP+5g~dpn z*_iP`QAEgkqDXwxGGmK`LyHm(g{nnEl;afmd7UOW1t%%7r@XFJ_{Vaj=EWqP8;j&S z;+a13uTX1}a(G}HqRhNeN{+$M+>En-eK@`^>bP0l+XkKM(t>P literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/blue-dot.png b/GMap.NET/GMap.NET.GtkSharp/Resources/blue-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..98b280d3019757279bb80abd14f4a3a2adfc6aad GIT binary patch literal 1340 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 T^E$RX00000NkvXXu0mjfg)VJP literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/blue_small.png b/GMap.NET/GMap.NET.GtkSharp/Resources/blue_small.png new file mode 100644 index 0000000000000000000000000000000000000000..2ec9ae941ad28c4dc50e2715cd92d43a546d8221 GIT binary patch literal 558 zcmV+}0@3}6P)2?J1P#*A*4ok% zL=ivC|Qc%}lAQD-FSZssb9b|@7gUFWK zJr4r|K@bE77zRMG2q20QsOl)>av4Y_PkS)$#EKuE%_iZ=0Votc6Tghs6!Ul%fw4vk zO^~3ysi_OgXst*t7d12}(A?ZjZW{>pJh*KH=?uGt%b~Xoz#2&c| z$bn!Uc8*vz?P`cIC%9aFrBdSYT?mJlX@4DAt<~ER-L%*H#C<-U+wCnh3M!s`_f#c_ z7K?Awj5&bHGfSDJ_+Jw|lq8kQawnZ0E_*(|+LZa=h$X1QROHHo6dj_?2fu-H&-dNe+!Wl_Q=*9|HtXNS zFfnWKA%*B8gvad=6{P|3q%0u3sSd$o#0SE5Wn}de9gWXQ(b`asfIr>n>>i%s)7VdZ zomyniAkoIDYGQ!RZ#rt>a@rA#Yfv>E4?Hf^R}~|Ca*2htgL3lCN%VQ;CR6*1$GC_p zP{@2GMb&V2sTiwz-3}gl$$^4L`99?M(-2p6>)DKzvL1R-Qt0C{j{{mvQK9JqcS#ol zF~wL}=fGlUGmPcUh_QdGoDMry{~Tdy{gBHL2R_pT(cUjXXqtdclCI4*iLQ#8?~I-v zXD{DUm^j%!IDNiD*H~9sMBDp!7PnJI_s1Db1XsE2B)-|q$>s@Zc`H(r>XK1emJ3;y zF!Fr~1Ebu+TcRh?`KI|#PrYvz!J!u6&-Cz3{2=7(ZCV1MxT>}CDtnQ0jL)s`SUZp7 z9!+NZyrM8CgJ=JB6;KVEp_J2G&biS@7q~cY%NOvD9-Sp zLH&24%VkE+9}I=gZyI!-$1+Q7oyl0O#OLtSP}rf_#Z&Bn_CnTsTH;l1j8Q)hy6#pp zOk$OIe>3K}ZyZAx)05`UM@45Dtk`!(k@>+=ueuercVo<%dy-4km2I3@1VXQ$eI)qP uxs~Zd&_BN|hRd&ttUL70>;1oD`Yda2&wh6N&sU(s89ZJ6T-G@yGywoxiC^si literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/go-big-green.png b/GMap.NET/GMap.NET.GtkSharp/Resources/go-big-green.png new file mode 100644 index 0000000000000000000000000000000000000000..e87315409f0cd4b2667826b0a4b1385d69f0afcc GIT binary patch literal 3350 zcmV+x4e9cUP)V6)7cym8aR(@0b(QFbLDnFCD zsFgyV`2gtXjHd(zmFIu9Zq1el|L}uoPbAMgKW;)PW%Fk+`N}f97mPvki6uLzoyb5*Q@ViKCMsL7W6S0tXJf zc+pV#sP02{-@BQHS8L2E!@yji>Wnb~9i53xptHMk;`ip^ou72{EflO@z0YDK&sA#;qc00RPY%-_q1LgqLqYl7RyvjI=5y*mX zUwq5awwjg+0JpDO$@1I3LlZ4@5i`a@9PLeN_~(Bq?8y49EyVyN~zklpI5K> zjhzY8ftH~Hpbo`;@^Dc|0T0}?`gK$JZ#=Pr<+p#E<1`Q;1gIFPO-H0YGxw9qr&iOp zDL_K%w9vwg1)t)JyYDck_5wSH!v_orfD1UE7hZVodsUkcTm|r%yZ@0DcYc?88i^7` zf~9Bzfu5pza^FBl$4Jo~+xjP+y^;n+O8odKpFf)`*DW%qpAP(DRGr}SiPwvlkGrWO z+7nU6Pdkq%k8Qv}(nS{niJnqAY3qh%^YIk*b!+u)n>77^1xIpU3N%&2hmQ@5e@)A4 zb>?k+LP~io=M30I66osaJf0YZqL{2^vvQFp!9p(n%HwbPTrN_YymQ_zFE; z-5IJ2i~7R8XFG2C1eKr+GU41wOuOSU^H#nL6y+R%gNNQ**jm?80&x93H&H|ZQKG5U z6*h;br-0Cj^+wtE@Sl15!Us99W(V=!SlaKWOwrB+^LS=-fH-l={_XO#FNUQ#2jGKk zhdvLWIW;a_cscEKrktL%sceFwTa*WghobC%U^~xF{wbA@zD=SpZexOt_%`=s#RVzo zp_g+mxd2~zsd;)q&H?ZrX`Bf#^YgQqTsWB^-Im=O8D3wvOh9BM^0BTyDpqgfg=s&h zX6=4N+{ki$b`M~hf|4w_@GxOfnR%%hIR~Jlp{)#H%Iq>+xJX!T&ahTow;6$%=?x@( z{vP(+wS|q-f639`{x8B1kWGCgn4dBUbm2^^z&tPK00djQN&$)|m88_OCpp4q`{`qU zPkKKJvgeM?Y%YJC!Z{jS-}SbY`F zVpmo?NGCBcdJPykK^;2AO|9tXF zJqSq#fXMWfR8)G81)L_ zzW~qqUW@7(^?B|gl#6P!4A+ChM>hIVTIa+m_V8Frsd{eh}ZMN=ue z^)kLxb2nE!v55Thy|$32WC54n%TrtgL+$uqv)Y4)at^@E#j{>=x|3n((C^+sMYC#r zkyYboW^_rJ`jv8StiFq@p1Kk5)G+{vRH~Z{c_Jev7AeaY2=ejL^wLp8+%PY;dBF7loTAQg}X|)570_#TwfG9CK2(WnFZOa__ zNnh~V!l!8NY@~$JWbG&A0G*!fxR6=s*zMk0d1>Hv7LXv$?(5eh6T;pM8J(tR9Gx~g z@D+}2zH#dvw*VwUG1g!GC_T{-V;O^iky6YS&->N*_Ux`d^@S9;ogP$F-dOYuJ?~o~ ze`WRqlAHoylJ_KjW?g&bi`V^r*=m5EBb_`q?-3FtC{l_tQsE56EM?Qwm$s%zvKs_W zrwbP@cHZ(l?b{m6=^qAuHL7iKyA}IsW&Xc>;n8`&Ua|%taIlpPi~b8IPTYz+)e7m~ z;7DhBwmz^-KO0gsg#rqw_|aBcUaU2z{vY6n!}V-%&;aOCN0&N=G>FSMe*9c__stKK z-#hOafR=4_Z2SJR6j6w(sJ7M5w0nDkBc;9E75G#ihqoS}?jbAWy#?GkoDW9_4S=u> zi9$@qX{VEgk9_^sbFP_O4N&v*3M$`xm$AvmXITvnnc)~SxF987M*)GJPWIjWiaBKf zxPf7oA((*37yx}TOq@7N{`jryoIaNU@Wzt$1QT6&Rj<_)F?)M5E8#Ici>j$O(5U#z z%Shewnu~$h83TYAU;_xq0L7kh{%c-XdOLs~POx+NhGdeIGKEa)%PjNIDO8K7+fhl| zpDd^M8(T#hA8ojZ@u)PYaas$9BQTZ%}R=tF^E)`Fr5@7`C}G3HQ(QD zo;VJ?$Oy`?Il+EIN^=USA1eTmk{B`0 zUv|-R=J&gHHnvjc!rb%LoO^klVI`nk!w z0K&&Z^fm`kQR#fE(Y$OW(EYJw01Cv3GWM$TEC<(jJVcxXfj!OUp#$Vtat44z5+{LY zs;|a1K0gW&ZS5mUgmAs}kYm@!8UP&~m+I~-oH?!*AlleXZy<#2^`U)d4*>G?htLHM zG(1y%^#FbKA%gq;_MYE~Tm#@33IhgJLZaZAT-XQ@>*%BVp!NHpIzT^b02oY@#%zUo zrx!N@L{4-gqL$7LjDqBr0VIDv;F{pA2Z+>%&;wSZw`nM^?vDZhgL^ekAke&yPJmcj zghU#EvyA~_kN`;3d`F+PpMKKYeO3X094rG29AjKT#i`mKa|85_1^^@45*uhF0dRIY zi{0_8OE#TV01UpBCeZSoL1(eME9;d1|3?&%0;l3MoW*YaEC*naVhB`+inGLB4VXWn gKf(w+_&gQ)KfTGY3YNU?1poj507*qoM6N<$f^wBv6951J literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/gray_small.png b/GMap.NET/GMap.NET.GtkSharp/Resources/gray_small.png new file mode 100644 index 0000000000000000000000000000000000000000..0b00733dacb214b9f0e5c072bc7b633f913d604d GIT binary patch literal 567 zcmV-70?7S|P)(RCwBq zlD%tMVHCz6wc>XsK^%%1D(-5R4lU@GMd1$ZP;n{!6FLQiEH0e_w-ky~rVeTxtCA(4 zL&y?>TtsXag-Efbpy>7E+am;cvZQ-Z0P1xX*lL&MkGY zF~BH5qJ@4;YjFdPn%N~H{=NOmk1 zi)c2R5`JJ#H|;K@As_1%|2QO*NjRNO)M_=9N+rpEWRA9d-x-gODwPV=>vakSgYv^J z8Rw?JVKHbt+IJq02cyvljYdP(-pe{3(KntuMIsUDer4XXNA=dcJHjD$P=wJZd2G~06vyAZnQm*hE~S-jcU$PT+ipv*-JT2dq|tbbv8nMu zv<730m?)PDQcw~_%ORl>0*y#88bYeANHFE08jt#SVkz@eFd3#Q%4vmKS!WRV!ECitd_;CKtc&n=0T z`(n6;@J2r=z*9Is_r9_57X|QT17KIUlZ_HDZNk|P%>+jq3BDR9-PgbW(n@0UbmHwH zTpGGxk2eSSC=Oyrc`eWUPkff0|JrJIJW={P|4(c!<&_Ypxov`v<7NP2Z#BrWO9$n( zQ>>Z&r{jq_(Ms5nO)Bi&FZRTg5dc1#-=w4@v9E^U`{oM+_^z46fjUx2lJLR2D~$kD zx$iMq=3`?`wxt*SF_Je2NKH<*THUun{MbygCY@A4+7o5~fZHTTwH0_1j9bo?8k6qZ z0C*hU7SvhMYX|__ac+?J-wvQ>J{~~#9Rcp0O4^PgfZQUl%Sz0+2H% zFP7mng0Br?;AkQcbquLW-*U4oc(SNkp&aEhYz5Q>WdRo@F<8w7NuI{8f=07C@M;uf zJpCmW!A}fu>^z<8+4Hu^*%_pwz5(${)UXnA1%rWDSS8EjxFp2I#U2Z;MQCN1V*`H^ zyDLkLDgXUb6Gu!s|(Lv5&1jvnZf`63)d7~ug7aU<^cafbVu6RD2bgF zj#*)ew@JJfBfcMySQ+lLoR3`0Y4~CMj1JEN?95rEGCafv3BGMQ+xao>AK~;2rINhK z-(xxdl%0Q)kXaDEQ-4PKa`Ap#szUGEvfXcA1)cMYLZs3?hhey8l64z8P&XzsfWhjs z^=2(#ccjhQilK1_l)jvd%p{enG{oKFtvcISGl1QdcD)hPNAw;!XIzEUvtM4oMalCy zr*5(sh+0>;@iGJGw;K|Bs{kJ_yh0@_f)C<}Sm3;ud8veV1Q%H|=DeRMGl1vI?AmU% zNh;0r1+I+{{63q+>m2z?p5)*2^a?qFn*nT@?yMbUAR96^$+k>_(Kf<|IQXWf?iaf% zK#|IGl1@hv(^;@t_lZ~*Yk(y zi;~JpA$|)qTF&&N#6e~Ni$m^O5(1T(@)^GuNM$6S5UUF_#rg<{wazjFSQv8G!}-9^ zvwgCPUqrd72l1IAz^7SjoMi?uH|Va;9N^2!F5U)`1!+ULG#@w^U1bJvd(d5XF+izr zvwktjY2H3;&jy_1ca>QhK2_wd4aLBb-^CYBk}a7%;yDgL&JZ`50rZr(i&GBg<;>Fn j`~q4awz;R^xzg|-E$Hb9-u`3n00000NkvXXu0mjfDCa>u literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/green.png b/GMap.NET/GMap.NET.GtkSharp/Resources/green.png new file mode 100644 index 0000000000000000000000000000000000000000..0f79315e427e3401061bd85d197b033ca24e5212 GIT binary patch literal 1190 zcmV;X1X=ruP)JW3b9v#cu@&% zgPs-gCf_VvQJ}>7Vh}Ht1H4zC=+AbXd{}-iNx+^c;KERq%DHSnxzrh1;U#&ipYYy1 z!rS~LW0Od^QvT-eL-=4YF8V61e*cev!!rRFOuLImJ0h>kCNWq|@J$oJ$rgg2TM{il zi=i6An|-7J&*1#L`_J{Ckbtim0K3ASY?OFv6V85UCOFYiqLOV>UwgKe4rxXF{Ciwh2Con+Xv6szH`rJ|M53 zVvX!S9be3;R>F=PQen>lu{WlS1mI)&O-f1<`)dfkZyuk3@0v**tRs~o2_FhxZ6rXI zdmoo&UN+V=_SD<)V>8K`3{nN@Pnrn;+$K4yt-u?va}D>y+XFf)dJP4@cAOjF^`C%% z`=*k%V<Ouq$au!f48cz<;KVpa&&wufXOfC~`^BqK!%D~% z4EkeXl`2o-k`Nb{ON<3wgjR-0Df~_Bt}HdKgm8%Wf};%}HWpvWW%V?!E*!fe@^|Dt zga7{v*A(5T`)fPq0{#`z9cgEyBz9IfX9X{lcs)jZJ|M9&+-W%I-?R7O*?gW-Z0ws0~UVPKIZaaw{$39`SZvQeQIx zyDO7iZ|3aLlGynxhX*B6|+siHq>9pOe}CSXspA+fIt@QK2!RH`EQFrJ77 z&U+bj6W$qEWQ~~f{$k7oyik_RcB@TM>8>wvZG_jG-4T1%6$7pc`<2J_hvK1jJf<%mge9IrB(9@bzrJtl}F{p8F6!TLkzFv&J4X0doV+bmjsdR(A0+ zkSs_a#HIPb!RUyYfI9-t+|2??y_@xoNlx?hVS5hX9G@d*Y4~)JGaHJ5BfpCeoFrSa zdc^Y_fSe&tmEz;2p%A3dmZm8}R8#~>+K6|QdiB1~_c^ZqiK)#4zvJHbd!LW@d%rJ%zf}@Oh0}5T zR+trDwbUUYJQB2(wX}22(N4+HDLbW^6Q%`ozmR$?Ocbva;ofv%AGf2V|H;Sd^eQS( zD-36Z>vWwLo)j+^G5By0$swoONM+#lHEzTw_F5% zfG`Mu^~wLh3*b(;koK4wrr~7%OdfWh4Yj9Q&lcsfP8Rw8Ji}u&gls`8jf2EB*3eJG zdZW_7*2WgtTB~@b=9?xOYYm2*G(3~R?Uo;up+W`2G=9(8Oh9Xm^8ILSkF}foWTdRLg~dCIs4dhO-WKM}c(d1nv0dH1U}Y@ymU>}W2CC1iSe{zu`lN8L z-T7YfrpK1X^!WO?P9IHk5_DMm1!jw3Qw8c;DwBf$*+*?YYUKv=_>W%5+;#3$j=Qh@ z@q7-{)%d}YyXZhCgdjEybYkE|yc50&J^x%}8v`%li?AD;4mD8C*oaOI?}bdeg`WZp Y0ECXGBT+P?O#lD@07*qoM6N<$f<=}Sn*aa+ literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/grn-pushpin.png b/GMap.NET/GMap.NET.GtkSharp/Resources/grn-pushpin.png new file mode 100644 index 0000000000000000000000000000000000000000..61d29725508873af97d1b60d0aa3ee4bc0814ede GIT binary patch literal 1237 zcmV;`1SPx#AY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF* zm;eA5Z<1fdMgRZ+32;bRa{vGf6951U69E94oEQKA1U^YbK~z}7y_aiDTV)u>|IcCI zxKk zZ_1u@pERa*p(wFaONxF)AddpLTL1w7QJ4R$kiJ4a6d;^ED9`U8SWmEym~l}?Dk&cq zQQLp#q~s-ZipWzMkg-+(yYY4oaiN?TwkinL6LhQV-%iRGCDitA8JDCD#{rmE1+c=p zUEG^4W5Pk4zL)r@knmcFSyvFIZUJUcr#!iJQZ{IZ0K^&v00DN%{%tpK%}#hM#Hm7} zEtfc3N?f%Qvo!>3gCGr*Z_6m#V?PCuZ3qB>6xo+?6(cs{ObOAi6GJxQT&aR-FCaRL ziHqe#pH56WDMzyiO`bCf;9+SmBmz$5Bs18_pf)rBYl%4*F)^3{DR1#_;@5Mix>cqfkl zc1BW!Nn(yaFT*x9Ui}W@&nn`2mD>3YClRP2Zq^VpK?~FnQ`PF-_hpo5?NDT00Ay;J zab4&rR*r|PD&Jnqg8mO!)ePtl{`TprP0y52qU32KgeV1ZQLSI%;9?i$%FNjE0xNT-$9JpmH8dSWHrU7Q_D~60&uI* zvmmLdYWI-m+(nw|wvFPE&0{#0MZB9!oGc(-GgF?pBOnWah5;lrHZ~4=yBw zV*s<+>~Xu@GXV53r=>NofujH(U*Wj6YJh(M#zH)Gj|L+h00000NkvXXu0mjfLg;7DQyaFjNVG5Pun-^DvUW%qZo}b;3OSJq5(xi6qP>+Y{n-nqlFFI{3w+uK>(-n}fmrbZH&n;Yli=T~QEXV=CU zYp2%5*SEnhBV$SA=FQUB-Md-xkt4!58c*|xtwCa+1-N~iWnaF`mYqDw!p!CfTdQ7!*)a;{~>bAmIN*U9s0kAM$_r3(LmADr%*UDGVR^dv3VyY(e8V6ot=C}WI!iO>FNrS zI5>=}tE;DNM$`}O8_+}k&>cUnGVnTK4puVqaxB9sm`HD<8ydcNBj|go8QA}CO=Dwr z{=Iv`Jlp`J0-Pjf=gvHw6q4H7py=5%QR7*5>J*(jL}CH^Scv$G(Y0$6%D;P;EnKzg zM@NMMa&F!f%J1aGh5Q&A0(_`IfWgp0(AbX|Zrl*W1(0>|;)LjNfe#Z2UdusT0E(@m zK%oy?w+u8gVf21Aj&iP z`-Mt6SzG{1j~)9&DW^|Uk?NgXBWU*#n>K;tym=$K6DJ(;<_J%?$>R0_Yo(q!!=mcz zQ}Jp-_SLIk932&2N6x;!5M(md&~EA8TZ;=I;qc*4)!Is}%wf))(U@JkpybUPz^H&k zB6*Ad_ooP1@18pXOAa2isYHu~dBw*!`y?mB>hW<{Y&L_lQh9}r2(PJ4aRJc#-j?F` z?`I23OP4#jxe2!G9vuzJl$1K{p+mxVw!{U1A+{-kh^njemdWLRe%H|fat{wsRaPd@ zLa}@H*c2Cldi{EFRadjG6pG={iVDE?ceH6Y0uzJg0>EEFq6*)*k)iAT;vNwJ&OScB z#q8L@G~2g}iVGmvWD*tHGMgI^(B&YP1GfEY1j1w#6&FB|(I~2~OG+5Nn13QybWtk1 z0}Td-<|Hb<7ZHX|OtDQ(OqrVc0|9tzwJrE_O!U@}xB$ei6iM6C!h(y6Rucd|Jk9hu fe&0S(eGcGXd0TozQ6I=600000NkvXXu0mjfKWb4+ literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/ltblu-pushpin.png b/GMap.NET/GMap.NET.GtkSharp/Resources/ltblu-pushpin.png new file mode 100644 index 0000000000000000000000000000000000000000..64fb973047bddf701196d0306298c1b38b064061 GIT binary patch literal 1369 zcmV-f1*ZCmP)Px#AY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF* zm;eA5Z<1fdMgRZ+32;bRa{vGf6951U69E94oEQKA1j0!~K~z}7y;p5aQ&$*npk!U*J(!!kG z+*)Lwo~_dP^IOFt(YF{21>E1Za7J7IlYoOvp=j41K1}A87K%D>fL0b3PJC!E3}d_z z@ACl9*(Bh)I6VAC+Q0zij*XE8lfMQw0cp>llm5sNT9%abr;}V>gSmRZPG|y-3YF@2 zb9XoCPMn~)>(?ps)hnI=L#`FcPo7Y4em==OJlffj2}yu8qbfdrLW?7aJbIKq+p~wb zQ>Q5T@ngz)^M-Qpfv*7Oo%CnV=%duszp>^=KrR#k(SijF>SEymZDS)vpE*MjAfn#4 zk3!4Ki9>(=jT@9QILLctGq55rkL<!?|-5 zfjCfCR#Mo(gQPijj3VmlXo*h82owrMz#LgzOqpq&@$$izTF|0{u0VxOp2M33u4Og#H($lB>j`b%`lHu%G{+azoBOanaV3D8SAf^`p zDj|c=*=zaoKe9(h$$aMyZ=4y7K7D!;#!HtdbnjlWx3epr4ITI-cMp1FRS`(rL&<^#`K9|VzNozl;*C$XxEw)FQ?PEQYg2?8wrW^#WF#y`+#MzPLE z2m+xWYqeuL;O=}3Zo#>yL1L4DnDgiVyL*hSL6LHn$$k~07%g%4@oC%k@F9JVfjn!` z$%5{$>*yfu@#B21PbFZuaDhH8Dc|LfKygVzETo|H zCPV8JQGnv_-6Qku+mvwsJ|#YSM6tJSk#}U|OW0d%%Mk>4`}=o(4z=4jK2Bfs_0f9l zju~3l*-2|rhFKt*u3aM&o=wPo4g#cSv4G#;k`k5)-`N_3nx$s*cwBEUB|LaQCK%){ zUL*swpXomfLY4_E7I;`yF{Z7JFVhmKv`C0F)Wqfy?V%7qj{kW33(~^^6EzLePfkx!EeRy8;!=1D#)@-Ci{6xop7~6 z4mi!`{{l;CX({F5euw7-(K|Go2q+Ya+Un|R3JeVFMb~An2`u6`ZnzS6KB-h%CVIza z3xQ1~P&bRk!d`N7P5`2^BR4mfe0_bp(49Bu1jJ%-hEk~{i9})&+0bk`0uOj0W2Sqa btpxr7j27EJF$e`;00000NkvXXu0mjfqPlIz literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/ltblue-dot.png b/GMap.NET/GMap.NET.GtkSharp/Resources/ltblue-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..d21f0c58cf05b7d75740bdc3c6682bbc49837f2a GIT binary patch literal 1301 zcmV+w1?u{VP)8pl~9aC1B!+yDh~u&Rp={bJ`h4KHbTqgN) zb7$^7_dDmF^PM{k0GJrEZ{KD)cki;S%a_@*jt&;RZyyV(sge2R++0{(S_%vE^TAoG1-U};x6;k+7tOkL(fZELe+l6Jxe-7Q2%7Tp67=@H zS4s+`o<9!-4q&@&pP-Mj-#ega3eY^W(=*^y(FSd+;DwTU5e}Mhun1^fY;!Y3;vo2&9}l$5cT<{p!?IScRVb-@!9TynYRstT5lt z?`m>SkDQA@NNsJrwM+(S7cUCooecrg_&8(?4uVWBhb5Jjsayom`|nhNfr2s1&?j|w z3sqp}FovF|1oUq);KN#denbcovzDGr-Q<0 z&!Av*^vejK_jGL@2?^wVufD5`Pl$}Dgof^Jf0>QVgtof+i^Yi6p?m{s$nW|SCp1Q0 zCCtW7Mp}+-*no-jE~249v?44Mk9r2K|4Y}{n3Z?`zF>!&03jcZMDE&^i$)=#y&Vdl zKNr7u%#)(;FBjRsH*RM|@@7_JOX!YtJY*i}AzI97zztayF@?&@y@Sy^} zMq>++#&yhi^QHhU0-2XCO@SU4_%M-SSq|X=P-GDW3VrbU^&gNwkj6?V?fg6z6PM1b00sEa*( zSolp0Tm&%0q979Cb#)#JrSgyEot>a`bp=gDMI0RzwRf*5xCm%BY>-BEHTz1X8VM>d z2ONJxnRX^(Qlz;E;6EWrglyWxQ1yOx2@M5%PtRW?ckX1m9Xlk!MIgXzmITT&oA2w} zZKG5IjssdGgvlrgE&~20lO(<_E@t>*{*hGCL9OobGa4C+lO*_FL>M|LL^U-rb#n6e zM8G39wgvx=NmdPki-1%~5n@|fSU_Rn8X|xX&nlY7?B6em&k^_se_~af++7Pz00000 LNkvXXu0mjfLPuTt literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/msmarker.shadow.png b/GMap.NET/GMap.NET.GtkSharp/Resources/msmarker.shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..f460f3fdcedd3a3763b74528ebaa2ce5f69ebe93 GIT binary patch literal 483 zcmV<90UZ8`P)>grk>XzAXXF{YR`a9)sAITZ?K0Guz;K=5Jg zvdyqDWZ^nu!?IF=m;_b?toX|6PN*uC7JrxwUD=v$TmTM$zT!Il z2k1BOqL&r`6`SU)C)k#1bFwDnOl}T=Q=nmtDcQDEBw?d9;yY3Iy#~%y3Z*<2iL7EA zkD8w9b(MxR))?w*iKykZE#=XTJ#9SElJWAPc^l@@Wj8%~E`NdjQa!e`{_XaMfMBCk zjHkc@5M;dtZ9B$3@SbwBV}p}f!xn)nxjL7d}002ovPDHLkV1k~R&sqQg literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/orange-dot.png b/GMap.NET/GMap.NET.GtkSharp/Resources/orange-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..db63b26a1e3011cbcdd558c976849d4fa426e4da GIT binary patch literal 3443 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 BjVb^D literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/pink-dot.png b/GMap.NET/GMap.NET.GtkSharp/Resources/pink-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..e946fe6033f0e61ffc5e207c61579305140801e3 GIT binary patch literal 1349 zcmV-L1-kl)P)=f;oFd0^83Y7`1($n;f?P$|T`nt@yVi(N z1T1oCFvhEhT*e}T6e~q*h2F$y(%8n(rVXu{v`HZ7{`&hZW`oNjUPsmfmsT5L|1~W6WKE~KF zhEIjmxjD;S71Ok|P;wx=f*p^oWfQ4w`u;SI*c>F$4|;%%8GzA*CRQDg6Xs$gAGZ)B zcZ20#P~epSm40bZ=%t2GdmpfnNd9w~CqG~1pQSn--=ObD{htm1S8yfs5UcWkwis7? zJKZe;&L-`IA94m^S~qOakD5U^|I9AP_K3m}+1(1i)b*D#dY;|_Q>*$|OYrJaG&8h? zm&0`KF#N1N4%e~=;JfU8gQ!jKZ|1%ZJ(26d+}s@M0(Bd{#s1s?pQm@Q!RYD;X2$Nc zD=Xp8ypuRl{{s^ni@wu;uc)d3``znRRmD%@I9velC$_RcJJ0b9w@COMSN5=pjrB+F z2%xiqkIePLJ1e$JxB#{V<;M$X%5%84H?%`f1n`sQRrok%A4miNHZRFe9;3Rz1u&V`$;Q-8zE*<8bZwwk zpJpEifd0eu4T8Dw*QvPrz{&JZK7h+uOsEzdR8}UVBi-5=TJ*?_NZ+v>ljHrnds%VT z)T*QUaX10G^`b%chn4CuDqtw427c3>FgZDG)0n!M_MI$HI(5Gg@fV}C4uh^{9bu)u zDLdp=GQa`#<#+bv*D+G2vX6q7)CII2G2I0HWkwhKB7H_&02f!jY|sQAEjlOw4Sd|yAckHA$3uBL!WA+{+lUr0icOZ zs!dtJwue0DI?uxTpEu&SfwPSrZ1m5HqlxHJVoF>9wE-GY)dgsoy|wHsye|MgZ?=XO zIkYLuMWML>@FpaxtwB1bkhz=-v-brzTgS_L!%EnmWyNf_h`0doI3}tR-xP+2%@N!N z@Rlt+TNkKhc={C;C%_6(mG~ypo#7B=MNg^oX`LdL;Q>}uTmWL`B(rY%yo5I};< z(r&ztiAD{H3!ppVMNv`6t@TNIo&fORS=Ec}PK*LEJq+M~044yQEBSt!00000NkvXX Hu0mjfhe&|T literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/pink-pushpin.png b/GMap.NET/GMap.NET.GtkSharp/Resources/pink-pushpin.png new file mode 100644 index 0000000000000000000000000000000000000000..306499804fbe6467b136ec71838edfba10d0e570 GIT binary patch literal 1424 zcmV;B1#kL^P)Px#AY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF* zm;eA5Z<1fdMgRZ+32;bRa{vGf6951U69E94oEQKA1o=rsK~z}7y;liLlV=!iIa^vm zh87r-uo8`~Y64_{+|UCMY&Wqwl_@CBB_j&k6m&YF;K7+rf*BB*HkCQR1DFC8N)Z@` zX6mkJoH09O2WSwFAuyi3f9Dp0CT8}>FM0Ci|Nrmn`+V>5yk9v0I8*VA5$VErG|dsr zY8UVv+Bsa#PI?zkaC_Fqr`r0T1Z-yuoqLZ*X2TR$0$un{e6yFMrPq+d?_9#HUR61%(`ZpTM2FWC7}x0zR7SGxb)GUOoD(d0?bgZ6o-x(!!@W4 z$v{~^Dh%=i_-Vy4j58z{BpJ=#8C-P&$#bJYd19b_3)mvSaddR9Z&noIY}jtJNOMse znu*H5t*8jxf>wDRE-A}#TU|xoATk?zkiJ+At~IxgEdoxF;*i17WDs&g>f_Edv%YTAvW2Iq>fVwDbJN{a820hUQXo<>2efVxv zQ#g*2;m?A%p_$0k&~v^|5`shvMrhA^CLviNU~6kzaAAcWzc1I*iF3)A#(Z+4Y_EAX zMCG6 z@0UC}k!V0S#h-EYR04gnLaY`?jM3Tv_6cw~nucYEFr==A@v-|S8*h{DLo>PG)5-NK zCR%I}5R%~(p}pWpgm=hq!-e#4a0e<{mH9tjZX-%hrqIChbnq+hQp$H1m; z^poTcuRcxXm;c1+8T3l?q44y3K>NgO5D1T%A3Jh)>n-5DpE0qi2mPyRaBKNdm}L8& zNWga4ejE?l1|i>}ij8LEEq3+lxcT3)>F zwiyC@{ui|0+9CpWJiB8B(R+X`H-U{EB&jW!NIZk_wGDVkA-KA%4Cm>@P1KOiM(iPE z;dJ;e+=wg3A-{J(<_}s#fX{bmsE8)z+jYnj>fB6yIP*#xml;U#i z$G8wvOfp=E3(-Y{V)W76MY_P`1yc#dekn{Pd}wJBD%9R#qy2G}xK1wbC4-&Rc3Y(X z#M}_2F$>XTFz?RG4p4L20ec&}0yfG}<@1vG(aDeQ8PnoNr{{In7OR~`sv5&|cFy93x8#huj`bKdO8LuWVKeCZcDQ3zl z-kI;%Tev<0Iz0wR&jO$oXg z+M>%~Dt8!uG9H6#`T_V>-*18brvKl}eGPhIH-NppJ=7{p8^6Kv%mO~sb&$dMsu*HN z?zAf_;E%i$XsG`o!`9IE^t+c;m4M^!^{Oh9CvYAn0q<#AiNZBtEYmj@e#4bL%CI%R z=Z*jdD+G&uF1)>Bhk!}I_OR8-9J=xx?(GfZ(3}MPXm|xaO5Y0tj)N^r^chS7!d#_| z=mGO&v$@_DKVwWNJwm7#TA2jk9v-GqO{09S#wm2$)&!|(R`jt6AY@=|kY>*N|35Ti z)-Tr4i3V6ba45?!me~VTKrRL%3g~4Lpz@N}1kd+@?{bdL$otv2c0Ukl3}Mx5U=pw^ za$Pjm``cKCF`!*LN~nfkO~-8- zr`t5DZle26Jy0@vzY(!FBW;I;tJ#N1i7dUv%~1?Ep}GA&X#6^6%B21X1d1eJ^iSxf zqQA)OBA@G~VG?k0j{S>OoOp@z~A(V+EMCIKgs>Spkkx*3~P zz&mW!2J$200COyS0dV6Fq!ysK#;EfH(e9XKI;sy%?QfSnTS zLx77H6b5Ok>1t`-Tf-!vKW_632I98Rr%>eJ{Pn)*Quu52NkFdv$8op%Rhy-6qKB+k z&+LIi%QxC&Fn%jZ@K$uCVx_y2e;TTm%vIl3uGw1+9pf_@DOT~u9)?tEM%q5 z(`mlB?8bO3hKxng^?j;M=6AMW5`ZqYNt?2q?1*^AXP(gM@7I&JgSWFQY?5auQA6}n zVhbh#HK7JxYD100-AVi<-WLF$H(MhMJ=&CIyrP)|;7y2^ZDA%N6-&-Vxy!)U#q;uu zQN?7>vLdpZ2POe{9OI=}mQL`nIfB~&LE?pHYZXRu$pJ;&?I00000NkvXXu0mjfM;vr4 literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/purple-dot.png b/GMap.NET/GMap.NET.GtkSharp/Resources/purple-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..c0d40cb7ccf66ad9016e64c47d3c5152e7fec2b0 GIT binary patch literal 1356 zcmV-S1+)5zP)t^%_I+5&BXLI*9BjTg19mrH*TO^Px^d3>e}k+Q|3R0=f&oM>{j#NaFEaZkK3J!V^0I8(X=@ z@J3eH_sVr=h$mLdb!XGNi>}iNXvvvJK@#PRJhT+{Z_4=J5E06VI*|Ir%p>| zj;m$6I0cZEuN6SXTmp2sPLO%11TcKw;kYm>o9DD1P({`O_T&*N0TB=CyYc?PNZAUT z=l2@}V>ot#{S*))P41@>ke_r&#qgP1cEd$BpzbFNNY=EPJ_h{#D((+DDgk!G`zS0R z<8)Yn9`@mF7%p4glyTxMvTe~pW(e_1K1ccjm4F^x37d>_k*)%_8;1CCw#;s(7?JnP zs%LO)2!3nGdhekg+Dh14e1q);CE8O)#6vgp5}&&x!ntu0coxku68TF7$) zs09$nBt`1!Qe4}iMt`2&4ld&)PMVCDfHbaL=) zlfquh^*hyZ&Ayib4BGwxKW`Z*!fOr=+KBO=P*2g1EK~wI^1pV_S#S+KR*Rp5F0@;czvK6hSc}Ig9!K?2r{sDxp zo{$wc+Ss0V1+|#w?}17{edfCxXf}RGTJ(8*{&Q4FvicmwBzU?@7VL&g!Y0EUo5E|M zt^@1Yo%0FWk@#%3tE&jQ3K!W}7{($b-VvadwRDlyHX3F(Kqa6u{k08LrN2&o1@3O* zD@E#~Fj)=IoIQv8zTjq6`nfI5#t%4!Qwb?p0*P&$yrxfFquhV$CsR zR!s%EiM)Qtr541VfuP?uptGjDh{&ac3n~GI_%SDpBV+tN literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/purple-pushpin.png b/GMap.NET/GMap.NET.GtkSharp/Resources/purple-pushpin.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc54ac962933fc16275956ed757c78b9f0a5599 GIT binary patch literal 1418 zcmV;51$Fv~P)Px#AY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF* zm;eA5Z<1fdMgRZ+32;bRa{vGf6951U69E94oEQKA1oKHmK~z}7y;liLR96)JGi)=? z2u3WjNF%s4K&c>MEzB_E42!_Xz6`^#jNrmDQxjZjO;JPSCjl#4sY82~{7V!@HzPx~3lTnR2fU`n^x8@sPSAG~ zVajL{uzSl@@nCgQ7dGnq@lh_YSr1g|fDe-IBP)DA{AOf6mWU>NMPs80LcR%DJ5QQ< ztt6@gS@M%8ns)`|+DE9&0yYqdjnr3Bzarr_B7MtXCvj|Nw~S8$Y>V@DOBu)tYeL$) z2cYra3d7t}SdsV}*6RidM1rzXlLM?y>BgMtIfGOu6*O-GUj!ICTic@rszzjn9!GZg zX{3c5KzzVwgim2moq;L#Dpn?SbD62h2ISr*2rZaxd=aqob`S5a&VGsos#YWfet~q# zM3(#naujEf8oZC*?Lbn{Ze)ZWLVECFcub9ig{7dJF9OM_q17l)A4I;o6*-iF%&;R! z4cUjp!0kv0-UGe7fwHn65wk1trbAFa&C#<3$qNB%E32v%iI=e~zLQ%q8;tF9m1n7M zqAh8JF7zZ^-tf9l!`BjK@>zuArnz|E+Mw+t9k@xs8!6zamtas{zW34^SGHred-?#44d9=EfLT)#a}2AJ{^Zg2DmC{%=T{D5qZL0WY=!dO7 zPk9b0L3=SyEZxJ08BKGU?0(^s1;1cNF{v4u&L&c{b=tqMIPwZIWk)$Lc!_}GJYxN7 zA+nKtP4g|xB48u3-kq(k!mc84j>k&sI_)!*XAGh&?JT$8y!%uq7X;&<;@0Cs>u-LoRm@%Mv=VGVu>GpDrxb{ECv84irV- zAW}cj^UqkQx{evnsy>S6X3iG)x=-=BzC89G1@A}c{5yCr_9wF6n^+Qc4GSYKqd?t8 z{kI$n)a_K57rDAHC@&()cQbnu-Z!@h)wA7`pPHiYz!>u*3L@Ibb}t}Xar!wZ7<&@* zv<=VEz`e^;ws1CWWoc8z$1&76PxN_`7IF}a)Yp(Vw`J(;|5pQE97Q6T5b!yKLSY$S zLKGmj8Qf^Nk2+8C z=yG!m>6z)Qe&FU9+-Gm=`n^EFEa&8V6mG@NadB}E>+0$tl}fk1@Cmvh4PgR7JevOt zj5ReiFqus3fHdYcnpp%K92^eS*Vn_}-~V@d96#0sCTldB-km#lLL?G>%)DkZhrp8R z>S`E`M)sp-%n6XFd{|gm2v1MX8}w*1<^%)+fx*Sa1(ueU@r)VGoGoyoEEq<*=b203 YA9@CK7|n9e!vFvP07*qoM6N<$g7*l79{>OV literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/purple.png b/GMap.NET/GMap.NET.GtkSharp/Resources/purple.png new file mode 100644 index 0000000000000000000000000000000000000000..b57873893261255efa18f98e7c47dcc0473d9bb7 GIT binary patch literal 1324 zcmV+{1=IS8P)4M<@lU=mX*rB z3RD01g*@KQ%kxdZdrvafzyo}#pFev)8^_dr0@&84Dkgn*hbz#uWZCh;6 zV*U(<%T{2#0vwFs=hmDrAwH}UTzF_HC8ncgwf#K_^xJNs9Q9-!o^HTX3*(glW90xt z_7xbkFF6>pFSGyOkKfxLP}u&h6eu!BB2Ve1(|pB%&x4D_*4Sf z$|utJ0zN#H^C^s$!-fYZjFbU9k~m=HN8`gP*udM|;D1BfCCVEC@17|t0px;?YvjA`NkEVD1nGxLfZ_8F$A;S2 zeNHQ&j;IAZlSilo!tXb9;q`;z(q(p^Z#D)-aqI;7Dj`^w)JG+dmv~6c@R^$p#*1t~ zZAO6XniliNfZMO&`k<#0XfVEqLjBWEhx!{}A6|x`(v=MjPG*ZNTU4M0f_;_)aD`JF}mH1PR?-|8~oeW05*6ZRBcXKO*R?vx4f(2d-L zXKzc~J@BmBV?_La#WLb ztA&WV7xP=-|>9I%tYe?r}b zKeA8>wC8>8pdORfbiqOHSk&=X`J%-*=_e@`a>5?;F&Xd&L2DHC)S{ z?ek_~lE?q$?$p1T7oft?xetfR^FAt}-4@%hh@ zA<5TgD<{CiO*-FTyd-Kg&azv0E!277-|Wu*1Z_`vCQB$3LubJP8w*2NLh2O`8hLXk z`PzEp%sQw9D$-tEM`hY;aVdQ=4%CRTS_PA3@l24-#e z4#tovZXfb;_xmbc@fdiz`~8}ma6oD$Go*RmDO3XZCd5fr{5Znbv$sS1ba)4ZeO{nB zf^hD~9CiwofF`P$ljN8-j?j%x#6c6ItF+>HK58~?>A~C=Pl>pb4B9!Z2M%t*B8X|zN i>kpG>vJ1Glo4{WuCnmC}i(NGU0000k}@P)+IczQ& zA;NrSNQ-JT*)vH~JyVp5rATs2iBYZ_)})Xd%u(f4g-)_3WMmDhzOGXKX})9HK;U}G ztaCF;6D1^+1T4>jO*Ybx)0oj`(6pK;8|88C`|*e$?^H#_(#R58P77_XeYNbRcL~!r zu{g2_Ev88-D~5s5^eA*y_Zz~pJsW+AK8&TuB-F*=TCN3;JlrLzwOxN@PYk=Y(;D{7 zJ%9gU#g#br&3#miii8JZ_(CA7P%FSC7fR&+>2=gmiX!FTf62}+E*!r_2xp~Rs9)0as`)ODkmaqQ`?%BPX3-&F1L>GD@ zw<0i1bYqa&)ESdWg^SVKZUWO}tibf3L1Y9*bZclZ$=eG51Q-C}`?8nbZVb}^0000< KMNUMnLSTYaHU&Na literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/pushpin_shadow.png b/GMap.NET/GMap.NET.GtkSharp/Resources/pushpin_shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..162aa0fa79147765d6dc58a68f2532992050711e GIT binary patch literal 713 zcmV;)0yh1LP)h)6H`C8?TZ)7|X!edP=shFvkqepH;m;oWTZVjs?#Gn2?# z+xuTWQGgAw0XDz}*Z><~18ji3kFZe`{T_dK#NzkLm#O1D8-pc42ja^T9M8sp8-ewl z)ERp-^59fO#dU4qO*?A<*oP9x5R_`^sqj<_aFfnD(1B;)cY{Y2EEi>%w@^m+ zDuFwPr3gDm74oTQEE)mWIlBau0;bR$nu!+pttg9hr?3QS5LXAf2R$ZdU5uTh3qbx7 z{Se(?rsVKO?rscQ(z-FE4n6_op=cNI36)b(;_g)RU385(#qV}gch`a~Y1@b#b!${3 z`wXx;A0gI;UfiwM)N^(M&6z$@=)BJIsT)=!`CRly zbU=kucJ3`Z=x1>8qv#W^^QI2{o4^`G_m$|aXdjNo)UH*Ku8>l=c`Evb=-ReGS6#Dx zG^_%@M2v?7TlLp12iP^@`xWc9XcKguHcoH~Qs5)NTkMeqz#}T81@_8wXo7pTZO~Pn zjj?VI2y_Ogt^g2IA^FF^tSiXBg7unM_s(O{Yq<8AiY6=hpW5phZXH;S<_pm~92B%o v-&1t&4NM)dx|g0Hk{{&x1@8Y7fc&`w(KT<-+Z<)900000NkvXXu0mjf`6)(z literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/red-dot.png b/GMap.NET/GMap.NET.GtkSharp/Resources/red-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..b0f3f0e92849bd842cfade65901b74284ec601c0 GIT binary patch literal 1337 zcmV-91;+Y`P)ZdrVtZ9LEo|h4Cn_0t1E7QYe&XX({E=mRBjSLJN!nqf}u$ zM3%Wk6BXT@xTuNKxJb6S!I)8JT;{TwnPpj=B6C}eV=voW5 zH0nq2Yv&sjaqvx}6+AsofXB9Y@$|I7w@p>hs!YI$Wa)_vRsYPr@&8G{eAi~OH(%3< zLE(rw51=0>>}v(jRwpcNZT7N^(ErotACwgUE)Tqvn>j$oGYj~^RZq@TnsRaSg`*_~ zfPr>yqNNAG2^ny~aZ4f1gy)2%&@_#4m;_vHu##+9*ttebJM{naoi1>ze?Q_-)xKwf)=n#_tQ*6{z$zf7h?sl?y z0KJoi9@0idJjWzpxJakPf-*l|SB{2i`**tl4fu6~l@=t=-u!GMlYonLWyBa0b<7kK zh0D+eo^I#5CSUIUGyPTZv9w2=9=DaT6{6{OJHgZ{{Y9eLq1+5E=z59~En2VVYXED= zub%Gi%ZYJB(lXuHD_``IE0|49a-zGNSjgq}B>9@!KvRzg76|wE z`|f&ERp_nOS~AsAE8dR&&)+LEbFL zslcrXxFnnx7IEJzq(RW9Rz5k|XeD3Zd#hm*aN25I!^g-et5G8LlT6`qaHpS3b_?C} zbEm9D30EBDuX z@0A+J_6${ZRKNyUL=O~fj0C&<;lYy?MffbA7bXFRO?qBN&3WXF{G8Z8iTJnAZKbdg zJK~@w&G0C51StbNhFXIDm{-sLI|2s5GDaVsY*cx z(vnG*ENnlmit>=)k6g)e(xTiX2$O*Qm^vY-vF!4=T~t6tT+Hw>G@#I~p)d)ct`_2? vrHJ&YliXB5hf2QfL`5Na7q_Pn4-)VPp(xYTA7S)500000NkvXXu0mjfx@>;Z literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/red-pushpin.png b/GMap.NET/GMap.NET.GtkSharp/Resources/red-pushpin.png new file mode 100644 index 0000000000000000000000000000000000000000..203512d5cdf92a3ccddbd69e84e239272c9b4ed3 GIT binary patch literal 1334 zcmV-61Px#AY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF* zm;eA5Z<1fdMgRZ+32;bRa{vGf6951U69E94oEQKA1fNMnK~z}7#aC@iQ&$*np;U{E z*4he7Mwv2|j}QwOhA}E)#eP@?K|X>A2tg50G^m7RA=$!~Y)I&aKW1s?m3sswh%NK_v%javgE#X@#5~#g$u8GDU~(&JqHK|++K8eMqB@pKw9~#RYWBvL>w&EBq}JFyzbvmWBK`XDKU}Kf`cDJ zna{A_C^Z3pv%mk)FEHL607&<+EY@fH!Y3E5uWnZtJzB(QW41fA}NXYlH0V2 zPQd$vAag&wbHP{(zzm;3 zIG75bgUmUQISQ}yLqq8;wYnY0BBaUzOW)N zUS4h39|fqStOBb8Wk^uq+LkRm0VeYl7?~fCoK@%**jp%hADF999O=r-DZ0 zo9*dS$lvxH`P;W{rPAjW!*w*Z0Dn_pAxXWwNqnOflyD2s|FzzMbylxd#Ss!(az$of*Cb zu;)(T$N2ckM8x&I$VjF_f|wl8Ez@c{dg0|G5V#40?8V=q#ZI+cmV`|DMge?V23oPF z9^t@uK&99+3|ypEcQs(h^gz~DWcgIRH$4YVp&CwMB)iGw?@G~#eCH?>b$KBn+Wh>6OCloZ!>B0w1k4aXTx+r|2Oa4_H z?{GM%y1JTe*u@9|aX>nd3nU9)!R{~R{{pR6Tg!1A*=)8)c=VIaVu>LzABOu|T3QH1 z&d6rD#1P=+uc)YCf6RL21avyxahJ-v4+3l*1qx&$*G#tl0#IU@)NF*~umAu607*qoM6N<$g45SsZvX%Q literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/red.png b/GMap.NET/GMap.NET.GtkSharp/Resources/red.png new file mode 100644 index 0000000000000000000000000000000000000000..e993751a97f826fb021fe765936d398c098640d7 GIT binary patch literal 1305 zcmV+!1?KvRP)XEg+VE=0t4mIQd%e!C@rNtT3#*XRoVihzzP@` z50Paq(L_ZzCmJ4CzdOY`Y zRvhhsJ4t?N!qe% zoH$|dIljODQchF^bfzZ5PL%?>@KYNd349)JIZhaK;W@QZKW;7K#Qzt8*$xMJR;_#t z-*&!U8V}z!Sis%m1bBR_2X{|1eBW3FEwUtxNS2;dDf(ybjejVC`K~QwZ@#({gTj&G zJb-?ju&)K&+nlhpt;xeOLjO;ne^g!oxIOT4Zsq_T&n)m$n~j{QH0I*u3r9=!00S;= zqNNAGi43&CadRPE3HJ$ep>Z1HFbQ0(w~%ac__+pLcIaPw@|D07F6dB5K@ldJ_{MJL zGYPz|%QEu({oz_;B|vY>x+muZdYj>9b1evX{;*4vUdbe&j*568Qyjqs+sNCm%n5x= z6v)FwLrenrci4$pO%rP)lY3SH$91J8(?BDv0%P52vWF7bnUzWdjj;+Gtd}Nm=bTlb zO(CIy4lxNB-OlyBefQtXUzHF?d&KE+YdKpXns(XAC7VeW z$m7ip<*K-#>)8rgwBF2D1J;n=zp$32-^Dmg0yA7MXrgV{jEOY2uTZn*iJ;F%OY&&q zEgmpv>lUyV%&_(XI*_t}5{HbsM%s|hR26gE;eFp*VZvtO8WFBQ=Rb{zy&1V|9_Bi? zknI`rJ>pG)Fx~C|!1nu}$uU3v>}mp8Xb8Acl7^}DFKrHTx6RJMByg+6>fv^49l5i$ zj+Yu9dfAmCSydb8(&L2%A_4<`xZYS5cB`e9Of}bdU=oY8%akZbt;l`sihs4ZQ^6}y?J#Sx!5Wr?0upl| z8+aMNL$7cvVXg!BbJbBn-Y&?gz@rJcC0s5n;<=ZKgwUsyJvG^2Az$J5?uSX>w8gNB zPmxm=gFqA@n8NMgZaC)9I$Krj6()hvVx3n$DASW2Dn)g4&?Z>K94Ocv1$N1!gC{GB@L9fBm;??R zbzT`Q&LeN-=fnjI_^|1e$b#L2YkRJ(5saB1j{nP%jU;I zfdEp%MCb8G2*G6Z36nrin#?By>2i`K4&P6!q9iorlQy}8G|Liw!X&UCm(CY7vFwug z-Bh3=K6dyRCZMlVLtzr2S?!CH<|5LkOzEHk?Fz~E6BUKzeLSANc#yzfrSS5=y^?vy P00000NkvXXu0mjfV_aiO literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/red_small.png b/GMap.NET/GMap.NET.GtkSharp/Resources/red_small.png new file mode 100644 index 0000000000000000000000000000000000000000..f960799b3ce3d623543db0467c535ddaca6fd66f GIT binary patch literal 562 zcmV-20?qx2P)OgJLAPVZXV3PE!T%o#nntZqRygBfLuG^ALFIYY z?_wi_O3vIoYRq@=$jydiOigMn{2qcd4W?wn>EY`$9Yw;}k@Qn*mgpR{{cwm!em1P4 zk(l@51dCu5lj+N0r~bW{CzKE(!CId32|Qm!-}-{lHyUudwZ65GWE%4y(AvW-kEXze z(Ze1uei(V_aGwjp9gc9cDKbheTxf=wD${Fu7yuxA1H<(eV6{Y zs*cztg@W-YTDjreDChq;LfWjbSVf&RpJzYT-`SrrtiK&*hO&qX@U9!0voY}91ORT5 z3et;m1_NKh1BmISe+?WV-ALIQu7NF6;ZuMC0OWR^kF0-JxBvhE07*qoM6N<$f{;M? AD*ylh literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/shadow_small.png b/GMap.NET/GMap.NET.GtkSharp/Resources/shadow_small.png new file mode 100644 index 0000000000000000000000000000000000000000..3a89759fca2a68217f42a4ef95851a179df425aa GIT binary patch literal 436 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 literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/white_small.png b/GMap.NET/GMap.NET.GtkSharp/Resources/white_small.png new file mode 100644 index 0000000000000000000000000000000000000000..cf2a8e9dd1e6f3f6c03ca5d5a31eac626d714245 GIT binary patch literal 473 zcmV;~0Ve*5P)VJNIK1|bWm|{DSKz4Tae_Wujun?xn6>K^;H~0U?k00aI z0J4>zpC9ZrCLp1pudmM_BO}9r3y6!0GZ-2gf|#-(4S#?9_`yI3K-K&M5p7INO#d%j zxPa41*REar&&tXQa#A-)gC-Dv_wexe|L@;FtQ!3M{6LC-0kIy;#%xe1BqkHxi6G06i@E(?Kh}G}_h`F&z00bBSTUGuT&J?=T P00000NkvXXu0mjf-jdKF literal 0 HcmV?d00001 diff --git a/GMap.NET/GMap.NET.GtkSharp/Resources/yellow-dot.png b/GMap.NET/GMap.NET.GtkSharp/Resources/yellow-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..79974d60ce2887f06cd59b9032b0cda6087c0b5d GIT binary patch literal 1341 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 Date: Sat, 4 Jun 2022 10:48:59 -0500 Subject: [PATCH 2/2] Demo.GtkSharp --- Demo/Demo.AvaloniaUi/Demo.AvaloniaUi.csproj | 11 +++++ Demo/Demo.GtkSharp/Class1.cs | 7 +++ Demo/Demo.GtkSharp/Demo.GtkSharp.csproj | 22 +++++++++ Demo/Demo.GtkSharp/MainWindow.cs | 32 +++++++++++++ Demo/Demo.GtkSharp/Program.cs | 17 +++++++ Demo/Demo.GtkSharp/gtk-gui/MainWindow.cs | 48 +++++++++++++++++++ Demo/Demo.GtkSharp/gtk-gui/generated.cs | 29 +++++++++++ Demo/Demo.GtkSharp/gtk-gui/gui.stetic | 47 ++++++++++++++++++ GMap.NET.sln | 13 ++++- .../GMap.NET.Avalonia.csproj | 14 +++++- GMap.NET/GMap.NET.Avalonia/GMapControl.cs | 2 +- GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj | 26 ++++++---- GMap.NET/GMap.NET.Core/Internals/Core.cs | 20 ++++---- .../GMap.NET.GtkSharp.csproj | 10 ++++ .../GMap.NET.GtkSharp/GMapControl.cs | 2 +- .../GMap.NET.GtkSharp/GMapImage.cs | 2 +- .../GMap.NET.WindowsForms.Utils.csproj | 14 +++++- .../GMap.NET.WindowsForms.csproj | 14 ++++-- .../GMap.NET.WindowsPresentation.csproj | 10 ++++ .../GMapControl.cs | 2 +- 20 files changed, 311 insertions(+), 31 deletions(-) create mode 100644 Demo/Demo.GtkSharp/Class1.cs create mode 100644 Demo/Demo.GtkSharp/Demo.GtkSharp.csproj create mode 100644 Demo/Demo.GtkSharp/MainWindow.cs create mode 100644 Demo/Demo.GtkSharp/Program.cs create mode 100644 Demo/Demo.GtkSharp/gtk-gui/MainWindow.cs create mode 100644 Demo/Demo.GtkSharp/gtk-gui/generated.cs create mode 100644 Demo/Demo.GtkSharp/gtk-gui/gui.stetic diff --git a/Demo/Demo.AvaloniaUi/Demo.AvaloniaUi.csproj b/Demo/Demo.AvaloniaUi/Demo.AvaloniaUi.csproj index 2fe1d63e..d0bf2e7e 100644 --- a/Demo/Demo.AvaloniaUi/Demo.AvaloniaUi.csproj +++ b/Demo/Demo.AvaloniaUi/Demo.AvaloniaUi.csproj @@ -6,6 +6,17 @@ default true + + + NETFRAMEWORK + + + NETSTANDARD + + + NETCORE + + diff --git a/Demo/Demo.GtkSharp/Class1.cs b/Demo/Demo.GtkSharp/Class1.cs new file mode 100644 index 00000000..86de2d18 --- /dev/null +++ b/Demo/Demo.GtkSharp/Class1.cs @@ -0,0 +1,7 @@ +namespace Demo.GtkSharp +{ + public class Class1 + { + + } +} \ No newline at end of file diff --git a/Demo/Demo.GtkSharp/Demo.GtkSharp.csproj b/Demo/Demo.GtkSharp/Demo.GtkSharp.csproj new file mode 100644 index 00000000..bdd0372c --- /dev/null +++ b/Demo/Demo.GtkSharp/Demo.GtkSharp.csproj @@ -0,0 +1,22 @@ + + + + net46;net47;net48 + enable + latest + true + WinExe + Demo.GtkSharp.MainClass + + + + + + + + + + + + + diff --git a/Demo/Demo.GtkSharp/MainWindow.cs b/Demo/Demo.GtkSharp/MainWindow.cs new file mode 100644 index 00000000..66d29a56 --- /dev/null +++ b/Demo/Demo.GtkSharp/MainWindow.cs @@ -0,0 +1,32 @@ +using System; +using Gtk; +using GMap.NET.MapProviders; +using GMap.NET; + +public partial class MainWindow: Gtk.Window +{ + public MainWindow() + : base(Gtk.WindowType.Toplevel) + { + Build(); + + // config map + MainMap.MapProvider = GMapProviders.OpenStreetMap; + MainMap.Position = new PointLatLng(59.93900, 30.31646); + MainMap.MinZoom = 0; + MainMap.MaxZoom = 24; + MainMap.Zoom = 9; + } + + protected void OnDeleteEvent(object sender, DeleteEventArgs a) + { + Gtk.Application.Quit(); + a.RetVal = true; + } + + public override void Destroy() + { + MainMap.Destroy(); + base.Destroy(); + } +} diff --git a/Demo/Demo.GtkSharp/Program.cs b/Demo/Demo.GtkSharp/Program.cs new file mode 100644 index 00000000..44996f54 --- /dev/null +++ b/Demo/Demo.GtkSharp/Program.cs @@ -0,0 +1,17 @@ +using System; +using Gtk; + +namespace Demo.GtkSharp +{ + class MainClass + { + [STAThread] + public static void Main(string[] args) + { + Gtk.Application.Init(); + MainWindow win = new MainWindow(); + win.Show(); + Gtk.Application.Run(); + } + } +} diff --git a/Demo/Demo.GtkSharp/gtk-gui/MainWindow.cs b/Demo/Demo.GtkSharp/gtk-gui/MainWindow.cs new file mode 100644 index 00000000..f24a6c98 --- /dev/null +++ b/Demo/Demo.GtkSharp/gtk-gui/MainWindow.cs @@ -0,0 +1,48 @@ + +// This file has been generated by the GUI designer. Do not modify. + +public partial class MainWindow +{ + private global::Gtk.HBox hbox1; + + private global::GMap.NET.GtkSharp.GMapControl MainMap; + + protected virtual void Build () + { + global::Stetic.Gui.Initialize (this); + // Widget MainWindow + this.Name = "MainWindow"; + this.Title = global::Mono.Unix.Catalog.GetString ("MainWindow"); + this.WindowPosition = ((global::Gtk.WindowPosition)(4)); + // Container child MainWindow.Gtk.Container+ContainerChild + this.hbox1 = new global::Gtk.HBox (); + this.hbox1.Name = "hbox1"; + this.hbox1.Spacing = 6; + // Container child hbox1.Gtk.Box+BoxChild + this.MainMap = new global::GMap.NET.GtkSharp.GMapControl (); + this.MainMap.Name = "MainMap"; + this.MainMap.MaxZoom = 0; + this.MainMap.MinZoom = 0; + this.MainMap.MouseWheelZoomEnabled = true; + this.MainMap.ShowTileGridLines = false; + this.MainMap.GrayScaleMode = false; + this.MainMap.NegativeMode = false; + this.MainMap.Bearing = 0F; + this.MainMap.Zoom = 0; + this.MainMap.RoutesEnabled = false; + this.MainMap.PolygonsEnabled = false; + this.MainMap.MarkersEnabled = false; + this.MainMap.CanDragMap = true; + this.hbox1.Add (this.MainMap); + global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.MainMap])); + w1.Position = 0; + this.Add (this.hbox1); + if ((this.Child != null)) { + this.Child.ShowAll (); + } + this.DefaultWidth = 400; + this.DefaultHeight = 300; + this.Show (); + this.DeleteEvent += new global::Gtk.DeleteEventHandler (this.OnDeleteEvent); + } +} diff --git a/Demo/Demo.GtkSharp/gtk-gui/generated.cs b/Demo/Demo.GtkSharp/gtk-gui/generated.cs new file mode 100644 index 00000000..9ef33639 --- /dev/null +++ b/Demo/Demo.GtkSharp/gtk-gui/generated.cs @@ -0,0 +1,29 @@ + +// This file has been generated by the GUI designer. Do not modify. +namespace Stetic +{ + internal class Gui + { + private static bool initialized; + + internal static void Initialize (Gtk.Widget iconRenderer) + { + if ((Stetic.Gui.initialized == false)) { + Stetic.Gui.initialized = true; + } + } + } + + internal class ActionGroups + { + public static Gtk.ActionGroup GetActionGroup (System.Type type) + { + return Stetic.ActionGroups.GetActionGroup (type.FullName); + } + + public static Gtk.ActionGroup GetActionGroup (string name) + { + return null; + } + } +} diff --git a/Demo/Demo.GtkSharp/gtk-gui/gui.stetic b/Demo/Demo.GtkSharp/gtk-gui/gui.stetic new file mode 100644 index 00000000..c8bc450a --- /dev/null +++ b/Demo/Demo.GtkSharp/gtk-gui/gui.stetic @@ -0,0 +1,47 @@ + + + + .. + + + + + + + + + MainWindow + CenterOnParent + + + + + 6 + + + + 0 + 0 + True + False + False + False + 0 + 0 + False + False + False + True + + + 0 + False + + + + + + + + + \ No newline at end of file diff --git a/GMap.NET.sln b/GMap.NET.sln index 8daad47f..a201291c 100644 --- a/GMap.NET.sln +++ b/GMap.NET.sln @@ -63,7 +63,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GMap.NET.WindowsForms.Utils EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.Testing", "Testing\Demo.Testing\Demo.Testing.csproj", "{CE9F0FDA-1271-4E69-9369-2634688E2FC0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GMap.NET.GtkSharp", "GMap.NET\GMap.NET.GtkSharp\GMap.NET.GtkSharp.csproj", "{DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GMap.NET.GtkSharp", "GMap.NET\GMap.NET.GtkSharp\GMap.NET.GtkSharp.csproj", "{DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.GtkSharp", "Demo\Demo.GtkSharp\Demo.GtkSharp.csproj", "{EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -256,6 +258,14 @@ Global {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}.Release|Any CPU.Build.0 = Release|Any CPU + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -284,6 +294,7 @@ Global {839D3F3C-D762-44D8-A3C7-50B3105C61C2} = {E797B22B-142C-4068-8F18-9E7E2C7B422C} {CE9F0FDA-1271-4E69-9369-2634688E2FC0} = {CEB4956F-6094-4268-972D-D46CF6792A84} {DF7EF3F6-AAE9-4072-9B15-550AF959A1B0} = {E797B22B-142C-4068-8F18-9E7E2C7B422C} + {EBB10D77-27CA-4A76-A7C7-C667E4E83F8D} = {7C6014F2-A785-4632-91AE-C5181F78C0FC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {121217E7-9EA2-4663-8B5C-E6E1F37A5CA9} diff --git a/GMap.NET/GMap.NET.Avalonia/GMap.NET.Avalonia.csproj b/GMap.NET/GMap.NET.Avalonia/GMap.NET.Avalonia.csproj index f7745cde..61a8274f 100644 --- a/GMap.NET/GMap.NET.Avalonia/GMap.NET.Avalonia.csproj +++ b/GMap.NET/GMap.NET.Avalonia/GMap.NET.Avalonia.csproj @@ -15,8 +15,18 @@ History Release Notes https://github.com/judero01col/GMap.NET/blob/master/README.md#release-notes - - + + + + NETFRAMEWORK;MONO_disabled;SQLite;MySQL_disabled;PostgreSQL_disabled;$(DefineConstants) + + + NETSTANDARD;MONO_disabled;SQLite;MySQL_disabled;PostgreSQL_disabled;$(DefineConstants) + + + NETCORE;MONO_disabled;SQLite;MySQL_disabled;PostgreSQL_disabled;$(DefineConstants) + + diff --git a/GMap.NET/GMap.NET.Avalonia/GMapControl.cs b/GMap.NET/GMap.NET.Avalonia/GMapControl.cs index e9918593..2a8f0231 100644 --- a/GMap.NET/GMap.NET.Avalonia/GMapControl.cs +++ b/GMap.NET/GMap.NET.Avalonia/GMapControl.cs @@ -1946,7 +1946,7 @@ public void ReloadMap() _core.ReloadMap(); } -#if !NET46 +#if !NETFRAMEWORK public Task ReloadMapAsync() { diff --git a/GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj b/GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj index f0bfbed4..42e76a8e 100644 --- a/GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj +++ b/GMap.NET/GMap.NET.Core/GMap.NET.Core.csproj @@ -5,9 +5,7 @@ GMap.NET.Core GMap.NET.Core GMap.NET - net46;net47;net48;netstandard2.0;netcoreapp3.1;net5.0;net6.0 - MONO_disabled;SQLite;MySQL_disabled;PostgreSQL_disabled;$(DefineConstants) - + net46;net47;net48;netstandard2.0;netcoreapp3.1;net5.0;net6.0 - New Provider OpenStreetMapGraphHopper - Fix OpenStreetMap GetRoute @@ -19,13 +17,23 @@ https://github.com/judero01col/GMap.NET/blob/master/README.md#release-notes - - - - - - + + NETFRAMEWORK;MONO_disabled;SQLite;MySQL_disabled;PostgreSQL_disabled;$(DefineConstants) + + + NETSTANDARD;MONO_disabled;SQLite;MySQL_disabled;PostgreSQL_disabled;$(DefineConstants) + + + NETCORE;MONO_disabled;SQLite;MySQL_disabled;PostgreSQL_disabled;$(DefineConstants) + + + + + + + + 4.8.3 diff --git a/GMap.NET/GMap.NET.Core/Internals/Core.cs b/GMap.NET/GMap.NET.Core/Internals/Core.cs index 5d2c4f9b..1e3f89d0 100644 --- a/GMap.NET/GMap.NET.Core/Internals/Core.cs +++ b/GMap.NET/GMap.NET.Core/Internals/Core.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using GMap.NET.MapProviders; using GMap.NET.Projections; -#if NET46 +#if NETFRAMEWORK using System.Collections.Concurrent; #endif @@ -57,7 +57,7 @@ internal sealed class Core : IDisposable internal List TileDrawingList = new List(); internal FastReaderWriterLock TileDrawingListLock = new FastReaderWriterLock(); -#if !NET46 +#if !NETFRAMEWORK public readonly Stack TileLoadQueue = new Stack(); #endif @@ -615,7 +615,7 @@ public void ReloadMap() } } -#if !NET46 +#if !NETFRAMEWORK public Task ReloadMapAsync() { ReloadMap(); @@ -768,7 +768,7 @@ public void CancelAsyncTasks() { if (IsStarted) { -#if NET46 +#if NETFRAMEWORK //TODO: clear loading #else Monitor.Enter(TileLoadQueue); @@ -794,7 +794,7 @@ public void CancelAsyncTasks() volatile int _okZoom; volatile int _skipOverZoom; -#if NET46 +#if NETFRAMEWORK internal static readonly BlockingCollection TileLoadQueue4 = new BlockingCollection(new ConcurrentStack()); @@ -1213,7 +1213,7 @@ void UpdateBounds() TileDrawingListLock.ReleaseWriterLock(); } -#if NET46 +#if NETFRAMEWORK Interlocked.Exchange(ref _loadWaitCount, 0); #else Monitor.Enter(TileLoadQueue); @@ -1226,7 +1226,7 @@ void UpdateBounds() foreach (var p in TileDrawingList) { var task = new LoadTask(p.PosXY, Zoom, this); -#if NET46 +#if NETFRAMEWORK AddLoadTask(task); #else { @@ -1243,7 +1243,7 @@ void UpdateBounds() TileDrawingListLock.ReleaseReaderLock(); } -#if !NET46 +#if !NETFRAMEWORK #region -- starts loader threads if needed -- lock (_gThreadPool) @@ -1270,7 +1270,7 @@ void UpdateBounds() _lastTileLoadStart = DateTime.Now; Debug.WriteLine("OnTileLoadStart - at zoom " + Zoom + ", time: " + _lastTileLoadStart.TimeOfDay); } -#if !NET46 +#if !NETFRAMEWORK _loadWaitCount = 0; Monitor.PulseAll(TileLoadQueue); } @@ -1360,7 +1360,7 @@ void Dispose(bool disposing) TileDrawingListLock.ReleaseWriterLock(); } -#if NET46 +#if NETFRAMEWORK //TODO: maybe #else // cancel waiting loaders diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp.csproj b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp.csproj index ccea51f9..ec3cfb57 100644 --- a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp.csproj +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp.csproj @@ -16,6 +16,16 @@ https://github.com/judero01col/GMap.NET/blob/master/README.md#release-notes + + NETFRAMEWORK + + + NETSTANDARD + + + NETCORE + + diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapControl.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapControl.cs index 40cc0be7..05e8faa0 100644 --- a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapControl.cs +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapControl.cs @@ -995,7 +995,7 @@ public Bitmap ToBitmap(Action waitTilesCount = null, bool runningFromMainTh { Console.WriteLine($"waiting {Core._loadWaitCount}"); - #if NET46 + #if NETFRAMEWORK if (lastCount != Core.TileLoadQueue4.Count) waitTilesCount?.Invoke(Core.TileLoadQueue4.Count); #endif diff --git a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapImage.cs b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapImage.cs index 2191146f..b0a1eed1 100644 --- a/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapImage.cs +++ b/GMap.NET/GMap.NET.GtkSharp/GMap.NET.GtkSharp/GMapImage.cs @@ -53,7 +53,7 @@ public static void Enable() internal ColorMatrix ColorMatrix; #endif - static readonly bool Win7OrLater = Stuff.IsRunningOnWin7orLater(); + static readonly bool Win7OrLater = Stuff.IsRunningOnWin7OrLater(); public override PureImage FromStream(Stream stream) { diff --git a/GMap.NET/GMap.NET.WindowsForms.Utils/GMap.NET.WindowsForms.Utils.csproj b/GMap.NET/GMap.NET.WindowsForms.Utils/GMap.NET.WindowsForms.Utils.csproj index aba04ff6..2192dfad 100644 --- a/GMap.NET/GMap.NET.WindowsForms.Utils/GMap.NET.WindowsForms.Utils.csproj +++ b/GMap.NET/GMap.NET.WindowsForms.Utils/GMap.NET.WindowsForms.Utils.csproj @@ -13,8 +13,18 @@ Use .DumpMarkers() or .DumpRoute() to add markers or route lines to a map in a new result pane - - + + + NETFRAMEWORK + + + NETSTANDARD + + + NETCORE + + + diff --git a/GMap.NET/GMap.NET.WindowsForms/GMap.NET.WindowsForms.csproj b/GMap.NET/GMap.NET.WindowsForms/GMap.NET.WindowsForms.csproj index 7fd0f24b..c045d891 100644 --- a/GMap.NET/GMap.NET.WindowsForms/GMap.NET.WindowsForms.csproj +++ b/GMap.NET/GMap.NET.WindowsForms/GMap.NET.WindowsForms.csproj @@ -6,9 +6,7 @@ GMap.NET.WindowsForms net46;net47;net48;netcoreapp3.1;net5.0-windows;net6.0-windows - true - ContinuesMapNo;$(DefineConstants) - + true - Insert and IndexOf are implemented in ObservableCollection - .Net Framework 4.6, 4.7, 4.8 support added @@ -19,6 +17,16 @@ https://github.com/judero01col/GMap.NET/blob/master/README.md#release-notes + + NETFRAMEWORK;ContinuesMapNo;$(DefineConstants) + + + NETSTANDARD;ContinuesMapNo;$(DefineConstants) + + + NETCORE;ContinuesMapNo;$(DefineConstants) + + diff --git a/GMap.NET/GMap.NET.WindowsPresentation/GMap.NET.WindowsPresentation.csproj b/GMap.NET/GMap.NET.WindowsPresentation/GMap.NET.WindowsPresentation.csproj index 03615c56..865c24e7 100644 --- a/GMap.NET/GMap.NET.WindowsPresentation/GMap.NET.WindowsPresentation.csproj +++ b/GMap.NET/GMap.NET.WindowsPresentation/GMap.NET.WindowsPresentation.csproj @@ -17,6 +17,16 @@ https://github.com/judero01col/GMap.NET/blob/master/README.md#release-notes + + NETFRAMEWORK + + + NETSTANDARD + + + NETCORE + + diff --git a/GMap.NET/GMap.NET.WindowsPresentation/GMapControl.cs b/GMap.NET/GMap.NET.WindowsPresentation/GMapControl.cs index e7c7d72a..cb42681c 100644 --- a/GMap.NET/GMap.NET.WindowsPresentation/GMapControl.cs +++ b/GMap.NET/GMap.NET.WindowsPresentation/GMapControl.cs @@ -2529,7 +2529,7 @@ public void ReloadMap() _core.ReloadMap(); } -#if !NET46 +#if !NETFRAMEWORK public Task ReloadMapAsync() { return _core.ReloadMapAsync();