Posted By

mkurdziel on 04/22/10


Tagged


Versions (?)

Objects in Adorner


 / Published in: C#
 

URL: http://dvuyka.spaces.live.com/blog/cns!305B02907E9BE19A!144.entry

  1. using System;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using System.Windows.Controls.Primitives;
  5. using System.Windows.Documents;
  6. using System.Windows.Input;
  7. using System.Windows.Media;
  8.  
  9. namespace adorners
  10. {
  11. public class ResizingAdorner : Adorner
  12. {
  13. // Resizing adorner uses Thumbs for visual elements.
  14. // The Thumbs have built-in mouse input handling.
  15. Thumb topLeft, topRight, bottomLeft, bottomRight;
  16.  
  17. // To store and manage the adorner's visual children.
  18. VisualCollection visualChildren;
  19.  
  20. // Initialize the ResizingAdorner.
  21. public ResizingAdorner(UIElement adornedElement)
  22. : base(adornedElement)
  23. {
  24. visualChildren = new VisualCollection(this);
  25.  
  26. // Call a helper method to initialize the Thumbs
  27. // with a customized cursors.
  28. BuildAdornerCorner(ref topLeft, Cursors.SizeNWSE);
  29. BuildAdornerCorner(ref topRight, Cursors.SizeNESW);
  30. BuildAdornerCorner(ref bottomLeft, Cursors.SizeNESW);
  31. BuildAdornerCorner(ref bottomRight, Cursors.SizeNWSE);
  32.  
  33. // Add handlers for resizing.
  34. bottomLeft.DragDelta += new DragDeltaEventHandler(HandleBottomLeft);
  35. bottomRight.DragDelta += new DragDeltaEventHandler(HandleBottomRight);
  36. topLeft.DragDelta += new DragDeltaEventHandler(HandleTopLeft);
  37. topRight.DragDelta += new DragDeltaEventHandler(HandleTopRight);
  38. }
  39.  
  40. // Handler for resizing from the bottom-right.
  41. void HandleBottomRight(object sender, DragDeltaEventArgs args)
  42. {
  43. FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
  44. Thumb hitThumb = sender as Thumb;
  45.  
  46. if (adornedElement == null || hitThumb == null) return;
  47. FrameworkElement parentElement = adornedElement.Parent as FrameworkElement;
  48.  
  49. // Ensure that the Width and Height are properly initialized after the resize.
  50. EnforceSize(adornedElement);
  51.  
  52. // Change the size by the amount the user drags the mouse, as long as it's larger
  53. // than the width or height of an adorner, respectively.
  54. adornedElement.Width = Math.Max(adornedElement.Width + args.HorizontalChange, hitThumb.DesiredSize.Width);
  55. adornedElement.Height = Math.Max(args.VerticalChange + adornedElement.Height, hitThumb.DesiredSize.Height);
  56. }
  57.  
  58. // Handler for resizing from the top-right.
  59. void HandleTopRight(object sender, DragDeltaEventArgs args)
  60. {
  61. FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
  62. Thumb hitThumb = sender as Thumb;
  63.  
  64. if (adornedElement == null || hitThumb == null) return;
  65. FrameworkElement parentElement = adornedElement.Parent as FrameworkElement;
  66.  
  67. // Ensure that the Width and Height are properly initialized after the resize.
  68. EnforceSize(adornedElement);
  69.  
  70. // Change the size by the amount the user drags the mouse, as long as it's larger
  71. // than the width or height of an adorner, respectively.
  72. adornedElement.Width = Math.Max(adornedElement.Width + args.HorizontalChange, hitThumb.DesiredSize.Width);
  73. //adornedElement.Height = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
  74.  
  75. double height_old = adornedElement.Height;
  76. double height_new = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
  77. double top_old = Canvas.GetTop(adornedElement);
  78. adornedElement.Height = height_new;
  79. Canvas.SetTop(adornedElement, top_old - (height_new - height_old));
  80. }
  81.  
  82. // Handler for resizing from the top-left.
  83. void HandleTopLeft(object sender, DragDeltaEventArgs args)
  84. {
  85. FrameworkElement adornedElement = AdornedElement as FrameworkElement;
  86. Thumb hitThumb = sender as Thumb;
  87.  
  88. if (adornedElement == null || hitThumb == null) return;
  89.  
  90. // Ensure that the Width and Height are properly initialized after the resize.
  91. EnforceSize(adornedElement);
  92.  
  93. // Change the size by the amount the user drags the mouse, as long as it's larger
  94. // than the width or height of an adorner, respectively.
  95. //adornedElement.Width = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
  96. //adornedElement.Height = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
  97.  
  98. double width_old = adornedElement.Width;
  99. double width_new = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
  100. double left_old = Canvas.GetLeft(adornedElement);
  101. adornedElement.Width = width_new;
  102. Canvas.SetLeft(adornedElement, left_old - (width_new - width_old));
  103.  
  104. double height_old = adornedElement.Height;
  105. double height_new = Math.Max(adornedElement.Height - args.VerticalChange, hitThumb.DesiredSize.Height);
  106. double top_old = Canvas.GetTop(adornedElement);
  107. adornedElement.Height = height_new;
  108. Canvas.SetTop(adornedElement, top_old - (height_new - height_old));
  109. }
  110.  
  111. // Handler for resizing from the bottom-left.
  112. void HandleBottomLeft(object sender, DragDeltaEventArgs args)
  113. {
  114. FrameworkElement adornedElement = AdornedElement as FrameworkElement;
  115. Thumb hitThumb = sender as Thumb;
  116.  
  117. if (adornedElement == null || hitThumb == null) return;
  118.  
  119. // Ensure that the Width and Height are properly initialized after the resize.
  120. EnforceSize(adornedElement);
  121.  
  122. // Change the size by the amount the user drags the mouse, as long as it's larger
  123. // than the width or height of an adorner, respectively.
  124. //adornedElement.Width = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
  125. adornedElement.Height = Math.Max(args.VerticalChange + adornedElement.Height, hitThumb.DesiredSize.Height);
  126.  
  127. double width_old = adornedElement.Width;
  128. double width_new = Math.Max(adornedElement.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
  129. double left_old = Canvas.GetLeft(adornedElement);
  130. adornedElement.Width = width_new;
  131. Canvas.SetLeft(adornedElement, left_old - (width_new - width_old));
  132. }
  133.  
  134. // Arrange the Adorners.
  135. protected override Size ArrangeOverride(Size finalSize)
  136. {
  137. // desiredWidth and desiredHeight are the width and height of the element that's being adorned.
  138. // These will be used to place the ResizingAdorner at the corners of the adorned element.
  139. double desiredWidth = AdornedElement.DesiredSize.Width;
  140. double desiredHeight = AdornedElement.DesiredSize.Height;
  141. // adornerWidth & adornerHeight are used for placement as well.
  142. double adornerWidth = this.DesiredSize.Width;
  143. double adornerHeight = this.DesiredSize.Height;
  144.  
  145. topLeft.Arrange(new Rect(-adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight));
  146. topRight.Arrange(new Rect(desiredWidth - adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight));
  147. bottomLeft.Arrange(new Rect(-adornerWidth / 2, desiredHeight - adornerHeight / 2, adornerWidth, adornerHeight));
  148. bottomRight.Arrange(new Rect(desiredWidth - adornerWidth / 2, desiredHeight - adornerHeight / 2, adornerWidth, adornerHeight));
  149.  
  150. // Return the final size.
  151. return finalSize;
  152. }
  153.  
  154. // Helper method to instantiate the corner Thumbs, set the Cursor property,
  155. // set some appearance properties, and add the elements to the visual tree.
  156. void BuildAdornerCorner(ref Thumb cornerThumb, Cursor customizedCursor)
  157. {
  158. if (cornerThumb != null) return;
  159.  
  160. cornerThumb = new Thumb();
  161.  
  162. // Set some arbitrary visual characteristics.
  163. cornerThumb.Cursor = customizedCursor;
  164. cornerThumb.Height = cornerThumb.Width = 10;
  165. cornerThumb.Opacity = 0.40;
  166. cornerThumb.Background = new SolidColorBrush(Colors.MediumBlue);
  167.  
  168. visualChildren.Add(cornerThumb);
  169. }
  170.  
  171. // This method ensures that the Widths and Heights are initialized. Sizing to content produces
  172. // Width and Height values of Double.NaN. Because this Adorner explicitly resizes, the Width and Height
  173. // need to be set first. It also sets the maximum size of the adorned element.
  174. void EnforceSize(FrameworkElement adornedElement)
  175. {
  176. if (adornedElement.Width.Equals(Double.NaN))
  177. adornedElement.Width = adornedElement.DesiredSize.Width;
  178. if (adornedElement.Height.Equals(Double.NaN))
  179. adornedElement.Height = adornedElement.DesiredSize.Height;
  180.  
  181. FrameworkElement parent = adornedElement.Parent as FrameworkElement;
  182. if (parent != null)
  183. {
  184. adornedElement.MaxHeight = parent.ActualHeight;
  185. adornedElement.MaxWidth = parent.ActualWidth;
  186. }
  187. }
  188. // Override the VisualChildrenCount and GetVisualChild properties to interface with
  189. // the adorner's visual collection.
  190. protected override int VisualChildrenCount { get { return visualChildren.Count; } }
  191. protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
  192. }
  193. }

Report this snippet  

You need to login to post a comment.