Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2287 - 1

2
namespace GMap.NET.WindowsPresentation
3
{
4
   using System;
5
   using System.Collections.Generic;
6
   using System.Collections.ObjectModel;
7
   using System.ComponentModel;
8
   using System.Globalization;
9
   using System.Linq;
10
   using System.Windows;
11
   using System.Windows.Controls;
12
   using System.Windows.Data;
13
   using System.Windows.Input;
14
   using System.Windows.Media;
15
   using System.Windows.Media.Effects;
16
   using System.Windows.Media.Imaging;
17
   using System.Windows.Shapes;
18
   using System.Windows.Threading;
19
   using GMap.NET;
20
   using GMap.NET.Internals;
21
   using System.Diagnostics;
22
   using GMap.NET.MapProviders;
23
   using System.Windows.Media.Animation;
24
   using GMap.NET.Projections;
25
 
26
   /// <summary>
27
   /// GMap.NET control for Windows Presentation
28
   /// </summary>
29
   public partial class GMapControl : ItemsControl, Interface, IDisposable
30
   {
31
      #region DependencyProperties and related stuff
32
 
33
      public System.Windows.Point MapPoint
34
      {
35
         get
36
         {
37
            return (System.Windows.Point)GetValue(MapPointProperty);
38
         }
39
         set
40
         {
41
            SetValue(MapPointProperty, value);
42
         }
43
      }
44
 
45
 
46
      // Using a DependencyProperty as the backing store for point.  This enables animation, styling, binding, etc...
47
      public static readonly DependencyProperty MapPointProperty =
48
             DependencyProperty.Register("MapPoint", typeof(System.Windows.Point), typeof(GMapControl), new PropertyMetadata(new Point(), OnMapPointPropertyChanged));
49
 
50
 
51
      private static void OnMapPointPropertyChanged(DependencyObject source,
52
      DependencyPropertyChangedEventArgs e)
53
      {
54
         Point temp = (Point)e.NewValue;
55
         (source as GMapControl).Position = new PointLatLng(temp.X, temp.Y);
56
      }
57
 
58
      public static readonly DependencyProperty MapProviderProperty = DependencyProperty.Register("MapProvider", typeof(GMapProvider), typeof(GMapControl), new UIPropertyMetadata(EmptyProvider.Instance, new PropertyChangedCallback(MapProviderPropertyChanged)));
59
 
60
      /// <summary>
61
      /// type of map
62
      /// </summary>
63
      [Browsable(false)]
64
      public GMapProvider MapProvider
65
      {
66
         get
67
         {
68
            return GetValue(MapProviderProperty) as GMapProvider;
69
         }
70
         set
71
         {
72
            SetValue(MapProviderProperty, value);
73
         }
74
      }
75
 
76
      private static void MapProviderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
77
      {
78
         GMapControl map = (GMapControl)d;
79
         if(map != null && e.NewValue != null)
80
         {
81
            Debug.WriteLine("MapType: " + e.OldValue + " -> " + e.NewValue);
82
 
83
            RectLatLng viewarea = map.SelectedArea;
84
            if(viewarea != RectLatLng.Empty)
85
            {
86
               map.Position = new PointLatLng(viewarea.Lat - viewarea.HeightLat / 2, viewarea.Lng + viewarea.WidthLng / 2);
87
            }
88
            else
89
            {
90
               viewarea = map.ViewArea;
91
            }
92
 
93
            map.Core.Provider = e.NewValue as GMapProvider;
94
 
95
            map.Copyright = null;
96
            if(!string.IsNullOrEmpty(map.Core.Provider.Copyright))
97
            {
98
               map.Copyright = new FormattedText(map.Core.Provider.Copyright, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface("GenericSansSerif"), 9, Brushes.Navy);
99
            }
100
 
101
            if(map.Core.IsStarted && map.Core.zoomToArea)
102
            {
103
               // restore zoomrect as close as possible
104
               if(viewarea != RectLatLng.Empty && viewarea != map.ViewArea)
105
               {
106
                  int bestZoom = map.Core.GetMaxZoomToFitRect(viewarea);
107
                  if(bestZoom > 0 && map.Zoom != bestZoom)
108
                  {
109
                     map.Zoom = bestZoom;
110
                  }
111
               }
112
            }
113
         }
114
      }
115
 
116
      public static readonly DependencyProperty ZoomProperty = DependencyProperty.Register("Zoom", typeof(double), typeof(GMapControl), new UIPropertyMetadata(0.0, new PropertyChangedCallback(ZoomPropertyChanged), new CoerceValueCallback(OnCoerceZoom)));
117
 
118
      /// <summary>
119
      /// map zoom
120
      /// </summary>
121
      [Category("GMap.NET")]
122
      public double Zoom
123
      {
124
         get
125
         {
126
            return (double)(GetValue(ZoomProperty));
127
         }
128
         set
129
         {
130
            SetValue(ZoomProperty, value);
131
         }
132
      }
133
 
134
      private static object OnCoerceZoom(DependencyObject o, object value)
135
      {
136
         GMapControl map = o as GMapControl;
137
         if(map != null)
138
         {
139
            double result = (double)value;
140
            if(result > map.MaxZoom)
141
            {
142
               result = map.MaxZoom;
143
            }
144
            if(result < map.MinZoom)
145
            {
146
               result = map.MinZoom;
147
            }
148
 
149
            return result;
150
         }
151
         else
152
         {
153
            return value;
154
         }
155
      }
156
 
157
      private ScaleModes scaleMode = ScaleModes.Integer;
158
 
159
      /// <summary>
160
      /// Specifies, if a floating map scale is displayed using a 
161
      /// stretched, or a narrowed map.
162
      /// If <code>ScaleMode</code> is <code>ScaleDown</code>,
163
      /// then a scale of 12.3 is displayed using a map zoom level of 13
164
      /// resized to the lower level. If the parameter is <code>ScaleUp</code> ,
165
      /// then the same scale is displayed using a zoom level of 12 with an
166
      /// enlarged scale. If the value is <code>Dynamic</code>, then until a
167
      /// remainder of 0.25 <code>ScaleUp</code> is applied, for bigger
168
      /// remainders <code>ScaleDown</code>.
169
      /// </summary>
170
      [Category("GMap.NET")]
171
      [Description("map scale type")]
172
      public ScaleModes ScaleMode
173
      {
174
         get
175
         {
176
            return scaleMode;
177
         }
178
         set
179
         {
180
            scaleMode = value;
181
            InvalidateVisual();
182
         }
183
      }
184
 
185
      private static void ZoomPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
186
      {
187
         GMapControl map = (GMapControl)d;
188
         if(map != null && map.MapProvider.Projection != null)
189
         {
190
            double value = (double)e.NewValue;
191
 
192
            Debug.WriteLine("Zoom: " + e.OldValue + " -> " + value);
193
 
194
            double remainder = value % 1;
195
            if(map.ScaleMode != ScaleModes.Integer && remainder != 0 && map.ActualWidth > 0)
196
            {
197
               bool scaleDown;
198
 
199
               switch(map.ScaleMode)
200
               {
201
                  case ScaleModes.ScaleDown:
202
                  scaleDown = true;
203
                  break;
204
 
205
                  case ScaleModes.Dynamic:
206
                  scaleDown = remainder > 0.25;
207
                  break;
208
 
209
                  default:
210
                  scaleDown = false;
211
                  break;
212
               }
213
 
214
               if(scaleDown)
215
                  remainder--;
216
 
217
               double scaleValue = Math.Pow(2d, remainder);
218
               {
219
                  if(map.MapScaleTransform == null)
220
                  {
221
                     map.MapScaleTransform = map.lastScaleTransform;
222
                  }
223
                  map.MapScaleTransform.ScaleX = scaleValue;
224
                  map.MapScaleTransform.ScaleY = scaleValue;
225
 
226
                  map.Core.scaleX = 1 / scaleValue;
227
                  map.Core.scaleY = 1 / scaleValue;
228
 
229
                  map.MapScaleTransform.CenterX = map.ActualWidth / 2;
230
                  map.MapScaleTransform.CenterY = map.ActualHeight / 2;
231
               }
232
 
233
               map.Core.Zoom = Convert.ToInt32(scaleDown ? Math.Ceiling(value) : value - remainder);
234
            }
235
            else
236
            {
237
               map.MapScaleTransform = null;
238
               map.Core.scaleX = 1;
239
               map.Core.scaleY = 1;
240
               map.Core.Zoom = (int)Math.Floor(value);
241
            }
242
 
243
            if(map.IsLoaded)
244
            {
245
               map.ForceUpdateOverlays();
246
               map.InvalidateVisual(true);
247
            }
248
         }
249
      }
250
 
251
      readonly ScaleTransform lastScaleTransform = new ScaleTransform();
252
 
253
      #endregion
254
 
255
      readonly Core Core = new Core();
256
      //GRect region;
257
      delegate void MethodInvoker();
258
      PointLatLng selectionStart;
259
      PointLatLng selectionEnd;
260
      Typeface tileTypeface = new Typeface("Arial");
261
      bool showTileGridLines = false;
262
 
263
      FormattedText Copyright;
264
 
265
      /// <summary>
266
      /// enables filling empty tiles using lower level images
267
      /// </summary>
268
      [Browsable(false)]
269
      public bool FillEmptyTiles
270
      {
271
         get
272
         {
273
            return Core.fillEmptyTiles;
274
         }
275
         set
276
         {
277
            Core.fillEmptyTiles = value;
278
         }
279
      }
280
 
281
      /// <summary>
282
      /// max zoom
283
      /// </summary>         
284
      [Category("GMap.NET")]
285
      [Description("maximum zoom level of map")]
286
      public int MaxZoom
287
      {
288
         get
289
         {
290
            return Core.maxZoom;
291
         }
292
         set
293
         {
294
            Core.maxZoom = value;
295
         }
296
      }
297
 
298
      /// <summary>
299
      /// min zoom
300
      /// </summary>      
301
      [Category("GMap.NET")]
302
      [Description("minimum zoom level of map")]
303
      public int MinZoom
304
      {
305
         get
306
         {
307
            return Core.minZoom;
308
         }
309
         set
310
         {
311
            Core.minZoom = value;
312
         }
313
      }
314
 
315
      /// <summary>
316
      /// pen for empty tile borders
317
      /// </summary>
318
      public Pen EmptyTileBorders = new Pen(Brushes.White, 1.0);
319
 
320
      /// <summary>
321
      /// pen for Selection
322
      /// </summary>
323
      public Pen SelectionPen = new Pen(Brushes.Blue, 2.0);
324
 
325
      /// <summary>
326
      /// background of selected area
327
      /// </summary>
328
      public Brush SelectedAreaFill = new SolidColorBrush(Color.FromArgb(33, Colors.RoyalBlue.R, Colors.RoyalBlue.G, Colors.RoyalBlue.B));
329
 
330
      /// <summary>
331
      /// /// <summary>
332
      /// pen for empty tile background
333
      /// </summary>
334
      public Brush EmptytileBrush = Brushes.Navy;
335
 
336
      /// <summary>
337
      /// text on empty tiles
338
      /// </summary>
339
      public FormattedText EmptyTileText = new FormattedText("We are sorry, but we don't\nhave imagery at this zoom\n     level for this region.", System.Globalization.CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface("Arial"), 16, Brushes.Blue);
340
 
341
      /// <summary>
342
      /// map zooming type for mouse wheel
343
      /// </summary>
344
      [Category("GMap.NET")]
345
      [Description("map zooming type for mouse wheel")]
346
      public MouseWheelZoomType MouseWheelZoomType
347
      {
348
         get
349
         {
350
            return Core.MouseWheelZoomType;
351
         }
352
         set
353
         {
354
            Core.MouseWheelZoomType = value;
355
         }
356
      }
357
 
358
              /// <summary>
359
        /// enable map zoom on mouse wheel
360
        /// </summary>
361
        [Category("GMap.NET")]
362
        [Description("enable map zoom on mouse wheel")]
363
        public bool MouseWheelZoomEnabled
364
        {
365
            get
366
            {
367
                return Core.MouseWheelZoomEnabled;
368
            }
369
            set
370
            {
371
                Core.MouseWheelZoomEnabled = value;
372
            }
373
        }
374
 
375
      /// <summary>
376
      /// map dragg button
377
      /// </summary>
378
      [Category("GMap.NET")]
379
      public MouseButton DragButton = MouseButton.Right;
380
 
381
      /// <summary>
382
      /// use circle for selection
383
      /// </summary>
384
      public bool SelectionUseCircle = false;
385
 
386
      /// <summary>
387
      /// shows tile gridlines
388
      /// </summary>
389
      [Category("GMap.NET")]
390
      public bool ShowTileGridLines
391
      {
392
         get
393
         {
394
            return showTileGridLines;
395
         }
396
         set
397
         {
398
            showTileGridLines = value;
399
            InvalidateVisual();
400
         }
401
      }
402
 
403
      /// <summary>
404
      /// retry count to get tile 
405
      /// </summary>
406
      [Browsable(false)]
407
      public int RetryLoadTile
408
      {
409
         get
410
         {
411
            return Core.RetryLoadTile;
412
         }
413
         set
414
         {
415
            Core.RetryLoadTile = value;
416
         }
417
      }
418
 
419
      /// <summary>
420
      /// how many levels of tiles are staying decompresed in memory
421
      /// </summary>
422
      [Browsable(false)]
423
      public int LevelsKeepInMemmory
424
      {
425
         get
426
         {
427
            return Core.LevelsKeepInMemmory;
428
         }
429
 
430
         set
431
         {
432
            Core.LevelsKeepInMemmory = value;
433
         }
434
      }
435
 
436
      /// <summary>
437
      /// current selected area in map
438
      /// </summary>
439
      private RectLatLng selectedArea;
440
 
441
      [Browsable(false)]
442
      public RectLatLng SelectedArea
443
      {
444
         get
445
         {
446
            return selectedArea;
447
         }
448
         set
449
         {
450
            selectedArea = value;
451
            InvalidateVisual();
452
         }
453
      }
454
 
455
      /// <summary>
456
      /// is touch control enabled
457
      /// </summary>
458
      public bool TouchEnabled = true;
459
 
460
      /// <summary>
461
      /// map boundaries
462
      /// </summary>
463
      public RectLatLng? BoundsOfMap = null;
464
 
465
      /// <summary>
466
      /// occurs when mouse selection is changed
467
      /// </summary>        
468
      public event SelectionChange OnSelectionChange;
469
 
470
      /// <summary>
471
      /// list of markers
472
      /// </summary>
473
      public readonly ObservableCollection<GMapMarker> Markers = new ObservableCollection<GMapMarker>();
474
 
475
      /// <summary>
476
      /// current markers overlay offset
477
      /// </summary>
478
      internal readonly TranslateTransform MapTranslateTransform = new TranslateTransform();
479
      internal readonly TranslateTransform MapOverlayTranslateTransform = new TranslateTransform();
480
 
481
      internal ScaleTransform MapScaleTransform = new ScaleTransform();
482
      internal RotateTransform MapRotateTransform = new RotateTransform();
483
 
484
      protected bool DesignModeInConstruct
485
      {
486
         get
487
         {
488
            return System.ComponentModel.DesignerProperties.GetIsInDesignMode(this);
489
         }
490
      }
491
 
492
      Canvas mapCanvas = null;
493
 
494
      /// <summary>
495
      /// markers overlay
496
      /// </summary>
497
      internal Canvas MapCanvas
498
      {
499
         get
500
         {
501
            if(mapCanvas == null)
502
            {
503
               if(this.VisualChildrenCount > 0)
504
               {
505
                  Border border = VisualTreeHelper.GetChild(this, 0) as Border;
506
                  ItemsPresenter items = border.Child as ItemsPresenter;
507
                  DependencyObject target = VisualTreeHelper.GetChild(items, 0);
508
                  mapCanvas = target as Canvas;
509
 
510
                  mapCanvas.RenderTransform = MapTranslateTransform;
511
               }
512
            }
513
 
514
            return mapCanvas;
515
         }
516
      }
517
 
518
      public GMaps Manager
519
      {
520
         get
521
         {
522
            return GMaps.Instance;
523
         }
524
      }
525
 
526
      static DataTemplate DataTemplateInstance;
527
      static ItemsPanelTemplate ItemsPanelTemplateInstance;
528
      static Style StyleInstance;
529
 
530
      public GMapControl()
531
      {
532
         if(!DesignModeInConstruct)
533
         {
534
            #region -- templates --
535
 
536
            #region -- xaml --
537
            //  <ItemsControl Name="figures">
538
            //    <ItemsControl.ItemTemplate>
539
            //        <DataTemplate>
540
            //            <ContentPresenter Content="{Binding Path=Shape}" />
541
            //        </DataTemplate>
542
            //    </ItemsControl.ItemTemplate>
543
            //    <ItemsControl.ItemsPanel>
544
            //        <ItemsPanelTemplate>
545
            //            <Canvas />
546
            //        </ItemsPanelTemplate>
547
            //    </ItemsControl.ItemsPanel>
548
            //    <ItemsControl.ItemContainerStyle>
549
            //        <Style>
550
            //            <Setter Property="Canvas.Left" Value="{Binding Path=LocalPositionX}"/>
551
            //            <Setter Property="Canvas.Top" Value="{Binding Path=LocalPositionY}"/>
552
            //        </Style>
553
            //    </ItemsControl.ItemContainerStyle>
554
            //</ItemsControl> 
555
            #endregion
556
 
557
            if(DataTemplateInstance == null)
558
            {
559
               DataTemplateInstance = new DataTemplate(typeof(GMapMarker));
560
               {
561
                  FrameworkElementFactory fef = new FrameworkElementFactory(typeof(ContentPresenter));
562
                  fef.SetBinding(ContentPresenter.ContentProperty, new Binding("Shape"));
563
                  DataTemplateInstance.VisualTree = fef;
564
               }
565
            }
566
            ItemTemplate = DataTemplateInstance;
567
 
568
            if(ItemsPanelTemplateInstance == null)
569
            {
570
               var factoryPanel = new FrameworkElementFactory(typeof(Canvas));
571
               {
572
                  factoryPanel.SetValue(Canvas.IsItemsHostProperty, true);
573
 
574
                  ItemsPanelTemplateInstance = new ItemsPanelTemplate();
575
                  {
576
                     ItemsPanelTemplateInstance.VisualTree = factoryPanel;
577
                  }
578
               }
579
            }
580
            ItemsPanel = ItemsPanelTemplateInstance;
581
 
582
            if(StyleInstance == null)
583
            {
584
               StyleInstance = new Style();
585
               {
586
                  StyleInstance.Setters.Add(new Setter(Canvas.LeftProperty, new Binding("LocalPositionX")));
587
                  StyleInstance.Setters.Add(new Setter(Canvas.TopProperty, new Binding("LocalPositionY")));
588
                  StyleInstance.Setters.Add(new Setter(Canvas.ZIndexProperty, new Binding("ZIndex")));
589
               }
590
            }
591
            ItemContainerStyle = StyleInstance;
592
            #endregion
593
 
594
            ClipToBounds = true;
595
            SnapsToDevicePixels = true;
596
 
597
            Core.SystemType = "WindowsPresentation";
598
 
599
            Core.RenderMode = GMap.NET.RenderMode.WPF;
600
 
601
            Core.OnMapZoomChanged += new MapZoomChanged(ForceUpdateOverlays);
602
            Loaded += new RoutedEventHandler(GMapControl_Loaded);
603
            Dispatcher.ShutdownStarted += new EventHandler(Dispatcher_ShutdownStarted);
604
            SizeChanged += new SizeChangedEventHandler(GMapControl_SizeChanged);
605
 
606
            // by default its internal property, feel free to use your own
607
            if(ItemsSource == null)
608
            {
609
               ItemsSource = Markers;
610
            }
611
 
612
            Core.Zoom = (int)((double)ZoomProperty.DefaultMetadata.DefaultValue);
613
         }
614
      }
615
 
616
      static GMapControl()
617
      {
618
         GMapImageProxy.Enable();
619
#if !PocketPC
620
         GMaps.Instance.SQLitePing();
621
#endif
622
      }
623
 
624
      void invalidatorEngage(object sender, ProgressChangedEventArgs e)
625
      {
626
         base.InvalidateVisual();
627
      }
628
 
629
      /// <summary>
630
      /// enque built-in thread safe invalidation
631
      /// </summary>
632
      public new void InvalidateVisual()
633
      {
634
         if(Core.Refresh != null)
635
         {
636
            Core.Refresh.Set();
637
         }
638
      }
639
 
640
      /// <summary>
641
      /// Invalidates the rendering of the element, and forces a complete new layout
642
      /// pass. System.Windows.UIElement.OnRender(System.Windows.Media.DrawingContext)
643
      /// is called after the layout cycle is completed. If not forced enques built-in thread safe invalidation
644
      /// </summary>
645
      /// <param name="forced"></param>
646
      public void InvalidateVisual(bool forced)
647
      {
648
         if(forced)
649
         {
650
            lock(Core.invalidationLock)
651
            {
652
               Core.lastInvalidation = DateTime.Now;
653
            }
654
            base.InvalidateVisual();
655
         }
656
         else
657
         {
658
            InvalidateVisual();
659
         }
660
      }
661
 
662
      protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
663
      {
664
         base.OnItemsChanged(e);
665
 
666
         if(e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
667
         {
668
             ForceUpdateOverlays(e.NewItems);
669
         }
670
         else
671
         {
672
             InvalidateVisual();
673
         }
674
      }
675
 
676
      /// <summary>
677
      /// inits core system
678
      /// </summary>
679
      /// <param name="sender"></param>
680
      /// <param name="e"></param>
681
      void GMapControl_Loaded(object sender, RoutedEventArgs e)
682
      {
683
         if(!Core.IsStarted)
684
         {
685
            if(lazyEvents)
686
            {
687
               lazyEvents = false;
688
 
689
               if(lazySetZoomToFitRect.HasValue)
690
               {
691
                  SetZoomToFitRect(lazySetZoomToFitRect.Value);
692
                  lazySetZoomToFitRect = null;
693
               }
694
            }
695
            Core.OnMapOpen().ProgressChanged += new ProgressChangedEventHandler(invalidatorEngage);
696
            ForceUpdateOverlays();
697
 
698
            if(Application.Current != null)
699
            {
700
               loadedApp = Application.Current;
701
 
702
               loadedApp.Dispatcher.Invoke(DispatcherPriority.ApplicationIdle,
703
                  new Action(delegate()
704
                  {
705
                     loadedApp.SessionEnding += new SessionEndingCancelEventHandler(Current_SessionEnding);
706
                  }
707
                  ));
708
            }
709
         }
710
      }
711
 
712
      Application loadedApp;
713
 
714
      void Current_SessionEnding(object sender, SessionEndingCancelEventArgs e)
715
      {
716
         GMaps.Instance.CancelTileCaching();
717
      }
718
 
719
      void Dispatcher_ShutdownStarted(object sender, EventArgs e)
720
      {
721
         Dispose();
722
      }
723
 
724
      /// <summary>
725
      /// recalculates size
726
      /// </summary>
727
      /// <param name="sender"></param>
728
      /// <param name="e"></param>
729
      void GMapControl_SizeChanged(object sender, SizeChangedEventArgs e)
730
      {
731
         System.Windows.Size constraint = e.NewSize;
732
 
733
         // 50px outside control
734
         //region = new GRect(-50, -50, (int)constraint.Width + 100, (int)constraint.Height + 100);
735
 
736
         Core.OnMapSizeChanged((int)constraint.Width, (int)constraint.Height);
737
 
738
         if(Core.IsStarted)
739
         {
740
            if(IsRotated)
741
            {
742
               UpdateRotationMatrix();
743
            }
744
 
745
            ForceUpdateOverlays();
746
         }
747
      }
748
 
749
      void ForceUpdateOverlays()
750
      {
751
          ForceUpdateOverlays(ItemsSource);          
752
      }
753
 
754
      void ForceUpdateOverlays(System.Collections.IEnumerable items)
755
      {
756
         using(Dispatcher.DisableProcessing())
757
         {
758
            UpdateMarkersOffset();
759
 
760
            foreach(GMapMarker i in items)
761
            {
762
               if(i != null)
763
               {
764
                  i.ForceUpdateLocalPosition(this);
765
 
766
                  if(i is IShapable)
767
                  {
768
                     (i as IShapable).RegenerateShape(this);
769
                  }
770
               }
771
            }
772
         }
773
         InvalidateVisual();
774
      }
775
 
776
      /// <summary>
777
      /// updates markers overlay offset
778
      /// </summary>
779
      void UpdateMarkersOffset()
780
      {
781
         if(MapCanvas != null)
782
         {
783
            if(MapScaleTransform != null)
784
            {
785
               var tp = MapScaleTransform.Transform(new System.Windows.Point(Core.renderOffset.X, Core.renderOffset.Y));
786
               MapOverlayTranslateTransform.X = tp.X;
787
               MapOverlayTranslateTransform.Y = tp.Y;
788
 
789
               // map is scaled already
790
               MapTranslateTransform.X = Core.renderOffset.X;
791
               MapTranslateTransform.Y = Core.renderOffset.Y;
792
            }
793
            else
794
            {
795
               MapTranslateTransform.X = Core.renderOffset.X;
796
               MapTranslateTransform.Y = Core.renderOffset.Y;
797
 
798
               MapOverlayTranslateTransform.X = MapTranslateTransform.X;
799
               MapOverlayTranslateTransform.Y = MapTranslateTransform.Y;
800
            }
801
         }
802
      }
803
 
804
      public Brush EmptyMapBackground = Brushes.WhiteSmoke;
805
 
806
      /// <summary>
807
      /// render map in WPF
808
      /// </summary>
809
      /// <param name="g"></param>
810
      void DrawMap(DrawingContext g)
811
      {
812
         if(MapProvider == EmptyProvider.Instance || MapProvider == null)
813
         {
814
            return;
815
         }
816
 
817
         Core.tileDrawingListLock.AcquireReaderLock();
818
         Core.Matrix.EnterReadLock();
819
         try
820
         {
821
            foreach(var tilePoint in Core.tileDrawingList)
822
            {
823
               Core.tileRect.Location = tilePoint.PosPixel;
824
               Core.tileRect.OffsetNegative(Core.compensationOffset);
825
 
826
               //if(region.IntersectsWith(Core.tileRect) || IsRotated)
827
               {
828
                  bool found = false;
829
 
830
                  Tile t = Core.Matrix.GetTileWithNoLock(Core.Zoom, tilePoint.PosXY);
831
                  if(t.NotEmpty)
832
                  {
833
                     foreach(GMapImage img in t.Overlays)
834
                     {
835
                        if(img != null && img.Img != null)
836
                        {
837
                           if(!found)
838
                              found = true;
839
 
840
                           var imgRect = new Rect(Core.tileRect.X + 0.6, Core.tileRect.Y + 0.6, Core.tileRect.Width + 0.6, Core.tileRect.Height + 0.6);
841
                           if(!img.IsParent)
842
                           {
843
                              g.DrawImage(img.Img, imgRect);
844
                           }
845
                           else
846
                           {
847
                              // TODO: move calculations to loader thread
848
                              var geometry = new RectangleGeometry(imgRect);
849
                              var parentImgRect = new Rect(Core.tileRect.X - Core.tileRect.Width * img.Xoff + 0.6, Core.tileRect.Y - Core.tileRect.Height * img.Yoff + 0.6, Core.tileRect.Width * img.Ix + 0.6, Core.tileRect.Height * img.Ix + 0.6);
850
 
851
                              g.PushClip(geometry);
852
                              g.DrawImage(img.Img, parentImgRect);
853
                              g.Pop();
854
                              geometry = null;
855
                           }
856
                        }
857
                     }
858
                  }
859
                  else if(FillEmptyTiles && MapProvider.Projection is MercatorProjection)
860
                  {
861
                     #region -- fill empty tiles --
862
                     int zoomOffset = 1;
863
                     Tile parentTile = Tile.Empty;
864
                     long Ix = 0;
865
 
866
                     while(!parentTile.NotEmpty && zoomOffset < Core.Zoom && zoomOffset <= LevelsKeepInMemmory)
867
                     {
868
                        Ix = (long)Math.Pow(2, zoomOffset);
869
                        parentTile = Core.Matrix.GetTileWithNoLock(Core.Zoom - zoomOffset++, new GMap.NET.GPoint((int)(tilePoint.PosXY.X / Ix), (int)(tilePoint.PosXY.Y / Ix)));
870
                     }
871
 
872
                     if(parentTile.NotEmpty)
873
                     {
874
                        long Xoff = Math.Abs(tilePoint.PosXY.X - (parentTile.Pos.X * Ix));
875
                        long Yoff = Math.Abs(tilePoint.PosXY.Y - (parentTile.Pos.Y * Ix));
876
 
877
                        var geometry = new RectangleGeometry(new Rect(Core.tileRect.X + 0.6, Core.tileRect.Y + 0.6, Core.tileRect.Width + 0.6, Core.tileRect.Height + 0.6));
878
                        var parentImgRect = new Rect(Core.tileRect.X - Core.tileRect.Width * Xoff + 0.6, Core.tileRect.Y - Core.tileRect.Height * Yoff + 0.6, Core.tileRect.Width * Ix + 0.6, Core.tileRect.Height * Ix + 0.6);
879
 
880
                        // render tile 
881
                        {
882
                           foreach(GMapImage img in parentTile.Overlays)
883
                           {
884
                              if(img != null && img.Img != null && !img.IsParent)
885
                              {
886
                                 if(!found)
887
                                    found = true;
888
 
889
                                 g.PushClip(geometry);
890
                                 g.DrawImage(img.Img, parentImgRect);
891
                                 g.DrawRectangle(SelectedAreaFill, null, geometry.Bounds);
892
                                 g.Pop();
893
                              }
894
                           }
895
                        }
896
 
897
                        geometry = null;
898
                     }
899
                     #endregion
900
                  }
901
 
902
                  // add text if tile is missing
903
                  if(!found)
904
                  {
905
                     lock(Core.FailedLoads)
906
                     {
907
                        var lt = new LoadTask(tilePoint.PosXY, Core.Zoom);
908
 
909
                        if(Core.FailedLoads.ContainsKey(lt))
910
                        {
911
                           g.DrawRectangle(EmptytileBrush, EmptyTileBorders, new Rect(Core.tileRect.X, Core.tileRect.Y, Core.tileRect.Width, Core.tileRect.Height));
912
 
913
                           var ex = Core.FailedLoads[lt];
914
                           FormattedText TileText = new FormattedText("Exception: " + ex.Message, System.Globalization.CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, tileTypeface, 14, Brushes.Red);
915
                           TileText.MaxTextWidth = Core.tileRect.Width - 11;
916
 
917
                           g.DrawText(TileText, new System.Windows.Point(Core.tileRect.X + 11, Core.tileRect.Y + 11));
918
 
919
                           g.DrawText(EmptyTileText, new System.Windows.Point(Core.tileRect.X + Core.tileRect.Width / 2 - EmptyTileText.Width / 2, Core.tileRect.Y + Core.tileRect.Height / 2 - EmptyTileText.Height / 2));
920
                        }
921
                     }
922
                  }
923
 
924
                  if(ShowTileGridLines)
925
                  {
926
                     g.DrawRectangle(null, EmptyTileBorders, new Rect(Core.tileRect.X, Core.tileRect.Y, Core.tileRect.Width, Core.tileRect.Height));
927
 
928
                     if(tilePoint.PosXY == Core.centerTileXYLocation)
929
                     {
930
                        FormattedText TileText = new FormattedText("CENTER:" + tilePoint.ToString(), System.Globalization.CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, tileTypeface, 16, Brushes.Red);
931
                        TileText.MaxTextWidth = Core.tileRect.Width;
932
                        g.DrawText(TileText, new System.Windows.Point(Core.tileRect.X + Core.tileRect.Width / 2 - EmptyTileText.Width / 2, Core.tileRect.Y + Core.tileRect.Height / 2 - TileText.Height / 2));
933
                     }
934
                     else
935
                     {
936
                        FormattedText TileText = new FormattedText("TILE: " + tilePoint.ToString(), System.Globalization.CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, tileTypeface, 16, Brushes.Red);
937
                        TileText.MaxTextWidth = Core.tileRect.Width;
938
                        g.DrawText(TileText, new System.Windows.Point(Core.tileRect.X + Core.tileRect.Width / 2 - EmptyTileText.Width / 2, Core.tileRect.Y + Core.tileRect.Height / 2 - TileText.Height / 2));
939
                     }
940
                  }
941
               }
942
            }
943
         }
944
         finally
945
         {
946
            Core.Matrix.LeaveReadLock();
947
            Core.tileDrawingListLock.ReleaseReaderLock();
948
         }
949
      }
950
 
951
      /// <summary>
952
      /// gets image of the current view
953
      /// </summary>
954
      /// <returns></returns>
955
      public ImageSource ToImageSource()
956
      {
957
         FrameworkElement obj = this;
958
 
959
         // Save current canvas transform
960
         Transform transform = obj.LayoutTransform;
961
         obj.LayoutTransform = null;
962
 
963
         // fix margin offset as well
964
         Thickness margin = obj.Margin;
965
         obj.Margin = new Thickness(0, 0,
966
         margin.Right - margin.Left, margin.Bottom - margin.Top);
967
 
968
         // Get the size of canvas
969
         Size size = new Size(obj.ActualWidth, obj.ActualHeight);
970
 
971
         // force control to Update
972
         obj.Measure(size);
973
         obj.Arrange(new Rect(size));
974
 
975
         RenderTargetBitmap bmp = new RenderTargetBitmap(
976
         (int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32);
977
 
978
         bmp.Render(obj);
979
 
980
         if(bmp.CanFreeze)
981
         {
982
            bmp.Freeze();
983
         }
984
 
985
         // return values as they were before
986
         obj.LayoutTransform = transform;
987
         obj.Margin = margin;
988
 
989
         return bmp;
990
      }
991
 
992
      /// <summary>
993
      /// creates path from list of points, for performance set addBlurEffect to false
994
      /// </summary>
995
      /// <param name="pl"></param>
996
      /// <returns></returns>
997
      public virtual Path CreateRoutePath(List<Point> localPath)
998
      {
2329 - 999
         return CreateRoutePath(localPath, true , null);
2287 - 1000
      }
1001
 
1002
      /// <summary>
1003
      /// creates path from list of points, for performance set addBlurEffect to false
1004
      /// </summary>
1005
      /// <param name="pl"></param>
1006
      /// <returns></returns>
2329 - 1007
      public virtual Path CreateRoutePath(List<Point> localPath, bool addBlurEffect, Brush brush)
2287 - 1008
      {
1009
         // Create a StreamGeometry to use to specify myPath.
1010
         StreamGeometry geometry = new StreamGeometry();
1011
 
1012
         using(StreamGeometryContext ctx = geometry.Open())
1013
         {
1014
            ctx.BeginFigure(localPath[0], false, false);
1015
 
1016
            // Draw a line to the next specified point.
1017
            ctx.PolyLineTo(localPath, true, true);
1018
         }
1019
 
1020
         // Freeze the geometry (make it unmodifiable)
1021
         // for additional performance benefits.
1022
         geometry.Freeze();
1023
 
1024
         // Create a path to draw a geometry with.
1025
         Path myPath = new Path();
1026
         {
1027
            // Specify the shape of the Path using the StreamGeometry.
1028
            myPath.Data = geometry;
1029
 
1030
            if (addBlurEffect)
1031
            {
1032
                BlurEffect ef = new BlurEffect();
1033
                {
1034
                    ef.KernelType = KernelType.Gaussian;
1035
                    ef.Radius = 3.0;
1036
                    ef.RenderingBias = RenderingBias.Performance;
1037
                }
1038
 
1039
                myPath.Effect = ef;
1040
            }
2329 - 1041
            if(brush !=null)
1042
                myPath.Stroke = brush;
1043
            else
1044
                myPath.Stroke = Brushes.Magenta;
2287 - 1045
            myPath.StrokeThickness = 5;
1046
            myPath.StrokeLineJoin = PenLineJoin.Round;
1047
            myPath.StrokeStartLineCap = PenLineCap.Triangle;
1048
            myPath.StrokeEndLineCap = PenLineCap.Square;
1049
 
1050
            myPath.Opacity = 0.6;
1051
            myPath.IsHitTestVisible = false;
1052
         }
1053
         return myPath;
1054
      }
1055
 
1056
      /// <summary>
1057
      /// creates path from list of points, for performance set addBlurEffect to false
1058
      /// </summary>
1059
      /// <param name="pl"></param>
1060
      /// <returns></returns>
1061
      public virtual Path CreatePolygonPath(List<Point> localPath)
1062
      {
1063
         return CreatePolygonPath(localPath, false);
1064
      }
1065
 
1066
      /// <summary>
1067
      /// creates path from list of points, for performance set addBlurEffect to false
1068
      /// </summary>
1069
      /// <param name="pl"></param>
1070
      /// <returns></returns>
1071
      public virtual Path CreatePolygonPath(List<Point> localPath, bool addBlurEffect)
1072
      {
1073
         // Create a StreamGeometry to use to specify myPath.
1074
         StreamGeometry geometry = new StreamGeometry();
1075
 
1076
         using(StreamGeometryContext ctx = geometry.Open())
1077
         {
1078
            ctx.BeginFigure(localPath[0], true, true);
1079
 
1080
            // Draw a line to the next specified point.
1081
            ctx.PolyLineTo(localPath, true, true);
1082
         }
1083
 
1084
         // Freeze the geometry (make it unmodifiable)
1085
         // for additional performance benefits.
1086
         geometry.Freeze();
1087
 
1088
         // Create a path to draw a geometry with.
1089
         Path myPath = new Path();
1090
         {
1091
            // Specify the shape of the Path using the StreamGeometry.
1092
            myPath.Data = geometry;
1093
 
1094
            if (addBlurEffect)
1095
            {
1096
                BlurEffect ef = new BlurEffect();
1097
                {
1098
                    ef.KernelType = KernelType.Gaussian;
1099
                    ef.Radius = 3.0;
1100
                    ef.RenderingBias = RenderingBias.Performance;
1101
                }
1102
 
1103
                myPath.Effect = ef;
1104
            }
1105
 
1106
            myPath.Stroke = Brushes.MidnightBlue;
1107
            myPath.StrokeThickness = 5;
1108
            myPath.StrokeLineJoin = PenLineJoin.Round;
1109
            myPath.StrokeStartLineCap = PenLineCap.Triangle;
1110
            myPath.StrokeEndLineCap = PenLineCap.Square;
1111
 
1112
            myPath.Fill = Brushes.AliceBlue;
1113
 
1114
            myPath.Opacity = 0.6;
1115
            myPath.IsHitTestVisible = false;
1116
         }
1117
         return myPath;
1118
      }
1119
 
1120
      /// <summary>
1121
      /// sets zoom to max to fit rect
1122
      /// </summary>
1123
      /// <param name="rect">area</param>
1124
      /// <returns></returns>
1125
      public bool SetZoomToFitRect(RectLatLng rect)
1126
      {
1127
         if(lazyEvents)
1128
         {
1129
            lazySetZoomToFitRect = rect;
1130
         }
1131
         else
1132
         {
1133
            int maxZoom = Core.GetMaxZoomToFitRect(rect);
1134
            if(maxZoom > 0)
1135
            {
1136
               PointLatLng center = new PointLatLng(rect.Lat - (rect.HeightLat / 2), rect.Lng + (rect.WidthLng / 2));
1137
               Position = center;
1138
 
1139
               if(maxZoom > MaxZoom)
1140
               {
1141
                  maxZoom = MaxZoom;
1142
               }
1143
 
1144
               if(Core.Zoom != maxZoom)
1145
               {
1146
                  Zoom = maxZoom;
1147
               }
1148
 
1149
               return true;
1150
            }
1151
         }
1152
         return false;
1153
      }
1154
 
1155
      RectLatLng? lazySetZoomToFitRect = null;
1156
      bool lazyEvents = true;
1157
 
1158
      /// <summary>
1159
      /// sets to max zoom to fit all markers and centers them in map
1160
      /// </summary>
1161
      /// <param name="ZIndex">z index or null to check all</param>
1162
      /// <returns></returns>
1163
      public bool ZoomAndCenterMarkers(int? ZIndex)
1164
      {
1165
         RectLatLng? rect = GetRectOfAllMarkers(ZIndex);
1166
         if(rect.HasValue)
1167
         {
1168
            return SetZoomToFitRect(rect.Value);
1169
         }
1170
 
1171
         return false;
1172
      }
1173
 
1174
      /// <summary>
1175
      /// gets rectangle with all objects inside
1176
      /// </summary>
1177
      /// <param name="ZIndex">z index or null to check all</param>
1178
      /// <returns></returns>
1179
      public RectLatLng? GetRectOfAllMarkers(int? ZIndex)
1180
      {
1181
         RectLatLng? ret = null;
1182
 
1183
         double left = double.MaxValue;
1184
         double top = double.MinValue;
1185
         double right = double.MinValue;
1186
         double bottom = double.MaxValue;
1187
         IEnumerable<GMapMarker> Overlays;
1188
 
1189
         if(ZIndex.HasValue)
1190
         {
1191
            Overlays = ItemsSource.Cast<GMapMarker>().Where(p => p != null && p.ZIndex == ZIndex);
1192
         }
1193
         else
1194
         {
1195
            Overlays = ItemsSource.Cast<GMapMarker>();
1196
         }
1197
 
1198
         if(Overlays != null)
1199
         {
1200
            foreach(var m in Overlays)
1201
            {
1202
               if(m.Shape != null && m.Shape.Visibility == System.Windows.Visibility.Visible)
1203
               {
1204
                  // left
1205
                  if(m.Position.Lng < left)
1206
                  {
1207
                     left = m.Position.Lng;
1208
                  }
1209
 
1210
                  // top
1211
                  if(m.Position.Lat > top)
1212
                  {
1213
                     top = m.Position.Lat;
1214
                  }
1215
 
1216
                  // right
1217
                  if(m.Position.Lng > right)
1218
                  {
1219
                     right = m.Position.Lng;
1220
                  }
1221
 
1222
                  // bottom
1223
                  if(m.Position.Lat < bottom)
1224
                  {
1225
                     bottom = m.Position.Lat;
1226
                  }
1227
               }
1228
            }
1229
         }
1230
 
1231
         if(left != double.MaxValue && right != double.MinValue && top != double.MinValue && bottom != double.MaxValue)
1232
         {
1233
            ret = RectLatLng.FromLTRB(left, top, right, bottom);
1234
         }
1235
 
1236
         return ret;
1237
      }
1238
 
1239
      /// <summary>
1240
      /// offset position in pixels
1241
      /// </summary>
1242
      /// <param name="x"></param>
1243
      /// <param name="y"></param>
1244
      public void Offset(int x, int y)
1245
      {
1246
         if(IsLoaded)
1247
         {
1248
            if(IsRotated)
1249
            {
1250
               Point p = new Point(x, y);
1251
               p = rotationMatrixInvert.Transform(p);
1252
               x = (int)p.X;
1253
               y = (int)p.Y;
1254
 
1255
               Core.DragOffset(new GPoint(x, y));
1256
 
1257
               ForceUpdateOverlays();
1258
            }
1259
            else
1260
            {
1261
               Core.DragOffset(new GPoint(x, y));
1262
 
1263
               UpdateMarkersOffset();
1264
               InvalidateVisual(true);
1265
            }
1266
         }
1267
      }
1268
 
1269
      readonly RotateTransform rotationMatrix = new RotateTransform();
1270
      GeneralTransform rotationMatrixInvert = new RotateTransform();
1271
 
1272
      /// <summary>
1273
      /// updates rotation matrix
1274
      /// </summary>
1275
      void UpdateRotationMatrix()
1276
      {
1277
         System.Windows.Point center = new System.Windows.Point(ActualWidth / 2.0, ActualHeight / 2.0);
1278
 
1279
         rotationMatrix.Angle = -Bearing;
1280
         rotationMatrix.CenterY = center.Y;
1281
         rotationMatrix.CenterX = center.X;
1282
 
1283
         rotationMatrixInvert = rotationMatrix.Inverse;
1284
      }
1285
 
1286
      /// <summary>
1287
      /// returs true if map bearing is not zero
1288
      /// </summary>         
1289
      public bool IsRotated
1290
      {
1291
         get
1292
         {
1293
            return Core.IsRotated;
1294
         }
1295
      }
1296
 
1297
      /// <summary>
1298
      /// bearing for rotation of the map
1299
      /// </summary>
1300
      [Category("GMap.NET")]
1301
      public float Bearing
1302
      {
1303
         get
1304
         {
1305
            return Core.bearing;
1306
         }
1307
         set
1308
         {
1309
            if(Core.bearing != value)
1310
            {
1311
               bool resize = Core.bearing == 0;
1312
               Core.bearing = value;
1313
 
1314
               UpdateRotationMatrix();
1315
 
1316
               if(value != 0 && value % 360 != 0)
1317
               {
1318
                  Core.IsRotated = true;
1319
 
1320
                  if(Core.tileRectBearing.Size == Core.tileRect.Size)
1321
                  {
1322
                     Core.tileRectBearing = Core.tileRect;
1323
                     Core.tileRectBearing.Inflate(1, 1);
1324
                  }
1325
               }
1326
               else
1327
               {
1328
                  Core.IsRotated = false;
1329
                  Core.tileRectBearing = Core.tileRect;
1330
               }
1331
 
1332
               if(resize)
1333
               {
1334
                  Core.OnMapSizeChanged((int)ActualWidth, (int)ActualHeight);
1335
               }
1336
 
1337
               if(Core.IsStarted)
1338
               {
1339
                  ForceUpdateOverlays();
1340
               }
1341
            }
1342
         }
1343
      }
1344
 
1345
      /// <summary>
1346
      /// apply transformation if in rotation mode
1347
      /// </summary>
1348
      System.Windows.Point ApplyRotation(double x, double y)
1349
      {
1350
         System.Windows.Point ret = new System.Windows.Point(x, y);
1351
 
1352
         if(IsRotated)
1353
         {
1354
            ret = rotationMatrix.Transform(ret);
1355
         }
1356
 
1357
         return ret;
1358
      }
1359
 
1360
      /// <summary>
1361
      /// apply transformation if in rotation mode
1362
      /// </summary>
1363
      System.Windows.Point ApplyRotationInversion(double x, double y)
1364
      {
1365
         System.Windows.Point ret = new System.Windows.Point(x, y);
1366
 
1367
         if(IsRotated)
1368
         {
1369
            ret = rotationMatrixInvert.Transform(ret);
1370
         }
1371
 
1372
         return ret;
1373
      }
1374
 
1375
      #region UserControl Events
1376
      protected override void OnRender(DrawingContext drawingContext)
1377
      {
1378
         if(!Core.IsStarted)
1379
            return;
1380
 
1381
         drawingContext.DrawRectangle(EmptyMapBackground, null, new Rect(RenderSize));
1382
 
1383
         if(IsRotated)
1384
         {
1385
            drawingContext.PushTransform(rotationMatrix);
1386
 
1387
            if(MapScaleTransform != null)
1388
            {
1389
               drawingContext.PushTransform(MapScaleTransform);
1390
               drawingContext.PushTransform(MapTranslateTransform);
1391
               {
1392
                  DrawMap(drawingContext);
1393
               }
1394
               drawingContext.Pop();
1395
               drawingContext.Pop();
1396
            }
1397
            else
1398
            {
1399
               drawingContext.PushTransform(MapTranslateTransform);
1400
               {
1401
                  DrawMap(drawingContext);
1402
               }
1403
               drawingContext.Pop();
1404
            }
1405
 
1406
            drawingContext.Pop();
1407
         }
1408
         else
1409
         {
1410
            if(MapScaleTransform != null)
1411
            {
1412
               drawingContext.PushTransform(MapScaleTransform);
1413
               drawingContext.PushTransform(MapTranslateTransform);
1414
               {
1415
                  DrawMap(drawingContext);
1416
 
1417
#if DEBUG
1418
                  drawingContext.DrawLine(VirtualCenterCrossPen, new Point(-20, 0), new Point(20, 0));
1419
                  drawingContext.DrawLine(VirtualCenterCrossPen, new Point(0, -20), new Point(0, 20));
1420
#endif
1421
               }
1422
               drawingContext.Pop();
1423
               drawingContext.Pop();
1424
            }
1425
            else
1426
            {
1427
               drawingContext.PushTransform(MapTranslateTransform);
1428
               {
1429
                  DrawMap(drawingContext);
1430
#if DEBUG
1431
                  drawingContext.DrawLine(VirtualCenterCrossPen, new Point(-20, 0), new Point(20, 0));
1432
                  drawingContext.DrawLine(VirtualCenterCrossPen, new Point(0, -20), new Point(0, 20));
1433
#endif
1434
               }
1435
               drawingContext.Pop();
1436
            }
1437
         }
1438
 
1439
         // selection
1440
         if(!SelectedArea.IsEmpty)
1441
         {
1442
            GPoint p1 = FromLatLngToLocal(SelectedArea.LocationTopLeft);
1443
            GPoint p2 = FromLatLngToLocal(SelectedArea.LocationRightBottom);
1444
 
1445
            long x1 = p1.X;
1446
            long y1 = p1.Y;
1447
            long x2 = p2.X;
1448
            long y2 = p2.Y;
1449
 
1450
            if(SelectionUseCircle)
1451
            {
1452
               drawingContext.DrawEllipse(SelectedAreaFill, SelectionPen, new System.Windows.Point(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2), (x2 - x1) / 2, (y2 - y1) / 2);
1453
            }
1454
            else
1455
            {
1456
               drawingContext.DrawRoundedRectangle(SelectedAreaFill, SelectionPen, new Rect(x1, y1, x2 - x1, y2 - y1), 5, 5);
1457
            }
1458
         }
1459
 
1460
         if(ShowCenter)
1461
         {
1462
            drawingContext.DrawLine(CenterCrossPen, new System.Windows.Point((ActualWidth / 2) - 5, ActualHeight / 2), new System.Windows.Point((ActualWidth / 2) + 5, ActualHeight / 2));
1463
            drawingContext.DrawLine(CenterCrossPen, new System.Windows.Point(ActualWidth / 2, (ActualHeight / 2) - 5), new System.Windows.Point(ActualWidth / 2, (ActualHeight / 2) + 5));
1464
         }
1465
 
1466
         if(renderHelperLine)
1467
         {
1468
            var p = Mouse.GetPosition(this);
1469
 
1470
            drawingContext.DrawLine(HelperLinePen, new Point(p.X, 0), new Point(p.X, ActualHeight));
1471
            drawingContext.DrawLine(HelperLinePen, new Point(0, p.Y), new Point(ActualWidth, p.Y));
1472
         }
1473
 
1474
         #region -- copyright --
1475
 
1476
         if(Copyright != null)
1477
         {
1478
            drawingContext.DrawText(Copyright, new System.Windows.Point(5, ActualHeight - Copyright.Height - 5));
1479
         }
1480
 
1481
         #endregion
1482
 
1483
         base.OnRender(drawingContext);
1484
      }
1485
 
1486
      public Pen CenterCrossPen = new Pen(Brushes.Red, 1);
1487
      public bool ShowCenter = true;
1488
 
1489
#if DEBUG
1490
      readonly Pen VirtualCenterCrossPen = new Pen(Brushes.Blue, 1);
1491
#endif
1492
 
1493
      HelperLineOptions helperLineOption = HelperLineOptions.DontShow;
1494
 
1495
      /// <summary>
1496
      /// draw lines at the mouse pointer position
1497
      /// </summary>
1498
      [Browsable(false)]
1499
      public HelperLineOptions HelperLineOption
1500
      {
1501
         get
1502
         {
1503
            return helperLineOption;
1504
         }
1505
         set
1506
         {
1507
            helperLineOption = value;
1508
            renderHelperLine = (helperLineOption == HelperLineOptions.ShowAlways);
1509
            if(Core.IsStarted)
1510
            {
1511
               InvalidateVisual();
1512
            }
1513
         }
1514
      }
1515
 
1516
      public Pen HelperLinePen = new Pen(Brushes.Blue, 1);
1517
      bool renderHelperLine = false;
1518
 
1519
      protected override void OnKeyUp(KeyEventArgs e)
1520
      {
1521
         base.OnKeyUp(e);
1522
 
1523
         if(HelperLineOption == HelperLineOptions.ShowOnModifierKey)
1524
         {
1525
            renderHelperLine = !(e.IsUp && (e.Key == Key.LeftShift || e.SystemKey == Key.LeftAlt));
1526
            if(!renderHelperLine)
1527
            {
1528
               InvalidateVisual();
1529
            }
1530
         }        
1531
      }
1532
 
1533
      protected override void OnKeyDown(KeyEventArgs e)
1534
      {
1535
         base.OnKeyDown(e);
1536
 
1537
         if(HelperLineOption == HelperLineOptions.ShowOnModifierKey)
1538
         {
1539
            renderHelperLine = e.IsDown && (e.Key == Key.LeftShift || e.SystemKey == Key.LeftAlt);
1540
            if(renderHelperLine)
1541
            {
1542
               InvalidateVisual();
1543
            }
1544
         }        
1545
      }
1546
 
1547
      /// <summary>
1548
      /// reverses MouseWheel zooming direction
1549
      /// </summary>
1550
      public bool InvertedMouseWheelZooming = false;
1551
 
1552
      /// <summary>
1553
      /// lets you zoom by MouseWheel even when pointer is in area of marker
1554
      /// </summary>
1555
      public bool IgnoreMarkerOnMouseWheel = false;
1556
 
1557
      protected override void OnMouseWheel(MouseWheelEventArgs e)
1558
      {
1559
         base.OnMouseWheel(e);
1560
 
1561
         if(MouseWheelZoomEnabled && (IsMouseDirectlyOver || IgnoreMarkerOnMouseWheel) && !Core.IsDragging)
1562
         {
1563
            System.Windows.Point p = e.GetPosition(this);
1564
 
1565
            if(MapScaleTransform != null)
1566
            {
1567
               p = MapScaleTransform.Inverse.Transform(p);
1568
            }
1569
 
1570
            p = ApplyRotationInversion(p.X, p.Y);
1571
 
1572
            if(Core.mouseLastZoom.X != (int)p.X && Core.mouseLastZoom.Y != (int)p.Y)
1573
            {
1574
               if(MouseWheelZoomType == MouseWheelZoomType.MousePositionAndCenter)
1575
               {
1576
                  Core.position = FromLocalToLatLng((int)p.X, (int)p.Y);
1577
               }
1578
               else if(MouseWheelZoomType == MouseWheelZoomType.ViewCenter)
1579
               {
1580
                  Core.position = FromLocalToLatLng((int)ActualWidth / 2, (int)ActualHeight / 2);
1581
               }
1582
               else if(MouseWheelZoomType == MouseWheelZoomType.MousePositionWithoutCenter)
1583
               {
1584
                  Core.position = FromLocalToLatLng((int)p.X, (int)p.Y);
1585
               }
1586
 
1587
               Core.mouseLastZoom.X = (int)p.X;
1588
               Core.mouseLastZoom.Y = (int)p.Y;
1589
            }
1590
 
1591
            // set mouse position to map center
1592
            if(MouseWheelZoomType != MouseWheelZoomType.MousePositionWithoutCenter)
1593
            {
1594
               System.Windows.Point ps = PointToScreen(new System.Windows.Point(ActualWidth / 2, ActualHeight / 2));
1595
               Stuff.SetCursorPos((int)ps.X, (int)ps.Y);
1596
            }
1597
 
1598
            Core.MouseWheelZooming = true;
1599
 
1600
            if(e.Delta > 0)
1601
            {
1602
               if(!InvertedMouseWheelZooming)
1603
               {
1604
                  Zoom = ((int)Zoom) + 1;
1605
               }
1606
               else
1607
               {
1608
                  Zoom = ((int)(Zoom + 0.99)) - 1;
1609
               }
1610
            }
1611
            else
1612
            {
1613
               if(InvertedMouseWheelZooming)
1614
               {
1615
                  Zoom = ((int)Zoom) + 1;
1616
               }
1617
               else
1618
               {
1619
                  Zoom = ((int)(Zoom + 0.99)) - 1;
1620
               }
1621
            }
1622
 
1623
            Core.MouseWheelZooming = false;
1624
         }
1625
      }
1626
 
1627
      bool isSelected = false;
1628
 
1629
      protected override void OnMouseDown(MouseButtonEventArgs e)
1630
      {
1631
         base.OnMouseDown(e);
1632
         if(CanDragMap && e.ChangedButton == DragButton)
1633
         {
1634
            Point p = e.GetPosition(this);
1635
 
1636
            if(MapScaleTransform != null)
1637
            {
1638
               p = MapScaleTransform.Inverse.Transform(p);
1639
            }
1640
 
1641
            p = ApplyRotationInversion(p.X, p.Y);
1642
 
1643
            Core.mouseDown.X = (int)p.X;
1644
            Core.mouseDown.Y = (int)p.Y;
1645
 
1646
            InvalidateVisual();
1647
         }
1648
         else
1649
         {
1650
            if(!isSelected)
1651
            {
1652
               Point p = e.GetPosition(this);
1653
               isSelected = true;
1654
               SelectedArea = RectLatLng.Empty;
1655
               selectionEnd = PointLatLng.Empty;
1656
               selectionStart = FromLocalToLatLng((int)p.X, (int)p.Y);
1657
            }
1658
         }        
1659
      }
1660
 
1661
      int onMouseUpTimestamp = 0;
1662
 
1663
      protected override void OnMouseUp(MouseButtonEventArgs e)
1664
      {
1665
         base.OnMouseUp(e);
1666
 
1667
         if(isSelected)
1668
         {
1669
            isSelected = false;
1670
         }
1671
 
1672
         if(Core.IsDragging)
1673
         {
1674
            if(isDragging)
1675
            {
1676
               onMouseUpTimestamp = e.Timestamp & Int32.MaxValue;
1677
               isDragging = false;
1678
               Debug.WriteLine("IsDragging = " + isDragging);
1679
               Cursor = cursorBefore;
1680
               Mouse.Capture(null);
1681
            }
1682
            Core.EndDrag();
1683
 
1684
            if(BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position))
1685
            {
1686
               if(Core.LastLocationInBounds.HasValue)
1687
               {
1688
                  Position = Core.LastLocationInBounds.Value;
1689
               }
1690
            }
1691
         }
1692
         else
1693
         {
1694
            if(e.ChangedButton == DragButton)
1695
            {
1696
               Core.mouseDown = GPoint.Empty;
1697
            }
1698
 
1699
            if(!selectionEnd.IsEmpty && !selectionStart.IsEmpty)
1700
            {
1701
               bool zoomtofit = false;
1702
 
1703
               if(!SelectedArea.IsEmpty && Keyboard.Modifiers == ModifierKeys.Shift)
1704
               {
1705
                  zoomtofit = SetZoomToFitRect(SelectedArea);
1706
               }
1707
 
1708
               if(OnSelectionChange != null)
1709
               {
1710
                  OnSelectionChange(SelectedArea, zoomtofit);
1711
               }
1712
            }
1713
            else
1714
            {
1715
               InvalidateVisual();
1716
            }
1717
         }
1718
      }
1719
 
1720
      Cursor cursorBefore = Cursors.Arrow;
1721
 
1722
      protected override void OnMouseMove(MouseEventArgs e)
1723
      {
1724
           if (CanDragMap)
1725
            {
1726
                 base.OnMouseMove(e);
1727
                // wpf generates to many events if mouse is over some visual
1728
                // and OnMouseUp is fired, wtf, anyway...
1729
                // http://greatmaps.codeplex.com/workitem/16013
1730
                if ((e.Timestamp & Int32.MaxValue) - onMouseUpTimestamp < 55)
1731
                {
1732
                    Debug.WriteLine("OnMouseMove skipped: " + ((e.Timestamp & Int32.MaxValue) - onMouseUpTimestamp) + "ms");
1733
                    return;
1734
                }
1735
 
1736
                if (!Core.IsDragging && !Core.mouseDown.IsEmpty)
1737
                {
1738
                    Point p = e.GetPosition(this);
1739
 
1740
                    if (MapScaleTransform != null)
1741
                    {
1742
                        p = MapScaleTransform.Inverse.Transform(p);
1743
                    }
1744
 
1745
                    p = ApplyRotationInversion(p.X, p.Y);
1746
 
1747
                    // cursor has moved beyond drag tolerance
1748
                    if (Math.Abs(p.X - Core.mouseDown.X) * 2 >= SystemParameters.MinimumHorizontalDragDistance || Math.Abs(p.Y - Core.mouseDown.Y) * 2 >= SystemParameters.MinimumVerticalDragDistance)
1749
                    {
1750
                        Core.BeginDrag(Core.mouseDown);
1751
                    }
1752
                }
1753
 
1754
                if (Core.IsDragging)
1755
                {
1756
                    if (!isDragging)
1757
                    {
1758
                        isDragging = true;
1759
                        Debug.WriteLine("IsDragging = " + isDragging);
1760
                        cursorBefore = Cursor;
1761
                        Cursor = Cursors.SizeAll;
1762
                        Mouse.Capture(this);
1763
                    }
1764
 
1765
                    if (BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position))
1766
                    {
1767
                        // ...
1768
                    }
1769
                    else
1770
                    {
1771
                        Point p = e.GetPosition(this);
1772
 
1773
                        if (MapScaleTransform != null)
1774
                        {
1775
                            p = MapScaleTransform.Inverse.Transform(p);
1776
                        }
1777
 
1778
                        p = ApplyRotationInversion(p.X, p.Y);
1779
 
1780
                        Core.mouseCurrent.X = (int)p.X;
1781
                        Core.mouseCurrent.Y = (int)p.Y;
1782
                        {
1783
                            Core.Drag(Core.mouseCurrent);
1784
                        }
1785
 
1786
                        if (IsRotated || scaleMode != ScaleModes.Integer)
1787
                        {
1788
                            ForceUpdateOverlays();
1789
                        }
1790
                        else
1791
                        {
1792
                            UpdateMarkersOffset();
1793
                        }
1794
                    }
1795
                    InvalidateVisual(true);
1796
                }
1797
                else
1798
                {
1799
                    if (isSelected && !selectionStart.IsEmpty && (Keyboard.Modifiers == ModifierKeys.Shift || Keyboard.Modifiers == ModifierKeys.Alt || DisableAltForSelection))
1800
                    {
1801
                        System.Windows.Point p = e.GetPosition(this);
1802
                        selectionEnd = FromLocalToLatLng((int)p.X, (int)p.Y);
1803
                        {
1804
                            GMap.NET.PointLatLng p1 = selectionStart;
1805
                            GMap.NET.PointLatLng p2 = selectionEnd;
1806
 
1807
                            double x1 = Math.Min(p1.Lng, p2.Lng);
1808
                            double y1 = Math.Max(p1.Lat, p2.Lat);
1809
                            double x2 = Math.Max(p1.Lng, p2.Lng);
1810
                            double y2 = Math.Min(p1.Lat, p2.Lat);
1811
 
1812
                            SelectedArea = new RectLatLng(y1, x1, x2 - x1, y1 - y2);
1813
                        }
1814
                    }
1815
 
1816
                    if (renderHelperLine)
1817
                    {
1818
                        InvalidateVisual(true);
1819
                    }
1820
                }
1821
            }    
1822
      }
1823
 
1824
      /// <summary>
1825
      /// if true, selects area just by holding mouse and moving
1826
      /// </summary>
1827
      public bool DisableAltForSelection = false;
1828
 
1829
      protected override void OnStylusDown(StylusDownEventArgs e)
1830
      {
1831
         base.OnStylusDown(e);
1832
 
1833
         if(TouchEnabled && CanDragMap && !e.InAir)
1834
         {
1835
            Point p = e.GetPosition(this);
1836
 
1837
            if(MapScaleTransform != null)
1838
            {
1839
               p = MapScaleTransform.Inverse.Transform(p);
1840
            }
1841
 
1842
            p = ApplyRotationInversion(p.X, p.Y);
1843
 
1844
            Core.mouseDown.X = (int)p.X;
1845
            Core.mouseDown.Y = (int)p.Y;
1846
 
1847
            InvalidateVisual();
1848
         }        
1849
      }
1850
 
1851
      protected override void OnStylusUp(StylusEventArgs e)
1852
      {
1853
         base.OnStylusUp(e);
1854
 
1855
         if(TouchEnabled)
1856
         {
1857
            if(isSelected)
1858
            {
1859
               isSelected = false;
1860
            }
1861
 
1862
            if(Core.IsDragging)
1863
            {
1864
               if(isDragging)
1865
               {
1866
                  onMouseUpTimestamp = e.Timestamp & Int32.MaxValue;
1867
                  isDragging = false;
1868
                  Debug.WriteLine("IsDragging = " + isDragging);
1869
                  Cursor = cursorBefore;
1870
                  Mouse.Capture(null);
1871
               }
1872
               Core.EndDrag();
1873
 
1874
               if(BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position))
1875
               {
1876
                  if(Core.LastLocationInBounds.HasValue)
1877
                  {
1878
                     Position = Core.LastLocationInBounds.Value;
1879
                  }
1880
               }
1881
            }
1882
            else
1883
            {
1884
               Core.mouseDown = GPoint.Empty;
1885
               InvalidateVisual();
1886
            }
1887
         }
1888
      }
1889
 
1890
      protected override void OnStylusMove(StylusEventArgs e)
1891
      {
1892
         base.OnStylusMove(e);
1893
 
1894
         if(TouchEnabled && CanDragMap)
1895
         {
1896
            // wpf generates to many events if mouse is over some visual
1897
            // and OnMouseUp is fired, wtf, anyway...
1898
            // http://greatmaps.codeplex.com/workitem/16013
1899
            if((e.Timestamp & Int32.MaxValue) - onMouseUpTimestamp < 55)
1900
            {
1901
               Debug.WriteLine("OnMouseMove skipped: " + ((e.Timestamp & Int32.MaxValue) - onMouseUpTimestamp) + "ms");
1902
               return;
1903
            }
1904
 
1905
            if(!Core.IsDragging && !Core.mouseDown.IsEmpty)
1906
            {
1907
               Point p = e.GetPosition(this);
1908
 
1909
               if(MapScaleTransform != null)
1910
               {
1911
                  p = MapScaleTransform.Inverse.Transform(p);
1912
               }
1913
 
1914
               p = ApplyRotationInversion(p.X, p.Y);
1915
 
1916
               // cursor has moved beyond drag tolerance
1917
               if(Math.Abs(p.X - Core.mouseDown.X) * 2 >= SystemParameters.MinimumHorizontalDragDistance || Math.Abs(p.Y - Core.mouseDown.Y) * 2 >= SystemParameters.MinimumVerticalDragDistance)
1918
               {
1919
                  Core.BeginDrag(Core.mouseDown);
1920
               }
1921
            }
1922
 
1923
            if(Core.IsDragging)
1924
            {
1925
               if(!isDragging)
1926
               {
1927
                  isDragging = true;
1928
                  Debug.WriteLine("IsDragging = " + isDragging);
1929
                  cursorBefore = Cursor;
1930
                  Cursor = Cursors.SizeAll;
1931
                  Mouse.Capture(this);
1932
               }
1933
 
1934
               if(BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position))
1935
               {
1936
                  // ...
1937
               }
1938
               else
1939
               {
1940
                  Point p = e.GetPosition(this);
1941
 
1942
                  if(MapScaleTransform != null)
1943
                  {
1944
                     p = MapScaleTransform.Inverse.Transform(p);
1945
                  }
1946
 
1947
                  p = ApplyRotationInversion(p.X, p.Y);
1948
 
1949
                  Core.mouseCurrent.X = (int)p.X;
1950
                  Core.mouseCurrent.Y = (int)p.Y;
1951
                  {
1952
                     Core.Drag(Core.mouseCurrent);
1953
                  }
1954
 
1955
                  if(IsRotated)
1956
                  {
1957
                     ForceUpdateOverlays();
1958
                  }
1959
                  else
1960
                  {
1961
                     UpdateMarkersOffset();
1962
                  }
1963
               }
1964
               InvalidateVisual();
1965
            }
1966
         }        
1967
      }
