Files
WPFToolkit/Src/Xceed.Wpf.Toolkit/Zoombox/ZoomboxViewFinderDisplay.cs
2024-02-23 07:03:56 -05:00

285 lines
9.4 KiB
C#

/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Windows;
using System.Windows.Media;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit.Zoombox
{
public class ZoomboxViewFinderDisplay : FrameworkElement
{
#region Constructors
static ZoomboxViewFinderDisplay()
{
ZoomboxViewFinderDisplay.DefaultStyleKeyProperty.OverrideMetadata( typeof( ZoomboxViewFinderDisplay ), new FrameworkPropertyMetadata( typeof( ZoomboxViewFinderDisplay ) ) );
}
public ZoomboxViewFinderDisplay()
{
}
#endregion
#region Background Property
public static readonly DependencyProperty BackgroundProperty =
DependencyProperty.Register( "Background", typeof( Brush ), typeof( ZoomboxViewFinderDisplay ),
new FrameworkPropertyMetadata( new SolidColorBrush( Color.FromArgb( 0xC0, 0xFF, 0xFF, 0xFF ) ), FrameworkPropertyMetadataOptions.AffectsRender ) );
public Brush Background
{
get
{
return ( Brush )this.GetValue( ZoomboxViewFinderDisplay.BackgroundProperty );
}
set
{
this.SetValue( ZoomboxViewFinderDisplay.BackgroundProperty, value );
}
}
#endregion
#region ContentBounds Property
private static readonly DependencyPropertyKey ContentBoundsPropertyKey =
DependencyProperty.RegisterReadOnly( "ContentBounds", typeof( Rect ), typeof( ZoomboxViewFinderDisplay ),
new FrameworkPropertyMetadata( ( Rect )Rect.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender ) );
public static readonly DependencyProperty ContentBoundsProperty = ZoomboxViewFinderDisplay.ContentBoundsPropertyKey.DependencyProperty;
internal Rect ContentBounds
{
get
{
return ( Rect )this.GetValue( ZoomboxViewFinderDisplay.ContentBoundsProperty );
}
set
{
this.SetValue( ZoomboxViewFinderDisplay.ContentBoundsPropertyKey, value );
}
}
#endregion
#region ShadowBrush Property
public static readonly DependencyProperty ShadowBrushProperty =
DependencyProperty.Register( "ShadowBrush", typeof( Brush ), typeof( ZoomboxViewFinderDisplay ),
new FrameworkPropertyMetadata( new SolidColorBrush( Color.FromArgb( 0x80, 0xFF, 0xFF, 0xFF ) ), FrameworkPropertyMetadataOptions.AffectsRender ) );
public Brush ShadowBrush
{
get
{
return ( Brush )this.GetValue( ZoomboxViewFinderDisplay.ShadowBrushProperty );
}
set
{
this.SetValue( ZoomboxViewFinderDisplay.ShadowBrushProperty, value );
}
}
#endregion
#region ViewportBrush Property
public static readonly DependencyProperty ViewportBrushProperty =
DependencyProperty.Register( "ViewportBrush", typeof( Brush ), typeof( ZoomboxViewFinderDisplay ),
new FrameworkPropertyMetadata( Brushes.Transparent, FrameworkPropertyMetadataOptions.AffectsRender ) );
public Brush ViewportBrush
{
get
{
return ( Brush )this.GetValue( ZoomboxViewFinderDisplay.ViewportBrushProperty );
}
set
{
this.SetValue( ZoomboxViewFinderDisplay.ViewportBrushProperty, value );
}
}
#endregion
#region ViewportPen Property
public static readonly DependencyProperty ViewportPenProperty =
DependencyProperty.Register( "ViewportPen", typeof( Pen ), typeof( ZoomboxViewFinderDisplay ),
new FrameworkPropertyMetadata( new Pen( new SolidColorBrush( Color.FromArgb( 0x80, 0x00, 0x00, 0x00 ) ), 1d ), FrameworkPropertyMetadataOptions.AffectsRender ) );
public Pen ViewportPen
{
get
{
return ( Pen )this.GetValue( ZoomboxViewFinderDisplay.ViewportPenProperty );
}
set
{
this.SetValue( ZoomboxViewFinderDisplay.ViewportPenProperty, value );
}
}
#endregion
#region ViewportRect Property
public static readonly DependencyProperty ViewportRectProperty =
DependencyProperty.Register( "ViewportRect", typeof( Rect ), typeof( ZoomboxViewFinderDisplay ),
new FrameworkPropertyMetadata( Rect.Empty, FrameworkPropertyMetadataOptions.AffectsRender ) );
public Rect ViewportRect
{
get
{
return ( Rect )this.GetValue( ZoomboxViewFinderDisplay.ViewportRectProperty );
}
set
{
this.SetValue( ZoomboxViewFinderDisplay.ViewportRectProperty, value );
}
}
#endregion
#region VisualBrush Property
private static readonly DependencyPropertyKey VisualBrushPropertyKey =
DependencyProperty.RegisterReadOnly( "VisualBrush", typeof( VisualBrush ), typeof( ZoomboxViewFinderDisplay ),
new FrameworkPropertyMetadata( ( VisualBrush )null ) );
public static readonly DependencyProperty VisualBrushProperty = ZoomboxViewFinderDisplay.VisualBrushPropertyKey.DependencyProperty;
internal VisualBrush VisualBrush
{
get
{
return ( VisualBrush )this.GetValue( ZoomboxViewFinderDisplay.VisualBrushProperty );
}
set
{
this.SetValue( ZoomboxViewFinderDisplay.VisualBrushPropertyKey, value );
}
}
#endregion
#region AvailableSize Internal Property
internal Size AvailableSize
{
get
{
return _availableSize;
}
}
private Size _availableSize = Size.Empty;
#endregion
#region Scale Internal Property
internal double Scale
{
get
{
return _scale;
}
set
{
_scale = value;
}
}
private double _scale = 1d;
#endregion
protected override Size ArrangeOverride( Size finalSize )
{
// Note that we do not call the Arrange method on any children
// because a ViewFinderDisplay has no children
// the control's RenderSize should always match its DesiredSize
return this.DesiredSize;
}
protected override Size MeasureOverride( Size availableSize )
{
// Note that we do not call the Measure method on any children
// because a ViewFinderDisplay has no children. It is merely used
// as a surface for the view finder's VisualBrush.
// store the available size for use by the Zoombox control
_availableSize = availableSize;
// Simulate size-to-content for the display panel by ensuring a width and height
// based on the content bounds. Otherwise, the display panel may have no size, since it doesn't
// contain content.
double width = DoubleHelper.IsNaN( this.ContentBounds.Width ) ? 0 : Math.Max( 0, this.ContentBounds.Width );
double height = DoubleHelper.IsNaN( this.ContentBounds.Height ) ? 0 : Math.Max( 0, this.ContentBounds.Height );
Size displayPanelSize = new Size( width, height );
// Now ensure that the result fits within the available size while maintaining
// the width/height ratio of the content bounds
if( displayPanelSize.Width > availableSize.Width || displayPanelSize.Height > availableSize.Height )
{
double aspectX = availableSize.Width / displayPanelSize.Width;
double aspectY = availableSize.Height / displayPanelSize.Height;
double scale = ( aspectX < aspectY ) ? aspectX : aspectY;
displayPanelSize = new Size( displayPanelSize.Width * scale, displayPanelSize.Height * scale );
}
return displayPanelSize;
}
protected override void OnRender( DrawingContext dc )
{
base.OnRender( dc );
dc.DrawRectangle( this.Background, null, this.ContentBounds );
dc.DrawRectangle( this.VisualBrush, null, this.ContentBounds );
if( this.ViewportRect.IntersectsWith( new Rect( this.RenderSize ) ) )
{
// draw shadow rectangles over the non-viewport regions
Rect r1 = new Rect( new Point( 0, 0 ), new Size( this.RenderSize.Width, Math.Max( 0, this.ViewportRect.Top ) ) );
Rect r2 = new Rect( new Point( 0, this.ViewportRect.Top ), new Size( Math.Max( 0, this.ViewportRect.Left ), this.ViewportRect.Height ) );
Rect r3 = new Rect( new Point( this.ViewportRect.Right, this.ViewportRect.Top ), new Size( Math.Max( 0, this.RenderSize.Width - this.ViewportRect.Right ), this.ViewportRect.Height ) );
Rect r4 = new Rect( new Point( 0, this.ViewportRect.Bottom ), new Size( this.RenderSize.Width, Math.Max( 0, this.RenderSize.Height - this.ViewportRect.Bottom ) ) );
dc.DrawRectangle( this.ShadowBrush, null, r1 );
dc.DrawRectangle( this.ShadowBrush, null, r2 );
dc.DrawRectangle( this.ShadowBrush, null, r3 );
dc.DrawRectangle( this.ShadowBrush, null, r4 );
// draw the rectangle around the viewport region
dc.DrawRectangle( this.ViewportBrush, this.ViewportPen, this.ViewportRect );
}
else
{
// if no part of the Rect is visible, just draw a
// shadow over the entire content bounds
dc.DrawRectangle( this.ShadowBrush, null, new Rect( this.RenderSize ) );
}
}
}
}