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;
}
}
}