1968
 
1969
      #endregion
1970
 
1971
      #region IGControl Members
1972
 
1973
      /// <summary>
1974
      /// Call it to empty tile cache & reload tiles
1975
      /// </summary>
1976
      public void ReloadMap()
1977
      {
1978
         Core.ReloadMap();
1979
      }
1980
 
1981
      /// <summary>
1982
      /// sets position using geocoder
1983
      /// </summary>
1984
      /// <param name="keys"></param>
1985
      /// <returns></returns>
1986
      public GeoCoderStatusCode SetPositionByKeywords(string keys)
1987
      {
1988
         GeoCoderStatusCode status = GeoCoderStatusCode.Unknow;
1989
 
1990
         GeocodingProvider gp = MapProvider as GeocodingProvider;
1991
         if(gp == null)
1992
         {
1993
            gp = GMapProviders.OpenStreetMap as GeocodingProvider;
1994
         }
1995
 
1996
         if(gp != null)
1997
         {
1998
            var pt = gp.GetPoint(keys, out status);
1999
            if(status == GeoCoderStatusCode.G_GEO_SUCCESS && pt.HasValue)
2000
            {
2001
               Position = pt.Value;
2002
            }
2003
         }
2004
 
2005
         return status;
2006
      }
2007
 
2008
      public PointLatLng FromLocalToLatLng(int x, int y)
