Fix 1
This commit is contained in:
@@ -0,0 +1,127 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:controls="using:Toolkit.UI.Controls.Avalonia">
|
||||||
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
|
<ResourceDictionary x:Key="Light">
|
||||||
|
<StaticResource x:Key="ContentCropperThumbBackground" ResourceKey="AccentFillColorDefaultBrush" />
|
||||||
|
<StaticResource x:Key="ContentCropperThumbBrush" ResourceKey="ControlElevationBorderBrush" />
|
||||||
|
<StaticResource x:Key="ContentCropperOuterThumbBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
<ResourceDictionary x:Key="Dark">
|
||||||
|
<StaticResource x:Key="ContentCropperThumbBackground" ResourceKey="AccentFillColorDefaultBrush" />
|
||||||
|
<StaticResource x:Key="ContentCropperThumbBrush" ResourceKey="ControlElevationBorderBrush" />
|
||||||
|
<StaticResource x:Key="ContentCropperOuterThumbBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
|
<CornerRadius x:Key="ContentCropperThumbCornerRadius">10</CornerRadius>
|
||||||
|
<x:Double x:Key="ContentCropperInnerThumbWidth">12</x:Double>
|
||||||
|
<x:Double x:Key="ContentCropperInnerThumbHeight">12</x:Double>
|
||||||
|
<x:Double x:Key="ContentCropperThumbWidth">18</x:Double>
|
||||||
|
<x:Double x:Key="ContentCropperThumbHeight">18</x:Double>
|
||||||
|
<ControlTheme x:Key="ContentCropperThumbStyle" TargetType="Thumb">
|
||||||
|
<Setter Property="BorderThickness" Value="1" />
|
||||||
|
<Setter Property="Background" Value="{DynamicResource ContentCropperThumbBackground}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{DynamicResource ContentCropperThumbBrush}" />
|
||||||
|
<Setter Property="ClipToBounds" Value="False" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate>
|
||||||
|
<Border
|
||||||
|
Margin="-2"
|
||||||
|
Background="{DynamicResource ContentCropperOuterThumbBackground}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
CornerRadius="{DynamicResource ContentCropperOuterThumbCornerRadius}">
|
||||||
|
<Ellipse
|
||||||
|
Name="InnerThumb"
|
||||||
|
Width="{DynamicResource ContentCropperInnerThumbWidth}"
|
||||||
|
Height="{DynamicResource ContentCropperInnerThumbHeight}"
|
||||||
|
Fill="{TemplateBinding Background}"
|
||||||
|
RenderTransform="scaleX(0.86) scaleY(0.86)">
|
||||||
|
<Ellipse.Transitions>
|
||||||
|
<Transitions>
|
||||||
|
<TransformOperationsTransition
|
||||||
|
Easing="0,0 0,1"
|
||||||
|
Property="RenderTransform"
|
||||||
|
Duration="00:00:00.167" />
|
||||||
|
</Transitions>
|
||||||
|
</Ellipse.Transitions>
|
||||||
|
</Ellipse>
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Style Selector="^:pointerover /template/ Ellipse#InnerThumb">
|
||||||
|
<Setter Property="RenderTransform" Value="scaleX(1.167) scaleY(1.167)" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^:pressed /template/ Ellipse#InnerThumb">
|
||||||
|
<Setter Property="RenderTransform" Value="scaleX(0.71) scaleY(0.71)" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^:disabled /template/ Ellipse#InnerThumb">
|
||||||
|
<Setter Property="RenderTransform" Value="scaleX(1.167) scaleY(1.167)" />
|
||||||
|
</Style>
|
||||||
|
</ControlTheme>
|
||||||
|
<ControlTheme x:Key="{x:Type ContentCropper}" TargetType="ContentCropper">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<ControlTemplate>
|
||||||
|
<Grid>
|
||||||
|
<ZoomBorder
|
||||||
|
x:Name="ZoomBorder"
|
||||||
|
ClipToBounds="True"
|
||||||
|
PanButton="Left">
|
||||||
|
<ContentPresenter
|
||||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||||
|
Content="{TemplateBinding Content}"
|
||||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||||
|
</ZoomBorder>
|
||||||
|
<Canvas x:Name="Canvas">
|
||||||
|
<Rectangle
|
||||||
|
x:Name="RectangleLeft"
|
||||||
|
Fill="{DynamicResource SmokeFillColorDefaultBrush}"
|
||||||
|
UseLayoutRounding="True" />
|
||||||
|
<Rectangle
|
||||||
|
x:Name="RectangleTop"
|
||||||
|
Fill="{DynamicResource SmokeFillColorDefaultBrush}"
|
||||||
|
UseLayoutRounding="True" />
|
||||||
|
<Rectangle
|
||||||
|
x:Name="RectangleRight"
|
||||||
|
Fill="{DynamicResource SmokeFillColorDefaultBrush}"
|
||||||
|
UseLayoutRounding="True" />
|
||||||
|
<Rectangle
|
||||||
|
x:Name="RectangleBottom"
|
||||||
|
Fill="{DynamicResource SmokeFillColorDefaultBrush}"
|
||||||
|
UseLayoutRounding="True" />
|
||||||
|
<Border
|
||||||
|
x:Name="Border"
|
||||||
|
Background="Transparent"
|
||||||
|
BorderBrush="Transparent"
|
||||||
|
BorderThickness="2"
|
||||||
|
Cursor="SizeAll" />
|
||||||
|
<Thumb
|
||||||
|
x:Name="TopLeftButton"
|
||||||
|
Width="{DynamicResource ContentCropperThumbWidth}"
|
||||||
|
Height="{DynamicResource ContentCropperThumbHeight}"
|
||||||
|
Theme="{StaticResource ContentCropperThumbStyle}" />
|
||||||
|
<Thumb
|
||||||
|
x:Name="TopRightButton"
|
||||||
|
Width="{DynamicResource ContentCropperThumbWidth}"
|
||||||
|
Height="{DynamicResource ContentCropperThumbHeight}"
|
||||||
|
Theme="{StaticResource ContentCropperThumbStyle}" />
|
||||||
|
<Thumb
|
||||||
|
x:Name="BottomLeftButton"
|
||||||
|
Width="{DynamicResource ContentCropperThumbWidth}"
|
||||||
|
Height="{DynamicResource ContentCropperThumbHeight}"
|
||||||
|
Theme="{StaticResource ContentCropperThumbStyle}" />
|
||||||
|
<Thumb
|
||||||
|
x:Name="BottomRightButton"
|
||||||
|
Width="{DynamicResource ContentCropperThumbWidth}"
|
||||||
|
Height="{DynamicResource ContentCropperThumbHeight}"
|
||||||
|
Theme="{StaticResource ContentCropperThumbStyle}" />
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter>
|
||||||
|
</ControlTheme>
|
||||||
|
</ResourceDictionary>
|
||||||
+99
-121
@@ -1,39 +1,34 @@
|
|||||||
using Avalonia;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
|
||||||
using Avalonia.Controls.Shapes;
|
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Media;
|
using Avalonia;
|
||||||
using Avalonia.Media.Imaging;
|
using Avalonia.Controls.Shapes;
|
||||||
|
|
||||||
namespace Toolkit.UI.Controls.Avalonia;
|
namespace Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
public class ImageCropper :
|
public class ContentCropper : ContentControl
|
||||||
TemplatedControl
|
|
||||||
{
|
{
|
||||||
public static readonly StyledProperty<IImage?> CurrentAreaBitmapProperty =
|
public static readonly StyledProperty<Rect> CropRectangleProperty =
|
||||||
AvaloniaProperty.Register<ImageCropper, IImage?>(nameof(CurrentAreaBitmap));
|
AvaloniaProperty.Register<ContentCropper, Rect>(nameof(CropRectangle));
|
||||||
|
|
||||||
public static readonly StyledProperty<Rect> CurrentRectProperty =
|
|
||||||
AvaloniaProperty.Register<ImageCropper, Rect>(nameof(CurrentRect));
|
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> IsRatioScaleProperty =
|
public static readonly StyledProperty<bool> IsRatioScaleProperty =
|
||||||
AvaloniaProperty.Register<ImageCropper, bool>(nameof(IsRatioScale));
|
AvaloniaProperty.Register<ContentCropper, bool>(nameof(IsRatioScale));
|
||||||
|
|
||||||
public static readonly StyledProperty<double> RectScaleProperty =
|
public static readonly StyledProperty<double> RectScaleProperty =
|
||||||
AvaloniaProperty.Register<ImageCropper, double>(nameof(RectScale), 0.5);
|
AvaloniaProperty.Register<ContentCropper, double>(nameof(RectScale), 0.5);
|
||||||
|
|
||||||
public static readonly StyledProperty<Size> ScaleSizeProperty =
|
public static readonly StyledProperty<Size> ScaleSizeProperty =
|
||||||
AvaloniaProperty.Register<ImageCropper, Size>(nameof(ScaleSize), new Size(2, 1));
|
AvaloniaProperty.Register<ContentCropper, Size>(nameof(ScaleSize), new Size(2, 1));
|
||||||
|
|
||||||
public static readonly StyledProperty<IImage?> SourceProperty =
|
|
||||||
AvaloniaProperty.Register<ImageCropper, IImage?>(nameof(Source));
|
|
||||||
|
|
||||||
private Border? border;
|
private Border? border;
|
||||||
private Thumb? bottomLeftButton;
|
private Thumb? bottomLeftButton;
|
||||||
private Thumb? bottomRightButton;
|
private Thumb? bottomRightButton;
|
||||||
private Canvas? canvas;
|
private Canvas? canvas;
|
||||||
|
private double cropHeightRatio;
|
||||||
|
private double cropLeftRatio;
|
||||||
|
private double cropTopRatio;
|
||||||
|
private double cropWidthRatio;
|
||||||
private bool isDragging;
|
private bool isDragging;
|
||||||
private double offsetX;
|
private double offsetX;
|
||||||
private double offsetY;
|
private double offsetY;
|
||||||
@@ -41,25 +36,18 @@ public class ImageCropper :
|
|||||||
private Rectangle? rectangleLeft;
|
private Rectangle? rectangleLeft;
|
||||||
private Rectangle? rectangleRight;
|
private Rectangle? rectangleRight;
|
||||||
private Rectangle? rectangleTop;
|
private Rectangle? rectangleTop;
|
||||||
|
|
||||||
private Thumb? topLeftButton;
|
private Thumb? topLeftButton;
|
||||||
private Thumb? topRightButton;
|
private Thumb? topRightButton;
|
||||||
|
|
||||||
static ImageCropper()
|
static ContentCropper()
|
||||||
{
|
{
|
||||||
AffectsRender<ImageCropper>(SourceProperty, RectScaleProperty);
|
AffectsRender<ContentCropper>(RectScaleProperty, ContentProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IImage? CurrentAreaBitmap
|
public Rect CropRectangle
|
||||||
{
|
{
|
||||||
get => GetValue(CurrentAreaBitmapProperty);
|
get => GetValue(CropRectangleProperty);
|
||||||
private set => SetValue(CurrentAreaBitmapProperty, value);
|
private set => SetValue(CropRectangleProperty, value);
|
||||||
}
|
|
||||||
|
|
||||||
public Rect CurrentRect
|
|
||||||
{
|
|
||||||
get => GetValue(CurrentRectProperty);
|
|
||||||
private set => SetValue(CurrentRectProperty, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsRatioScale
|
public bool IsRatioScale
|
||||||
@@ -80,12 +68,6 @@ public class ImageCropper :
|
|||||||
set => SetValue(ScaleSizeProperty, value);
|
set => SetValue(ScaleSizeProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IImage? Source
|
|
||||||
{
|
|
||||||
get => GetValue(SourceProperty);
|
|
||||||
set => SetValue(SourceProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs args)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs args)
|
||||||
{
|
{
|
||||||
base.OnApplyTemplate(args);
|
base.OnApplyTemplate(args);
|
||||||
@@ -120,59 +102,85 @@ public class ImageCropper :
|
|||||||
{
|
{
|
||||||
bottomRightButton.DragDelta += OnThumbDragDelta;
|
bottomRightButton.DragDelta += OnThumbDragDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawImage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnLoaded(RoutedEventArgs args)
|
protected override void OnLoaded(RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
base.OnLoaded(args);
|
base.OnLoaded(args);
|
||||||
DrawImage();
|
InitializeCropRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||||
{
|
{
|
||||||
base.OnPropertyChanged(change);
|
base.OnPropertyChanged(change);
|
||||||
|
|
||||||
if (change.Property == SourceProperty ||
|
if (change.Property == IsRatioScaleProperty ||
|
||||||
change.Property == IsRatioScaleProperty ||
|
change.Property == RectScaleProperty ||
|
||||||
change.Property == RectScaleProperty)
|
change.Property == ContentProperty)
|
||||||
{
|
{
|
||||||
DrawImage();
|
InitializeCropRect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawImage()
|
protected override void OnSizeChanged(SizeChangedEventArgs args)
|
||||||
{
|
{
|
||||||
if (canvas is null || Source is not Bitmap bitmap)
|
base.OnSizeChanged(args);
|
||||||
|
|
||||||
|
if (canvas is null || border is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double maxWidth = DesiredSize.Width;
|
double newContentWidth = Bounds.Width;
|
||||||
double maxHeight = DesiredSize.Height;
|
double newContentHeight = Bounds.Height;
|
||||||
|
|
||||||
double imageWidth = Source.Size.Width;
|
canvas.Width = newContentWidth;
|
||||||
double imageHeight = Source.Size.Height;
|
canvas.Height = newContentHeight;
|
||||||
|
|
||||||
double scaleFactor = Math.Min(maxWidth / imageWidth, maxHeight / imageHeight);
|
// Calculate new positions and sizes based on updated ratios
|
||||||
double width = imageWidth * scaleFactor;
|
double newCropLeft = cropLeftRatio * newContentWidth;
|
||||||
double height = imageHeight * scaleFactor;
|
double newCropTop = cropTopRatio * newContentHeight;
|
||||||
|
double newCropWidth = cropWidthRatio * newContentWidth;
|
||||||
|
double newCropHeight = cropHeightRatio * newContentHeight;
|
||||||
|
|
||||||
|
// Check if the crop rectangle was resized or moved, and update accordingly
|
||||||
|
if (border.Width != newCropWidth || border.Height != newCropHeight)
|
||||||
|
{
|
||||||
|
border.Width = newCropWidth;
|
||||||
|
border.Height = newCropHeight;
|
||||||
|
Canvas.SetLeft(border, newCropLeft);
|
||||||
|
Canvas.SetTop(border, newCropTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
PositionThumbs();
|
||||||
|
RenderOverLays();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeCropRect()
|
||||||
|
{
|
||||||
|
if (canvas is null || Content is not Control content)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double maxWidth = Bounds.Width;
|
||||||
|
double maxHeight = Bounds.Height;
|
||||||
|
|
||||||
|
double contentWidth = content.Bounds.Width > 0 ? content.Bounds.Width : maxWidth * 0.5;
|
||||||
|
double contentHeight = content.Bounds.Height > 0 ? content.Bounds.Height : maxHeight * 0.5;
|
||||||
|
|
||||||
|
double scaleFactor = Math.Min(maxWidth / contentWidth, maxHeight / contentHeight);
|
||||||
|
double width = contentWidth * scaleFactor;
|
||||||
|
double height = contentHeight * scaleFactor;
|
||||||
|
|
||||||
canvas.Width = width;
|
canvas.Width = width;
|
||||||
canvas.Height = height;
|
canvas.Height = height;
|
||||||
|
|
||||||
canvas.Background = new ImageBrush
|
UpdateCropArea(width, height);
|
||||||
{
|
RenderOverLays();
|
||||||
Source = bitmap
|
|
||||||
};
|
|
||||||
|
|
||||||
UpdatePunchThrough(width, height);
|
|
||||||
Render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBorderPointerMoved(object? sender,
|
private void OnBorderPointerMoved(object? sender, PointerEventArgs args)
|
||||||
PointerEventArgs args)
|
|
||||||
{
|
{
|
||||||
if (!isDragging || canvas is null || border is null)
|
if (!isDragging || canvas is null || border is null)
|
||||||
{
|
{
|
||||||
@@ -187,11 +195,10 @@ public class ImageCropper :
|
|||||||
Canvas.SetTop(border, newY);
|
Canvas.SetTop(border, newY);
|
||||||
|
|
||||||
PositionThumbs();
|
PositionThumbs();
|
||||||
Render();
|
RenderOverLays();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBorderPointerPressed(object? sender,
|
private void OnBorderPointerPressed(object? sender, PointerPressedEventArgs args)
|
||||||
PointerPressedEventArgs args)
|
|
||||||
{
|
{
|
||||||
if (!isDragging && border is not null)
|
if (!isDragging && border is not null)
|
||||||
{
|
{
|
||||||
@@ -203,8 +210,11 @@ public class ImageCropper :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBorderPointerReleased(object? sender,
|
private void OnBorderPointerReleased(object? sender, PointerReleasedEventArgs args)
|
||||||
PointerReleasedEventArgs args) => isDragging = false;
|
{
|
||||||
|
isDragging = false;
|
||||||
|
UpdateCropRatios();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnThumbDragDelta(object? sender, VectorEventArgs args)
|
private void OnThumbDragDelta(object? sender, VectorEventArgs args)
|
||||||
{
|
{
|
||||||
@@ -226,33 +236,20 @@ public class ImageCropper :
|
|||||||
case "TopLeftButton":
|
case "TopLeftButton":
|
||||||
newWidth = Math.Max(0, border.Width - deltaX);
|
newWidth = Math.Max(0, border.Width - deltaX);
|
||||||
newHeight = Math.Max(0, border.Height - deltaY);
|
newHeight = Math.Max(0, border.Height - deltaY);
|
||||||
if (newWidth > 0)
|
if (newWidth > 0) leftPosition += deltaX;
|
||||||
{
|
if (newHeight > 0) topPosition += deltaY;
|
||||||
leftPosition += deltaX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newHeight > 0)
|
|
||||||
{
|
|
||||||
topPosition += deltaY;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "TopRightButton":
|
case "TopRightButton":
|
||||||
newWidth = Math.Max(0, border.Width + deltaX);
|
newWidth = Math.Max(0, border.Width + deltaX);
|
||||||
newHeight = Math.Max(0, border.Height - deltaY);
|
newHeight = Math.Max(0, border.Height - deltaY);
|
||||||
if (newHeight > 0)
|
if (newHeight > 0) topPosition += deltaY;
|
||||||
{
|
|
||||||
topPosition += deltaY;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "BottomLeftButton":
|
case "BottomLeftButton":
|
||||||
newWidth = Math.Max(0, border.Width - deltaX);
|
newWidth = Math.Max(0, border.Width - deltaX);
|
||||||
newHeight = Math.Max(0, border.Height + deltaY);
|
newHeight = Math.Max(0, border.Height + deltaY);
|
||||||
if (newWidth > 0)
|
if (newWidth > 0) leftPosition += deltaX;
|
||||||
{
|
|
||||||
leftPosition += deltaX;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "BottomRightButton":
|
case "BottomRightButton":
|
||||||
@@ -261,45 +258,16 @@ public class ImageCropper :
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newWidth < 0 || newHeight < 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thumb.Name == "TopLeftButton" || thumb.Name == "BottomLeftButton")
|
|
||||||
{
|
|
||||||
leftPosition = Math.Max(0, leftPosition);
|
|
||||||
if (newWidth > 0)
|
|
||||||
{
|
|
||||||
newWidth = Math.Max(0, border.Width - (leftPosition - Canvas.GetLeft(border)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (thumb.Name == "TopRightButton" || thumb.Name == "BottomRightButton")
|
|
||||||
{
|
|
||||||
newWidth = Math.Min(newWidth, canvas.Width - leftPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thumb.Name == "TopLeftButton" || thumb.Name == "TopRightButton")
|
|
||||||
{
|
|
||||||
topPosition = Math.Max(0, topPosition);
|
|
||||||
if (newHeight > 0)
|
|
||||||
{
|
|
||||||
newHeight = Math.Max(0, border.Height - (topPosition - Canvas.GetTop(border)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (thumb.Name == "BottomLeftButton" || thumb.Name == "BottomRightButton")
|
|
||||||
{
|
|
||||||
newHeight = Math.Min(newHeight, canvas.Height - topPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
border.Width = newWidth;
|
border.Width = newWidth;
|
||||||
border.Height = newHeight;
|
border.Height = newHeight;
|
||||||
|
|
||||||
Canvas.SetLeft(border, leftPosition);
|
Canvas.SetLeft(border, leftPosition);
|
||||||
Canvas.SetTop(border, topPosition);
|
Canvas.SetTop(border, topPosition);
|
||||||
|
|
||||||
|
UpdateCropRatios();
|
||||||
|
|
||||||
PositionThumbs();
|
PositionThumbs();
|
||||||
Render();
|
RenderOverLays();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PositionThumbs()
|
private void PositionThumbs()
|
||||||
@@ -340,7 +308,7 @@ public class ImageCropper :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Render()
|
private void RenderOverLays()
|
||||||
{
|
{
|
||||||
if (canvas == null ||
|
if (canvas == null ||
|
||||||
border == null ||
|
border == null ||
|
||||||
@@ -376,11 +344,22 @@ public class ImageCropper :
|
|||||||
Canvas.SetTop(rectangleBottom, bottomY);
|
Canvas.SetTop(rectangleBottom, bottomY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePunchThrough(double width,
|
private void UpdateCropRatios()
|
||||||
double height)
|
|
||||||
{
|
{
|
||||||
if (canvas == null ||
|
if (canvas == null || border == null)
|
||||||
border == null)
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cropLeftRatio = Canvas.GetLeft(border) / canvas.Width;
|
||||||
|
cropTopRatio = Canvas.GetTop(border) / canvas.Height;
|
||||||
|
cropWidthRatio = border.Width / canvas.Width;
|
||||||
|
cropHeightRatio = border.Height / canvas.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCropArea(double width, double height)
|
||||||
|
{
|
||||||
|
if (canvas == null || border == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -420,4 +399,3 @@ public class ImageCropper :
|
|||||||
border.PointerReleased += OnBorderPointerReleased;
|
border.PointerReleased += OnBorderPointerReleased;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
<ResourceDictionary
|
|
||||||
xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:controls="using:Toolkit.UI.Controls.Avalonia">
|
|
||||||
<ResourceDictionary.ThemeDictionaries>
|
|
||||||
<ResourceDictionary x:Key="Light">
|
|
||||||
<StaticResource x:Key="ImageCropperThumbBackground" ResourceKey="AccentFillColorDefaultBrush" />
|
|
||||||
<StaticResource x:Key="ImageCropperThumbBrush" ResourceKey="ControlElevationBorderBrush" />
|
|
||||||
<StaticResource x:Key="ImageCropperOuterThumbBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
|
|
||||||
</ResourceDictionary>
|
|
||||||
<ResourceDictionary x:Key="Dark">
|
|
||||||
<StaticResource x:Key="ImageCropperThumbBackground" ResourceKey="AccentFillColorDefaultBrush" />
|
|
||||||
<StaticResource x:Key="ImageCropperThumbBrush" ResourceKey="ControlElevationBorderBrush" />
|
|
||||||
<StaticResource x:Key="ImageCropperOuterThumbBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
|
|
||||||
</ResourceDictionary>
|
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
|
||||||
<CornerRadius x:Key="ImageCropperThumbCornerRadius">10</CornerRadius>
|
|
||||||
<x:Double x:Key="ImageCropperInnerThumbWidth">12</x:Double>
|
|
||||||
<x:Double x:Key="ImageCropperInnerThumbHeight">12</x:Double>
|
|
||||||
<x:Double x:Key="ImageCropperThumbWidth">18</x:Double>
|
|
||||||
<x:Double x:Key="ImageCropperThumbHeight">18</x:Double>
|
|
||||||
<ControlTheme x:Key="ImageCropperThumbStyle" TargetType="Thumb">
|
|
||||||
<Setter Property="BorderThickness" Value="1" />
|
|
||||||
<Setter Property="Background" Value="{DynamicResource ImageCropperThumbBackground}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource ImageCropperThumbBrush}" />
|
|
||||||
<Setter Property="ClipToBounds" Value="False" />
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate>
|
|
||||||
<Border
|
|
||||||
Margin="-2"
|
|
||||||
Background="{DynamicResource ImageCropperOuterThumbBackground}"
|
|
||||||
BorderBrush="{TemplateBinding BorderBrush}"
|
|
||||||
BorderThickness="{TemplateBinding BorderThickness}"
|
|
||||||
CornerRadius="{DynamicResource ImageCropperOuterThumbCornerRadius}">
|
|
||||||
<Ellipse
|
|
||||||
Name="InnerThumb"
|
|
||||||
Width="{DynamicResource ImageCropperInnerThumbWidth}"
|
|
||||||
Height="{DynamicResource ImageCropperInnerThumbHeight}"
|
|
||||||
Fill="{TemplateBinding Background}"
|
|
||||||
RenderTransform="scaleX(0.86) scaleY(0.86)">
|
|
||||||
<Ellipse.Transitions>
|
|
||||||
<Transitions>
|
|
||||||
<TransformOperationsTransition
|
|
||||||
Easing="0,0 0,1"
|
|
||||||
Property="RenderTransform"
|
|
||||||
Duration="00:00:00.167" />
|
|
||||||
</Transitions>
|
|
||||||
</Ellipse.Transitions>
|
|
||||||
</Ellipse>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
<Style Selector="^:pointerover /template/ Ellipse#InnerThumb">
|
|
||||||
<Setter Property="RenderTransform" Value="scaleX(1.167) scaleY(1.167)" />
|
|
||||||
</Style>
|
|
||||||
<Style Selector="^:pressed /template/ Ellipse#InnerThumb">
|
|
||||||
<Setter Property="RenderTransform" Value="scaleX(0.71) scaleY(0.71)" />
|
|
||||||
</Style>
|
|
||||||
<Style Selector="^:disabled /template/ Ellipse#InnerThumb">
|
|
||||||
<Setter Property="RenderTransform" Value="scaleX(1.167) scaleY(1.167)" />
|
|
||||||
</Style>
|
|
||||||
</ControlTheme>
|
|
||||||
<ControlTheme x:Key="{x:Type ImageCropper}" TargetType="ImageCropper">
|
|
||||||
<Setter Property="Template">
|
|
||||||
<ControlTemplate>
|
|
||||||
<Canvas x:Name="Canvas">
|
|
||||||
<Rectangle
|
|
||||||
x:Name="RectangleLeft"
|
|
||||||
Fill="{DynamicResource SmokeFillColorDefaultBrush}"
|
|
||||||
UseLayoutRounding="True" />
|
|
||||||
<Rectangle
|
|
||||||
x:Name="RectangleTop"
|
|
||||||
Fill="{DynamicResource SmokeFillColorDefaultBrush}"
|
|
||||||
UseLayoutRounding="True" />
|
|
||||||
<Rectangle
|
|
||||||
x:Name="RectangleRight"
|
|
||||||
Fill="{DynamicResource SmokeFillColorDefaultBrush}"
|
|
||||||
UseLayoutRounding="True" />
|
|
||||||
<Rectangle
|
|
||||||
x:Name="RectangleBottom"
|
|
||||||
Fill="{DynamicResource SmokeFillColorDefaultBrush}"
|
|
||||||
UseLayoutRounding="True" />
|
|
||||||
<Border
|
|
||||||
x:Name="Border"
|
|
||||||
Background="Transparent"
|
|
||||||
BorderBrush="Transparent"
|
|
||||||
BorderThickness="2"
|
|
||||||
Cursor="SizeAll" />
|
|
||||||
<Thumb
|
|
||||||
x:Name="TopLeftButton"
|
|
||||||
Width="{DynamicResource ImageCropperThumbWidth}"
|
|
||||||
Height="{DynamicResource ImageCropperThumbHeight}"
|
|
||||||
Theme="{StaticResource ImageCropperThumbStyle}" />
|
|
||||||
<Thumb
|
|
||||||
x:Name="TopRightButton"
|
|
||||||
Width="{DynamicResource ImageCropperThumbWidth}"
|
|
||||||
Height="{DynamicResource ImageCropperThumbHeight}"
|
|
||||||
Theme="{StaticResource ImageCropperThumbStyle}" />
|
|
||||||
<Thumb
|
|
||||||
x:Name="BottomLeftButton"
|
|
||||||
Width="{DynamicResource ImageCropperThumbWidth}"
|
|
||||||
Height="{DynamicResource ImageCropperThumbHeight}"
|
|
||||||
Theme="{StaticResource ImageCropperThumbStyle}" />
|
|
||||||
<Thumb
|
|
||||||
x:Name="BottomRightButton"
|
|
||||||
Width="{DynamicResource ImageCropperThumbWidth}"
|
|
||||||
Height="{DynamicResource ImageCropperThumbHeight}"
|
|
||||||
Theme="{StaticResource ImageCropperThumbStyle}" />
|
|
||||||
</Canvas>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter>
|
|
||||||
</ControlTheme>
|
|
||||||
</ResourceDictionary>
|
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
<MergeResourceInclude Source="../Overflow/Overflow.axaml" />
|
<MergeResourceInclude Source="../Overflow/Overflow.axaml" />
|
||||||
<MergeResourceInclude Source="../ContentBadge/ContentBadge.axaml" />
|
<MergeResourceInclude Source="../ContentBadge/ContentBadge.axaml" />
|
||||||
<MergeResourceInclude Source="../TabStrip/TabStrip.axaml" />
|
<MergeResourceInclude Source="../TabStrip/TabStrip.axaml" />
|
||||||
<MergeResourceInclude Source="../ImageCropper/ImageCropper.axaml" />
|
<MergeResourceInclude Source="../ContentCropper/ContentCropper.axaml" />
|
||||||
<MergeResourceInclude Source="../ContentCard/ContentCard.axaml" />
|
<MergeResourceInclude Source="../ContentCard/ContentCard.axaml" />
|
||||||
<MergeResourceInclude Source="../TaskDialog/TaskDialog.axaml" />
|
<MergeResourceInclude Source="../TaskDialog/TaskDialog.axaml" />
|
||||||
<MergeResourceInclude Source="../ContentColorPicker/ContentColorPicker.axaml" />
|
<MergeResourceInclude Source="../ContentColorPicker/ContentColorPicker.axaml" />
|
||||||
|
|||||||
Reference in New Issue
Block a user