179 lines
6.9 KiB
C#
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;
|
|
}
|
|
}
|
|
} |