2009
      {
2010
         if(MapScaleTransform != null)
2011
         {
2012
            var tp = MapScaleTransform.Inverse.Transform(new System.Windows.Point(x, y));
2013
            x = (int)tp.X;
2014
            y = (int)tp.Y;
2015
         }
2016
 
2017
         if(IsRotated)
2018
         {
2019
            var f = rotationMatrixInvert.Transform(new System.Windows.Point(x, y));
2020
 
2021
            x = (int)f.X;
2022
            y = (int)f.Y;
2023
         }
2024
 
2025
         return Core.FromLocalToLatLng(x, y);
2026
      }
2027
 
2028
      public GPoint FromLatLngToLocal(PointLatLng point)
2029
      {
2030
         GPoint ret = Core.FromLatLngToLocal(point);
2031
 
2032
         if(MapScaleTransform != null)
2033
         {
2034
            var tp = MapScaleTransform.Transform(new System.Windows.Point(ret.X, ret.Y));
2035
            ret.X = (int)tp.X;
2036
            ret.Y = (int)tp.Y;
2037
         }
2038
 
2039
         if(IsRotated)
2040
         {
2041
            var f = rotationMatrix.Transform(new System.Windows.Point(ret.X, ret.Y));
2042
 
2043
            ret.X = (int)f.X;
2044
            ret.Y = (int)f.Y;
2045
         }
2046
 
2047
         return ret;
2048
      }
