PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/CommonAPI/API/ESRI.ArcGIS.Client.Toolkit/Magnifier/MagnifyingGlass.cs

#
C# | 349 lines | 270 code | 30 blank | 49 comment | 67 complexity | d7b7e9fe4dee5715de08b8f530e81a27 MD5 | raw file
  1. // (c) Copyright ESRI.
  2. // This source is subject to the Microsoft Public License (Ms-PL).
  3. // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
  4. // All other rights reserved.
  5. using System;
  6. using System.Linq;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Input;
  10. using ESRI.ArcGIS.Client.Geometry;
  11. using System.Windows.Media;
  12. namespace ESRI.ArcGIS.Client.Toolkit
  13. {
  14. /// <summary>
  15. /// Magnifying control for the <see cref="ESRI.ArcGIS.Client.Map"/> using a <see cref="TiledMapServiceLayer"/>.
  16. /// </summary>
  17. /// <remarks>
  18. /// If you require multiple layer or dynamic layers in your magnifier,
  19. /// use the <see cref="Magnifier"/> control instead.
  20. /// </remarks>
  21. [TemplatePart(Name = "bigMap", Type = typeof(Map))]
  22. [System.Windows.Markup.ContentProperty("Layer")]
  23. public class MagnifyingGlass : Control
  24. {
  25. Map bigMap;
  26. Cursor cursor;
  27. double lastResolution = double.NaN;
  28. Point beginP;
  29. Point currentP;
  30. bool dragOn = false;
  31. /// <summary>
  32. /// Initializes a new instance of the <see cref="MagnifyingGlass"/> class.
  33. /// </summary>
  34. public MagnifyingGlass()
  35. {
  36. #if SILVERLIGHT
  37. DefaultStyleKey = typeof(MagnifyingGlass);
  38. #endif
  39. this.Opacity = 0.0;
  40. ZoomFactor = 5;
  41. }
  42. /// <summary>
  43. /// Static initialization for the <see cref="MagnifyingGlass"/> control.
  44. /// </summary>
  45. static MagnifyingGlass()
  46. {
  47. #if !SILVERLIGHT
  48. DefaultStyleKeyProperty.OverrideMetadata(typeof(MagnifyingGlass),
  49. new FrameworkPropertyMetadata(typeof(MagnifyingGlass)));
  50. #endif
  51. }
  52. /// <summary>
  53. /// Provides the behavior for the "Arrange" pass of Silverlight layout.
  54. /// Classes can override this method to define their own arrange pass behavior.
  55. /// </summary>
  56. /// <param name="finalSize">The final area within the parent that
  57. /// this object should use to arrange itself and its children.</param>
  58. /// <returns>The actual size used.</returns>
  59. protected override Size ArrangeOverride(Size finalSize)
  60. {
  61. if (this.Visibility == Visibility.Visible)
  62. {
  63. //Visibility has changed. Update extent
  64. Dispatcher.BeginInvoke((Action) delegate()
  65. {
  66. SetMagnifyResolution();
  67. UpdateMagnifyMapCenter();
  68. });
  69. }
  70. return base.ArrangeOverride(finalSize);
  71. }
  72. /// <summary>
  73. /// When overridden in a derived class, is invoked whenever application
  74. /// code or internal processes (such as a rebuilding layout pass) call
  75. /// <see cref="M:System.Windows.Controls.Control.ApplyTemplate"/>.
  76. /// </summary>
  77. public override void OnApplyTemplate()
  78. {
  79. base.OnApplyTemplate();
  80. if (this.Layer != null && bigMap != null)
  81. {
  82. bigMap.Layers.Remove(this.Layer);
  83. }
  84. bigMap = GetTemplateChild("bigMap") as Map;
  85. if (bigMap == null)
  86. {
  87. throw new ArgumentNullException(Properties.Resources.MagnifyingGlass_BigMapNotFoundInTemplate);
  88. }
  89. bigMap.Layers.LayersInitialized += Layers_LayersInitialized;
  90. if(Layer != null)
  91. bigMap.Layers.Add(Layer);
  92. bigMap.MinimumResolution = double.Epsilon;
  93. bigMap.MaximumResolution = double.MaxValue;
  94. this.MouseLeftButtonDown += MagnifyBox_MouseLeftButtonDown;
  95. this.MouseMove += MagnifyBox_MouseMove;
  96. this.MouseLeftButtonUp += MagnifyBox_MouseLeftButtonUp;
  97. this.Opacity = 1;
  98. if ((this.Visibility == Visibility.Visible) && Map != null)
  99. {
  100. Dispatcher.BeginInvoke((Action)delegate()
  101. {
  102. SetMagnifyResolution();
  103. UpdateMagnifyMapCenter();
  104. });
  105. }
  106. }
  107. private void Layers_LayersInitialized(object sender, EventArgs args)
  108. {
  109. SetMagnifyResolution();
  110. UpdateMagnifyMapCenter();
  111. }
  112. private void MagnifyBox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  113. {
  114. if (dragOn)
  115. {
  116. this.ReleaseMouseCapture();
  117. dragOn = false;
  118. }
  119. this.Cursor = cursor;
  120. }
  121. private void MagnifyBox_MouseMove(object sender, MouseEventArgs e)
  122. {
  123. if (dragOn)
  124. {
  125. currentP = e.GetPosition(null);
  126. double x0 = System.Convert.ToDouble(this.GetValue(Canvas.LeftProperty));
  127. double y0 = System.Convert.ToDouble(this.GetValue(Canvas.TopProperty));
  128. ApplyTranslationTransform(currentP.X - beginP.X, currentP.Y - beginP.Y);
  129. beginP = currentP;
  130. UpdateMagnifyMapCenter();
  131. }
  132. }
  133. private void ApplyTranslationTransform(double x, double y)
  134. {
  135. if (this.FlowDirection == System.Windows.FlowDirection.RightToLeft)
  136. x = -x;
  137. Transform renderTransform = this.RenderTransform;
  138. TransformGroup group = renderTransform as TransformGroup;
  139. MatrixTransform transform2 = renderTransform as MatrixTransform;
  140. TranslateTransform transform3 = renderTransform as TranslateTransform;
  141. if (transform3 == null)
  142. {
  143. if (group != null)
  144. {
  145. if (group.Children.Count > 0)
  146. {
  147. transform3 = group.Children[group.Children.Count - 1] as TranslateTransform;
  148. }
  149. if (transform3 == null)
  150. {
  151. transform3 = new TranslateTransform();
  152. group.Children.Add(transform3);
  153. }
  154. }
  155. else
  156. {
  157. if (transform2 != null)
  158. {
  159. Matrix matrix = transform2.Matrix;
  160. matrix.OffsetX += x;
  161. matrix.OffsetY += y;
  162. MatrixTransform transform4 = new MatrixTransform();
  163. transform4.Matrix = matrix;
  164. this.RenderTransform = transform4;
  165. return;
  166. }
  167. TransformGroup group2 = new TransformGroup();
  168. transform3 = new TranslateTransform();
  169. if (renderTransform != null)
  170. {
  171. group2.Children.Add(renderTransform);
  172. }
  173. group2.Children.Add(transform3);
  174. this.RenderTransform = group2;
  175. }
  176. }
  177. transform3.X += x;
  178. transform3.Y += y;
  179. }
  180. private void MagnifyBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  181. {
  182. cursor = this.Cursor;
  183. this.Cursor = Cursors.None;
  184. dragOn = true;
  185. beginP = e.GetPosition(null);
  186. this.CaptureMouse();
  187. }
  188. private void map_ExtentChanging(object sender, ExtentEventArgs e)
  189. {
  190. UpdateMagnifyMapCenter();
  191. }
  192. private void map_ExtentChanged(object sender, ExtentEventArgs e)
  193. {
  194. if (this.Map.Resolution != lastResolution)
  195. SetMagnifyResolution();
  196. UpdateMagnifyMapCenter();
  197. }
  198. private void SetMagnifyResolution()
  199. {
  200. if (this.Map == null || this.Map.Extent == null) return;
  201. double mapRes = this.Map.Resolution;
  202. double magRes = mapRes / ZoomFactor;
  203. if (bigMap != null && bigMap.Resolution != magRes)
  204. {
  205. if (bigMap.Extent == null)
  206. {
  207. MapPoint center = this.Map.Extent.GetCenter();
  208. bigMap.Extent = new Envelope(center.X - bigMap.ActualWidth * mapRes,
  209. center.Y - bigMap.ActualWidth * mapRes,
  210. center.X + bigMap.ActualWidth * mapRes,
  211. center.Y + bigMap.ActualWidth * mapRes);
  212. }
  213. bigMap.Rotation = Map.Rotation;
  214. bigMap.ZoomToResolution(magRes);
  215. }
  216. }
  217. private void UpdateMagnifyMapCenter()
  218. {
  219. if (this.Visibility == Visibility.Collapsed) return;
  220. if (bigMap != null && Map != null)
  221. {
  222. try
  223. {
  224. Point p = TransformToVisual(this.Map).Transform(new Point((this.RenderSize.Width * .5), (this.RenderSize.Height * .5)));
  225. MapPoint center = this.Map.ScreenToMap(p);
  226. if (center != null)
  227. bigMap.PanTo(center);
  228. }
  229. catch (ArgumentException) //Resizing elements at design time can cause errors
  230. {
  231. }
  232. }
  233. }
  234. /// <summary>
  235. /// Identifies the <see cref="Layer"/> dependency property.
  236. /// </summary>
  237. public static readonly DependencyProperty LayerProperty = DependencyProperty.Register("Layer", typeof(TiledMapServiceLayer), typeof(MagnifyingGlass), new PropertyMetadata(OnLayerPropertyChanged));
  238. private static void OnLayerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  239. {
  240. MagnifyingGlass mag = d as MagnifyingGlass;
  241. if (mag.bigMap != null)
  242. {
  243. mag.bigMap.Layers.Clear();
  244. if (mag.Layer != null)
  245. mag.bigMap.Layers.Add(mag.Layer);
  246. }
  247. }
  248. /// <summary>
  249. /// Gets or sets the layer used in the overview map.
  250. /// </summary>
  251. /// <value>The layer.</value>
  252. public TiledMapServiceLayer Layer
  253. {
  254. get { return (TiledMapServiceLayer)GetValue(LayerProperty); }
  255. set { SetValue(LayerProperty, value); }
  256. }
  257. /// <summary>
  258. /// Identifies the <see cref="Map"/> dependency property.
  259. /// </summary>
  260. public static readonly DependencyProperty MapProperty = DependencyProperty.Register("Map", typeof(Map), typeof(MagnifyingGlass), new PropertyMetadata(OnMapPropertyChanged));
  261. private static void OnMapPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  262. {
  263. MagnifyingGlass mag = d as MagnifyingGlass;
  264. Map old = e.OldValue as Map;
  265. if (old != null) //clean up
  266. {
  267. if (mag.bigMap != null)
  268. mag.bigMap.Layers.Clear();
  269. old.RotationChanged -= mag.map_RotationChanged;
  270. old.ExtentChanged -= mag.map_ExtentChanged;
  271. old.ExtentChanging -= mag.map_ExtentChanging;
  272. }
  273. Map newMap = e.NewValue as Map;
  274. if (newMap != null)
  275. {
  276. if (mag.bigMap != null)
  277. {
  278. if (mag.Layer != null && !mag.bigMap.Layers.Any()) // the layer may have laready b een added OnLayerChanegd or OnApplyTemplate events
  279. mag.bigMap.Layers.Add(mag.Layer);
  280. mag.bigMap.Rotation = newMap.Rotation;
  281. }
  282. newMap.RotationChanged += mag.map_RotationChanged;
  283. newMap.ExtentChanged += mag.map_ExtentChanged;
  284. newMap.ExtentChanging += mag.map_ExtentChanging;
  285. }
  286. }
  287. private void map_RotationChanged(object sender, DependencyPropertyChangedEventArgs e)
  288. {
  289. if (bigMap == null) return;
  290. bigMap.Rotation = (this.FlowDirection == System.Windows.FlowDirection.LeftToRight) ? (double)e.NewValue : -(double)e.NewValue;
  291. UpdateMagnifyMapCenter();
  292. }
  293. /// <summary>
  294. /// Sets or gets the Map control associated with the OverviewMap.
  295. /// </summary>
  296. public Map Map
  297. {
  298. get { return (Map)GetValue(MapProperty); }
  299. set { SetValue(MapProperty, value); }
  300. }
  301. /// <summary>
  302. /// Identifies the <see cref="ZoomFactor"/> dependency property.
  303. /// </summary>
  304. public static readonly DependencyProperty ZoomFactorProperty = DependencyProperty.Register("ZoomFactor", typeof(double), typeof(MagnifyingGlass), new PropertyMetadata(OnZoomFactorPropertyChanged));
  305. private static void OnZoomFactorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  306. {
  307. MagnifyingGlass mag = d as MagnifyingGlass;
  308. mag.SetMagnifyResolution();
  309. }
  310. /// <summary>
  311. /// Gets or sets the zoom factor.
  312. /// </summary>
  313. public double ZoomFactor
  314. {
  315. get { return (double)GetValue(ZoomFactorProperty); }
  316. set { SetValue(ZoomFactorProperty, value); }
  317. }
  318. }
  319. }