[12762] | 1 | // <copyright>
|
---|
| 2 | // This control is created by Ashley Davis and copyrighted under CPOL, and available as part of
|
---|
| 3 | // a CodeProject article at
|
---|
| 4 | // http://www.codeproject.com/KB/WPF/zoomandpancontrol.aspx
|
---|
| 5 | // <date>This code is based on the article dated: 29 Jun 2010</date>
|
---|
| 6 | // </copyright>
|
---|
| 7 |
|
---|
| 8 | using System;
|
---|
| 9 | using System.Linq;
|
---|
| 10 | using System.Text;
|
---|
| 11 | using System.Collections.Generic;
|
---|
| 12 |
|
---|
| 13 | using System.Windows;
|
---|
| 14 | using System.Windows.Media;
|
---|
| 15 | using System.Windows.Controls;
|
---|
| 16 |
|
---|
| 17 | namespace SharpVectors.Runtime
|
---|
| 18 | {
|
---|
| 19 | /// <summary>
|
---|
| 20 | /// This is an extension to the ZoomPanControl class that implements
|
---|
| 21 | /// the IScrollInfo interface properties and functions.
|
---|
| 22 | ///
|
---|
| 23 | /// IScrollInfo is implemented to allow ZoomPanControl to be wrapped (in XAML)
|
---|
| 24 | /// in a ScrollViewer. IScrollInfo allows the ScrollViewer and ZoomPanControl to
|
---|
| 25 | /// communicate important information such as the horizontal and vertical scrollbar offsets.
|
---|
| 26 | ///
|
---|
| 27 | /// There is a good series of articles showing how to implement IScrollInfo starting here:
|
---|
| 28 | /// http://blogs.msdn.com/bencon/archive/2006/01/05/509991.aspx
|
---|
| 29 | ///
|
---|
| 30 | /// </summary>
|
---|
| 31 | public partial class ZoomPanControl
|
---|
| 32 | {
|
---|
| 33 | #region Public Properties
|
---|
| 34 |
|
---|
| 35 | /// <summary>
|
---|
| 36 | /// Set to 'true' when the vertical scrollbar is enabled.
|
---|
| 37 | /// </summary>
|
---|
| 38 | public bool CanVerticallyScroll
|
---|
| 39 | {
|
---|
| 40 | get
|
---|
| 41 | {
|
---|
| 42 | return canVerticallyScroll;
|
---|
| 43 | }
|
---|
| 44 | set
|
---|
| 45 | {
|
---|
| 46 | canVerticallyScroll = value;
|
---|
| 47 | }
|
---|
| 48 | }
|
---|
| 49 |
|
---|
| 50 | /// <summary>
|
---|
| 51 | /// Set to 'true' when the vertical scrollbar is enabled.
|
---|
| 52 | /// </summary>
|
---|
| 53 | public bool CanHorizontallyScroll
|
---|
| 54 | {
|
---|
| 55 | get
|
---|
| 56 | {
|
---|
| 57 | return canHorizontallyScroll;
|
---|
| 58 | }
|
---|
| 59 | set
|
---|
| 60 | {
|
---|
| 61 | canHorizontallyScroll = value;
|
---|
| 62 | }
|
---|
| 63 | }
|
---|
| 64 |
|
---|
| 65 | /// <summary>
|
---|
| 66 | /// The width of the content (with 'ContentScale' applied).
|
---|
| 67 | /// </summary>
|
---|
| 68 | public double ExtentWidth
|
---|
| 69 | {
|
---|
| 70 | get
|
---|
| 71 | {
|
---|
| 72 | return unScaledExtent.Width * ContentScale;
|
---|
| 73 | }
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 76 | /// <summary>
|
---|
| 77 | /// The height of the content (with 'ContentScale' applied).
|
---|
| 78 | /// </summary>
|
---|
| 79 | public double ExtentHeight
|
---|
| 80 | {
|
---|
| 81 | get
|
---|
| 82 | {
|
---|
| 83 | return unScaledExtent.Height * ContentScale;
|
---|
| 84 | }
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 | /// <summary>
|
---|
| 88 | /// Get the width of the viewport onto the content.
|
---|
| 89 | /// </summary>
|
---|
| 90 | public double ViewportWidth
|
---|
| 91 | {
|
---|
| 92 | get
|
---|
| 93 | {
|
---|
| 94 | return viewport.Width;
|
---|
| 95 | }
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | /// <summary>
|
---|
| 99 | /// Get the height of the viewport onto the content.
|
---|
| 100 | /// </summary>
|
---|
| 101 | public double ViewportHeight
|
---|
| 102 | {
|
---|
| 103 | get
|
---|
| 104 | {
|
---|
| 105 | return viewport.Height;
|
---|
| 106 | }
|
---|
| 107 | }
|
---|
| 108 |
|
---|
| 109 | /// <summary>
|
---|
| 110 | /// Reference to the ScrollViewer that is wrapped (in XAML) around the ZoomPanControl.
|
---|
| 111 | /// Or set to null if there is no ScrollViewer.
|
---|
| 112 | /// </summary>
|
---|
| 113 | public ScrollViewer ScrollOwner
|
---|
| 114 | {
|
---|
| 115 | get
|
---|
| 116 | {
|
---|
| 117 | return scrollOwner;
|
---|
| 118 | }
|
---|
| 119 | set
|
---|
| 120 | {
|
---|
| 121 | scrollOwner = value;
|
---|
| 122 | }
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | /// <summary>
|
---|
| 126 | /// The offset of the horizontal scrollbar.
|
---|
| 127 | /// </summary>
|
---|
| 128 | public double HorizontalOffset
|
---|
| 129 | {
|
---|
| 130 | get
|
---|
| 131 | {
|
---|
| 132 | return ContentOffsetX * ContentScale;
|
---|
| 133 | }
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | /// <summary>
|
---|
| 137 | /// The offset of the vertical scrollbar.
|
---|
| 138 | /// </summary>
|
---|
| 139 | public double VerticalOffset
|
---|
| 140 | {
|
---|
| 141 | get
|
---|
| 142 | {
|
---|
| 143 | return ContentOffsetY * ContentScale;
|
---|
| 144 | }
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | /// <summary>
|
---|
| 148 | /// Called when the offset of the horizontal scrollbar has been set.
|
---|
| 149 | /// </summary>
|
---|
| 150 | public void SetHorizontalOffset(double offset)
|
---|
| 151 | {
|
---|
| 152 | if (disableScrollOffsetSync)
|
---|
| 153 | {
|
---|
| 154 | return;
|
---|
| 155 | }
|
---|
| 156 |
|
---|
| 157 | try
|
---|
| 158 | {
|
---|
| 159 | disableScrollOffsetSync = true;
|
---|
| 160 |
|
---|
| 161 | ContentOffsetX = offset / ContentScale;
|
---|
| 162 | }
|
---|
| 163 | finally
|
---|
| 164 | {
|
---|
| 165 | disableScrollOffsetSync = false;
|
---|
| 166 | }
|
---|
| 167 | }
|
---|
| 168 |
|
---|
| 169 | #endregion
|
---|
| 170 |
|
---|
| 171 | #region Public Methods
|
---|
| 172 |
|
---|
| 173 | /// <summary>
|
---|
| 174 | /// Called when the offset of the vertical scrollbar has been set.
|
---|
| 175 | /// </summary>
|
---|
| 176 | public void SetVerticalOffset(double offset)
|
---|
| 177 | {
|
---|
| 178 | if (disableScrollOffsetSync)
|
---|
| 179 | {
|
---|
| 180 | return;
|
---|
| 181 | }
|
---|
| 182 |
|
---|
| 183 | try
|
---|
| 184 | {
|
---|
| 185 | disableScrollOffsetSync = true;
|
---|
| 186 |
|
---|
| 187 | ContentOffsetY = offset / ContentScale;
|
---|
| 188 | }
|
---|
| 189 | finally
|
---|
| 190 | {
|
---|
| 191 | disableScrollOffsetSync = false;
|
---|
| 192 | }
|
---|
| 193 | }
|
---|
| 194 |
|
---|
| 195 | /// <summary>
|
---|
| 196 | /// Shift the content offset one line up.
|
---|
| 197 | /// </summary>
|
---|
| 198 | public void LineUp()
|
---|
| 199 | {
|
---|
| 200 | ContentOffsetY -= (ContentViewportHeight / 10);
|
---|
| 201 | }
|
---|
| 202 |
|
---|
| 203 | /// <summary>
|
---|
| 204 | /// Shift the content offset one line down.
|
---|
| 205 | /// </summary>
|
---|
| 206 | public void LineDown()
|
---|
| 207 | {
|
---|
| 208 | ContentOffsetY += (ContentViewportHeight / 10);
|
---|
| 209 | }
|
---|
| 210 |
|
---|
| 211 | /// <summary>
|
---|
| 212 | /// Shift the content offset one line left.
|
---|
| 213 | /// </summary>
|
---|
| 214 | public void LineLeft()
|
---|
| 215 | {
|
---|
| 216 | ContentOffsetX -= (ContentViewportWidth / 10);
|
---|
| 217 | }
|
---|
| 218 |
|
---|
| 219 | /// <summary>
|
---|
| 220 | /// Shift the content offset one line right.
|
---|
| 221 | /// </summary>
|
---|
| 222 | public void LineRight()
|
---|
| 223 | {
|
---|
| 224 | ContentOffsetX += (ContentViewportWidth / 10);
|
---|
| 225 | }
|
---|
| 226 |
|
---|
| 227 | /// <summary>
|
---|
| 228 | /// Shift the content offset one page up.
|
---|
| 229 | /// </summary>
|
---|
| 230 | public void PageUp()
|
---|
| 231 | {
|
---|
| 232 | ContentOffsetY -= ContentViewportHeight;
|
---|
| 233 | }
|
---|
| 234 |
|
---|
| 235 | /// <summary>
|
---|
| 236 | /// Shift the content offset one page down.
|
---|
| 237 | /// </summary>
|
---|
| 238 | public void PageDown()
|
---|
| 239 | {
|
---|
| 240 | ContentOffsetY += ContentViewportHeight;
|
---|
| 241 | }
|
---|
| 242 |
|
---|
| 243 | /// <summary>
|
---|
| 244 | /// Shift the content offset one page left.
|
---|
| 245 | /// </summary>
|
---|
| 246 | public void PageLeft()
|
---|
| 247 | {
|
---|
| 248 | ContentOffsetX -= ContentViewportWidth;
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 | /// <summary>
|
---|
| 252 | /// Shift the content offset one page right.
|
---|
| 253 | /// </summary>
|
---|
| 254 | public void PageRight()
|
---|
| 255 | {
|
---|
| 256 | ContentOffsetX += ContentViewportWidth;
|
---|
| 257 | }
|
---|
| 258 |
|
---|
| 259 | /// <summary>
|
---|
| 260 | /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is
|
---|
| 261 | /// used for zooming in and out, not for manipulating the scrollbars.
|
---|
| 262 | /// </summary>
|
---|
| 263 | public void MouseWheelDown()
|
---|
| 264 | {
|
---|
| 265 | if (IsMouseWheelScrollingEnabled)
|
---|
| 266 | {
|
---|
| 267 | LineDown();
|
---|
| 268 | }
|
---|
| 269 | }
|
---|
| 270 |
|
---|
| 271 | /// <summary>
|
---|
| 272 | /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is
|
---|
| 273 | /// used for zooming in and out, not for manipulating the scrollbars.
|
---|
| 274 | /// </summary>
|
---|
| 275 | public void MouseWheelLeft()
|
---|
| 276 | {
|
---|
| 277 | if (IsMouseWheelScrollingEnabled)
|
---|
| 278 | {
|
---|
| 279 | LineLeft();
|
---|
| 280 | }
|
---|
| 281 | }
|
---|
| 282 |
|
---|
| 283 | /// <summary>
|
---|
| 284 | /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is
|
---|
| 285 | /// used for zooming in and out, not for manipulating the scrollbars.
|
---|
| 286 | /// </summary>
|
---|
| 287 | public void MouseWheelRight()
|
---|
| 288 | {
|
---|
| 289 | if (IsMouseWheelScrollingEnabled)
|
---|
| 290 | {
|
---|
| 291 | LineRight();
|
---|
| 292 | }
|
---|
| 293 | }
|
---|
| 294 |
|
---|
| 295 | /// <summary>
|
---|
| 296 | /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is
|
---|
| 297 | /// used for zooming in and out, not for manipulating the scrollbars.
|
---|
| 298 | /// </summary>
|
---|
| 299 | public void MouseWheelUp()
|
---|
| 300 | {
|
---|
| 301 | if (IsMouseWheelScrollingEnabled)
|
---|
| 302 | {
|
---|
| 303 | LineUp();
|
---|
| 304 | }
|
---|
| 305 | }
|
---|
| 306 |
|
---|
| 307 | /// <summary>
|
---|
| 308 | /// Bring the specified rectangle to view.
|
---|
| 309 | /// </summary>
|
---|
| 310 | public Rect MakeVisible(Visual visual, Rect rectangle)
|
---|
| 311 | {
|
---|
| 312 | if (content.IsAncestorOf(visual))
|
---|
| 313 | {
|
---|
| 314 | Rect transformedRect = visual.TransformToAncestor(content).TransformBounds(rectangle);
|
---|
| 315 | if (!transformedRect.IntersectsWith(new Rect(ContentOffsetX, ContentOffsetY, ContentViewportWidth, ContentViewportHeight)))
|
---|
| 316 | {
|
---|
| 317 | AnimatedSnapTo(new Point(transformedRect.X + (transformedRect.Width / 2),
|
---|
| 318 | transformedRect.Y + (transformedRect.Height / 2)));
|
---|
| 319 | }
|
---|
| 320 | }
|
---|
| 321 | return rectangle;
|
---|
| 322 | }
|
---|
| 323 |
|
---|
| 324 | #endregion
|
---|
| 325 | }
|
---|
| 326 | }
|
---|