2049
 
2050
      public bool ShowExportDialog()
2051
      {
2052
         var dlg = new Microsoft.Win32.SaveFileDialog();
2053
         {
2054
            dlg.CheckPathExists = true;
2055
            dlg.CheckFileExists = false;
2056
            dlg.AddExtension = true;
2057
            dlg.DefaultExt = "gmdb";
2058
            dlg.ValidateNames = true;
2059
            dlg.Title = "GMap.NET: Export map to db, if file exsist only new data will be added";
2060
            dlg.FileName = "DataExp";
2061
            dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
2062
            dlg.Filter = "GMap.NET DB files (*.gmdb)|*.gmdb";
2063
            dlg.FilterIndex = 1;
2064
            dlg.RestoreDirectory = true;
2065
 
2066
            if(dlg.ShowDialog() == true)
2067
            {
2068
               bool ok = GMaps.Instance.ExportToGMDB(dlg.FileName);
2069
               if(ok)
2070
               {
2071
                  MessageBox.Show("Complete!", "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Information);
2072
               }
2073
               else
2074
               {
2075
                  MessageBox.Show("  Failed!", "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Warning);
2076
               }
2077
 
2078
               return ok;
2079
            }
2080
         }
2081
 
2082
         return false;
2083
      }
2084
 
2085
      public bool ShowImportDialog()
2086
      {
2087
         var dlg = new Microsoft.Win32.OpenFileDialog();
2088
         {
2089
            dlg.CheckPathExists = true;
2090
            dlg.CheckFileExists = false;
2091
            dlg.AddExtension = true;
2092
            dlg.DefaultExt = "gmdb";
2093
            dlg.ValidateNames = true;
2094
            dlg.Title = "GMap.NET: Import to db, only new data will be added";
2095
            dlg.FileName = "DataImport";
2096
            dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
2097
            dlg.Filter = "GMap.NET DB files (*.gmdb)|*.gmdb";
2098
            dlg.FilterIndex = 1;
2099
            dlg.RestoreDirectory = true;
2100
 
2101
            if(dlg.ShowDialog() == true)
2102
            {
2103
               Cursor = Cursors.Wait;
2104
 
2105
               bool ok = GMaps.Instance.ImportFromGMDB(dlg.FileName);
2106
               if(ok)
2107
               {
2108
                  MessageBox.Show("Complete!", "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Information);
2109
                  ReloadMap();
2110
               }
2111
               else
2112
               {
2113
                  MessageBox.Show("  Failed!", "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Warning);
2114
               }
2115
 
2116
               Cursor = Cursors.Arrow;
2117
 
2118
               return ok;
2119
            }
2120
         }
2121
 
2122
         return false;
2123
      }
2124
 
2125
      /// <summary>
2126
      /// current coordinates of the map center
2127
      /// </summary>
2128
      [Browsable(false)]
2129
      public PointLatLng Position
2130
      {
2131
         get
2132
         {
2133
            return Core.Position;
2134
         }
2135
         set
2136
         {
2137
            Core.Position = value;
2138
 
2139
            if(Core.IsStarted)
2140
            {
2141
               ForceUpdateOverlays();
2142
            }
2143
         }
2144
      }
2145
 
2146
      [Browsable(false)]
2147
      public GPoint PositionPixel
2148
      {
2149
         get
2150
         {
2151
            return Core.PositionPixel;
2152
         }
2153
      }
2154
 
2155
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
2156
      [Browsable(false)]
2157
      public string CacheLocation
2158
      {
2159
         get
2160
         {
2161
            return CacheLocator.Location;
2162
         }
2163
         set
2164
         {
2165
            CacheLocator.Location = value;
2166
         }
2167
      }
2168
 
2169
      bool isDragging = false;
2170
 
2171
      [Browsable(false)]
2172
      public bool IsDragging
2173
      {
2174
         get
2175
         {
2176
            return isDragging;
2177
         }
2178
      }
2179
 
2180
      [Browsable(false)]
2181
      public RectLatLng ViewArea
2182
      {
2183
         get
2184
         {
2185
             if(!IsRotated)
2186
             {
2187
                 return Core.ViewArea;
2188
             }
2189
             else if(Core.Provider.Projection != null)
2190
             {
2191
                 var p = FromLocalToLatLng(0, 0);
2192
                 var p2 = FromLocalToLatLng((int)Width, (int)Height);
2193
 
2194
                 return RectLatLng.FromLTRB(p.Lng, p.Lat, p2.Lng, p2.Lat);
2195
             }
2196
             return RectLatLng.Empty;
2197
         }
2198
      }
2199
 
2200
      [Category("GMap.NET")]
2201
      public bool CanDragMap
2202
      {
2203
         get
2204
         {
2205
            return Core.CanDragMap;
2206
         }
2207
         set
2208
         {
2209
            Core.CanDragMap = value;
2210
         }
2211
      }
2212
 
2213
      public GMap.NET.RenderMode RenderMode
2214
      {
2215
         get
2216
         {
2217
            return GMap.NET.RenderMode.WPF;
2218
         }
2219
      }
2220
 
2221
      #endregion
2222
 
2223
      #region IGControl event Members
2224
 
2225
      public event PositionChanged OnPositionChanged
2226
      {
2227
         add
2228
         {
2229
            Core.OnCurrentPositionChanged += value;
2230
         }
2231
         remove
2232
         {
2233
            Core.OnCurrentPositionChanged -= value;
2234
         }
2235
      }
2236
 
2237
      public event TileLoadComplete OnTileLoadComplete
2238
      {
2239
         add
2240
         {
2241
            Core.OnTileLoadComplete += value;
2242
         }
2243
         remove
2244
         {
2245
            Core.OnTileLoadComplete -= value;
2246
         }
2247
      }
2248
 
2249
      public event TileLoadStart OnTileLoadStart
2250
      {
2251
         add
2252
         {
2253
            Core.OnTileLoadStart += value;
2254
         }
2255
         remove
2256
         {
2257
            Core.OnTileLoadStart -= value;
2258
         }
2259
      }
2260
 
2261
      public event MapDrag OnMapDrag
2262
      {
2263
         add
2264
         {
2265
            Core.OnMapDrag += value;
2266
         }
2267
         remove
2268
         {
2269
            Core.OnMapDrag -= value;
2270
         }
2271
      }
2272
 
2273
      public event MapZoomChanged OnMapZoomChanged
2274
      {
2275
         add
2276
         {
2277
            Core.OnMapZoomChanged += value;
2278
         }
2279
         remove
2280
         {
2281
            Core.OnMapZoomChanged -= value;
2282
         }
2283
      }
2284
 
2285
      /// <summary>
2286
      /// occures on map type changed
2287
      /// </summary>
2288
      public event MapTypeChanged OnMapTypeChanged
2289
      {
2290
         add
2291
         {
2292
            Core.OnMapTypeChanged += value;
2293
         }
2294
         remove
2295
         {
2296
            Core.OnMapTypeChanged -= value;
2297
         }
2298
      }
2299
 
2300
      /// <summary>
2301
      /// occurs on empty tile displayed
2302
      /// </summary>
2303
      public event EmptyTileError OnEmptyTileError
2304
      {
2305
         add
2306
         {
2307
            Core.OnEmptyTileError += value;
2308
         }
2309
         remove
2310
         {
2311
            Core.OnEmptyTileError -= value;
2312
         }
2313
      }
2314
      #endregion
2315
 
2316
      #region IDisposable Members
2317
 
2318
      public virtual void Dispose()
2319
      {
2320
         if(Core.IsStarted)
2321
         {
2322
            Core.OnMapZoomChanged -= new MapZoomChanged(ForceUpdateOverlays);
2323
            Loaded -= new RoutedEventHandler(GMapControl_Loaded);
2324
            Dispatcher.ShutdownStarted -= new EventHandler(Dispatcher_ShutdownStarted);
2325
            SizeChanged -= new SizeChangedEventHandler(GMapControl_SizeChanged);
2326
            if(loadedApp != null)
2327
            {
2328
               loadedApp.SessionEnding -= new SessionEndingCancelEventHandler(Current_SessionEnding);
2329
            }
2330
            Core.OnMapClose();
2331
         }
2332
      }
2333
 
2334
      #endregion
2335
   }
2336
 
2337
   public enum HelperLineOptions
2338
   {
2339
      DontShow = 0,
2340
      ShowAlways = 1,
2341
      ShowOnModifierKey = 2
2342
   }
2343
 
2344
   public enum ScaleModes
2345
   {
2346
      /// <summary>
2347
      /// no scaling
2348
      /// </summary>
2349
      Integer,
2350
 
2351
      /// <summary>
2352
      /// scales to fractional level using a stretched tiles, any issues -> http://greatmaps.codeplex.com/workitem/16046
2353
      /// </summary>
2354
      ScaleUp,
2355
 
2356
      /// <summary>
2357
      /// scales to fractional level using a narrowed tiles, any issues -> http://greatmaps.codeplex.com/workitem/16046
2358
      /// </summary>
2359
      ScaleDown,
2360
 
2361
      /// <summary>
2362
      /// scales to fractional level using a combination both stretched and narrowed tiles, any issues -> http://greatmaps.codeplex.com/workitem/16046
2363
      /// </summary>
2364
      Dynamic
2365
   }
2366
 
2367
   public delegate void SelectionChange(RectLatLng Selection, bool ZoomToFit);
2368
}