using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace Bro.Common.ImageCanvas { /// /// This is an extension to the ZoomAndPanControol class that implements /// the IScrollInfo interface properties and functions. /// /// IScrollInfo is implemented to allow ZoomAndPanControl to be wrapped (in XAML) /// in a ScrollViewer. IScrollInfo allows the ScrollViewer and ZoomAndPanControl to /// communicate important information such as the horizontal and vertical scrollbar offsets. /// /// There is a good series of articles showing how to implement IScrollInfo starting here: /// http://blogs.msdn.com/bencon/archive/2006/01/05/509991.aspx /// /// public partial class ZoomAndPanControl { /// /// Set to 'true' when the vertical scrollbar is enabled. /// public bool CanVerticallyScroll { get; set; } = false; /// /// Set to 'true' when the vertical scrollbar is enabled. /// public bool CanHorizontallyScroll { get; set; } = false; /// /// The width of the content (with 'ViewportZoom' applied). /// public double ExtentWidth => _unScaledExtent.Width * InternalViewportZoom; /// /// The height of the content (with 'ViewportZoom' applied). /// public double ExtentHeight => _unScaledExtent.Height * InternalViewportZoom; /// /// Get the width of the viewport onto the content. /// public double ViewportWidth => _viewport.Width; /// /// Get the height of the viewport onto the content. /// public double ViewportHeight => _viewport.Height; /// /// Reference to the ScrollViewer that is wrapped (in XAML) around the ZoomAndPanControl. /// Or set to null if there is no ScrollViewer. /// public ScrollViewer ScrollOwner { get; set; } = null; /// /// The offset of the horizontal scrollbar. /// public double HorizontalOffset => ContentOffsetX * InternalViewportZoom; /// /// The offset of the vertical scrollbar. /// public double VerticalOffset => ContentOffsetY * InternalViewportZoom; /// /// Called when the offset of the horizontal scrollbar has been set. /// public void SetHorizontalOffset(double offset) { if (_disableScrollOffsetSync) return; try { _disableScrollOffsetSync = true; ContentOffsetX = offset / InternalViewportZoom; DelayedSaveZoom750Miliseconds(); } finally { _disableScrollOffsetSync = false; } } /// /// Called when the offset of the vertical scrollbar has been set. /// public void SetVerticalOffset(double offset) { if (_disableScrollOffsetSync) return; try { _disableScrollOffsetSync = true; ContentOffsetY = offset / InternalViewportZoom; DelayedSaveZoom750Miliseconds(); } finally { _disableScrollOffsetSync = false; } } /// /// Shift the content offset one line up. /// public void LineUp() { DelayedSaveZoom750Miliseconds(); ContentOffsetY -= (ContentViewportHeight / 10); } /// /// Shift the content offset one line down. /// public void LineDown() { DelayedSaveZoom750Miliseconds(); ContentOffsetY += (ContentViewportHeight / 10); } /// /// Shift the content offset one line left. /// public void LineLeft() { DelayedSaveZoom750Miliseconds(); ContentOffsetX -= (ContentViewportWidth / 10); } /// /// Shift the content offset one line right. /// public void LineRight() { DelayedSaveZoom750Miliseconds(); ContentOffsetX += (ContentViewportWidth / 10); } /// /// Shift the content offset one page up. /// public void PageUp() { DelayedSaveZoom1500Miliseconds(); ContentOffsetY -= ContentViewportHeight; } /// /// Shift the content offset one page down. /// public void PageDown() { DelayedSaveZoom1500Miliseconds(); ContentOffsetY += ContentViewportHeight; } /// /// Shift the content offset one page left. /// public void PageLeft() { DelayedSaveZoom1500Miliseconds(); ContentOffsetX -= ContentViewportWidth; } /// /// Shift the content offset one page right. /// public void PageRight() { DelayedSaveZoom1500Miliseconds(); ContentOffsetX += ContentViewportWidth; } /// /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is /// used for zooming in and out, not for manipulating the scrollbars. /// public void MouseWheelDown() { if (IsMouseWheelScrollingEnabled) { LineDown(); } } /// /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is /// used for zooming in and out, not for manipulating the scrollbars. /// public void MouseWheelLeft() { if (IsMouseWheelScrollingEnabled) { LineLeft(); } } /// /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is /// used for zooming in and out, not for manipulating the scrollbars. /// public void MouseWheelRight() { if (IsMouseWheelScrollingEnabled) { LineRight(); } } /// /// Don't handle mouse wheel input from the ScrollViewer, the mouse wheel is /// used for zooming in and out, not for manipulating the scrollbars. /// public void MouseWheelUp() { if (IsMouseWheelScrollingEnabled) { LineUp(); } } /// /// Bring the specified rectangle to view. /// public Rect MakeVisible(Visual visual, Rect rectangle) { if (_content.IsAncestorOf(visual)) { var transformedRect = visual.TransformToAncestor(_content).TransformBounds(rectangle); var viewportRect = new Rect(ContentOffsetX, ContentOffsetY, ContentViewportWidth, ContentViewportHeight); if (!transformedRect.Contains(viewportRect)) { double horizOffset = 0; double vertOffset = 0; if (transformedRect.Left < viewportRect.Left) { // // Want to move viewport left. // horizOffset = transformedRect.Left - viewportRect.Left; } else if (transformedRect.Right > viewportRect.Right) { // // Want to move viewport right. // horizOffset = transformedRect.Right - viewportRect.Right; } if (transformedRect.Top < viewportRect.Top) { // // Want to move viewport up. // vertOffset = transformedRect.Top - viewportRect.Top; } else if (transformedRect.Bottom > viewportRect.Bottom) { // // Want to move viewport down. // vertOffset = transformedRect.Bottom - viewportRect.Bottom; } SnapContentOffsetTo(new Point(ContentOffsetX + horizOffset, ContentOffsetY + vertOffset)); } } return rectangle; } } }