Files
HandyControl/src/Shared/HandyControl_Shared/Controls/Image/ImageBlock.cs
T

179 lines
6.9 KiB
C#

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using HandyControl.Data;
namespace HandyControl.Controls
{
public class ImageBlock : FrameworkElement
{
private readonly DispatcherTimer _dispatcherTimer;
private int _indexMax;
private int _indexMin;
private int _currentIndex;
public ImageBlock()
{
_dispatcherTimer = new DispatcherTimer
{
Interval = Interval
};
_dispatcherTimer.Tick += DispatcherTimer_Tick;
}
private void OnPositionsChanged()
{
_indexMin = StartRow * Columns + StartColumn;
_indexMax = EndRow * Columns + EndColumn;
_currentIndex = _indexMin;
}
private static void OnPositionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ImageBlock)d;
ctl.OnPositionsChanged();
}
private void DispatcherTimer_Tick(object sender, EventArgs e) => InvalidateVisual();
public static readonly DependencyProperty StartColumnProperty = DependencyProperty.Register(
"StartColumn", typeof(int), typeof(ImageBlock), new FrameworkPropertyMetadata(ValueBoxes.Int0Box,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnPositionsChanged));
public int StartColumn
{
get => (int) GetValue(StartColumnProperty);
set => SetValue(StartColumnProperty, value);
}
public static readonly DependencyProperty StartRowProperty = DependencyProperty.Register(
"StartRow", typeof(int), typeof(ImageBlock), new FrameworkPropertyMetadata(ValueBoxes.Int0Box,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnPositionsChanged));
public int StartRow
{
get => (int) GetValue(StartRowProperty);
set => SetValue(StartRowProperty, value);
}
public static readonly DependencyProperty EndColumnProperty = DependencyProperty.Register(
"EndColumn", typeof(int), typeof(ImageBlock), new FrameworkPropertyMetadata(ValueBoxes.Int0Box,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnPositionsChanged));
public int EndColumn
{
get => (int) GetValue(EndColumnProperty);
set => SetValue(EndColumnProperty, value);
}
public static readonly DependencyProperty EndRowProperty = DependencyProperty.Register(
"EndRow", typeof(int), typeof(ImageBlock), new FrameworkPropertyMetadata(ValueBoxes.Int0Box,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnPositionsChanged));
public int EndRow
{
get => (int) GetValue(EndRowProperty);
set => SetValue(EndRowProperty, value);
}
public static readonly DependencyProperty IsPlayingProperty = DependencyProperty.Register(
"IsPlaying", typeof(bool), typeof(ImageBlock), new FrameworkPropertyMetadata(ValueBoxes.FalseBox,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnIsPlayingChanged));
private static void OnIsPlayingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ImageBlock)d;
if ((bool) e.NewValue)
{
ctl._dispatcherTimer.Start();
}
else
{
ctl._dispatcherTimer.Stop();
}
}
public bool IsPlaying
{
get => (bool) GetValue(IsPlayingProperty);
set => SetValue(IsPlayingProperty, value);
}
public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register(
"Columns", typeof(int), typeof(ImageBlock), new FrameworkPropertyMetadata(ValueBoxes.Int1Box,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender), obj => (int)obj >= 1);
public int Columns
{
get => (int) GetValue(ColumnsProperty);
set => SetValue(ColumnsProperty, value);
}
public static readonly DependencyProperty RowsProperty = DependencyProperty.Register(
"Rows", typeof(int), typeof(ImageBlock), new FrameworkPropertyMetadata(ValueBoxes.Int1Box,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender), obj => (int)obj >= 1);
public int Rows
{
get => (int) GetValue(RowsProperty);
set => SetValue(RowsProperty, value);
}
public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register(
"Interval", typeof(TimeSpan), typeof(ImageBlock), new PropertyMetadata(TimeSpan.FromSeconds(1), OnIntervalChanged));
private static void OnIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ImageBlock) d;
ctl._dispatcherTimer.Interval = (TimeSpan) e.NewValue;
}
public TimeSpan Interval
{
get => (TimeSpan) GetValue(IntervalProperty);
set => SetValue(IntervalProperty, value);
}
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source", typeof(ImageSource), typeof(ImageBlock), new FrameworkPropertyMetadata(default(ImageSource),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));
public ImageSource Source
{
get => (ImageSource)GetValue(SourceProperty);
set => SetValue(SourceProperty, value);
}
protected override void OnRender(DrawingContext dc)
{
if (Source != null && Source is BitmapSource source)
{
// ReSharper disable once AssignNullToNotNullAttribute
var croppedBitmap = new CroppedBitmap(source,
CalDisplayRect(source.PixelWidth / Columns, source.PixelHeight / Rows));
dc.DrawImage(croppedBitmap, new Rect(0, 0, RenderSize.Width, RenderSize.Height));
}
}
private Int32Rect CalDisplayRect(int width, int height)
{
if (_currentIndex > _indexMax)
{
_currentIndex = _indexMin;
}
var x = _currentIndex % Columns * width;
// ReSharper disable once PossibleLossOfFraction
var y = _currentIndex / Columns * height;
var rect = new Int32Rect(x, y, width, height);
_currentIndex++;
return rect;
}
}
}