Code refactorization + cleanup

This commit is contained in:
MarcinZiabek
2022-03-21 01:16:26 +01:00
parent 321cba32ce
commit b2826a06b8
7 changed files with 119 additions and 140 deletions
+19 -57
View File
@@ -2,10 +2,7 @@
using System.ComponentModel;
using Avalonia.Threading;
using QuestPDF.Drawing;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using SkiaSharp;
namespace QuestPDF.Previewer
{
@@ -17,8 +14,8 @@ namespace QuestPDF.Previewer
public event PropertyChangedEventHandler? PropertyChanged;
private ObservableCollection<RenderedPageInfo> _pages = new();
public ObservableCollection<RenderedPageInfo> Pages
private ObservableCollection<PreviewPage> _pages = new();
public ObservableCollection<PreviewPage> Pages
{
get => _pages;
set
@@ -48,21 +45,23 @@ namespace QuestPDF.Previewer
public void UpdateDocument(IDocument? document)
{
Document = document;
if (document != null)
if (document == null)
return;
try
{
try
{
IsRendering = true;
RenderDocument(document);
}
catch (Exception ex)
{
RenderDocument(CreateExceptionDocument(ex));
}
finally
{
IsRendering = false;
}
IsRendering = true;
RenderDocument(document);
}
catch (Exception exception)
{
var exceptionDocument = new ExceptionDocument(exception);
RenderDocument(exceptionDocument);
}
finally
{
IsRendering = false;
}
}
@@ -82,44 +81,7 @@ namespace QuestPDF.Previewer
Dispatcher.UIThread.Post(() =>
{
Pages.Clear();
Pages = new ObservableCollection<RenderedPageInfo>(canvas.Pictures);
});
}
private static IDocument CreateExceptionDocument(Exception exception)
{
return Fluent.Document.Create(document =>
{
document.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(1, Unit.Inch);
page.PageColor(Colors.Red.Lighten4);
page.DefaultTextStyle(x => x.FontSize(16));
page.Header()
.BorderBottom(2)
.BorderColor(Colors.Red.Medium)
.PaddingBottom(5)
.Text("Ooops! Something went wrong...").FontSize(28).FontColor(Colors.Red.Medium).Bold();
page.Content().PaddingVertical(20).Column(column =>
{
var currentException = exception;
while (currentException != null)
{
column.Item().Text(exception.GetType().Name).FontSize(20).SemiBold();
column.Item().Text(exception.Message).FontSize(14);
column.Item().PaddingTop(10).Text(exception.StackTrace).FontSize(10).Light();
currentException = currentException.InnerException;
if (currentException != null)
column.Item().PaddingVertical(15).LineHorizontal(2).LineColor(Colors.Red.Medium);
}
});
});
Pages = new ObservableCollection<PreviewPage>(canvas.Pictures);
});
}
}
+55
View File
@@ -0,0 +1,55 @@
using QuestPDF.Drawing;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
namespace QuestPDF.Previewer;
public class ExceptionDocument : IDocument
{
private Exception Exception { get; }
public ExceptionDocument(Exception exception)
{
Exception = exception;
}
public DocumentMetadata GetMetadata()
{
return DocumentMetadata.Default;
}
public void Compose(IDocumentContainer document)
{
document.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(1, Unit.Inch);
page.PageColor(Colors.Red.Lighten4);
page.DefaultTextStyle(x => x.FontSize(16));
page.Header()
.BorderBottom(2)
.BorderColor(Colors.Red.Medium)
.PaddingBottom(5)
.Text("Ooops! Something went wrong...").FontSize(28).FontColor(Colors.Red.Medium).Bold();
page.Content().PaddingVertical(20).Column(column =>
{
var currentException = Exception;
while (currentException != null)
{
column.Item().Text(currentException.GetType().Name).FontSize(20).SemiBold();
column.Item().Text(currentException.Message).FontSize(14);
column.Item().PaddingTop(10).Text(currentException.StackTrace).FontSize(10).Light();
currentException = currentException.InnerException;
if (currentException != null)
column.Item().PaddingVertical(15).LineHorizontal(2).LineColor(Colors.Red.Medium);
}
});
});
}
}
+25 -18
View File
@@ -1,9 +1,7 @@
using System.Diagnostics;
using Avalonia;
using Avalonia;
using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Skia;
using QuestPDF.Helpers;
using SkiaSharp;
namespace QuestPDF.Previewer;
@@ -11,7 +9,7 @@ namespace QuestPDF.Previewer;
class InteractiveCanvas : ICustomDrawOperation
{
public Rect Bounds { get; set; }
public ICollection<RenderedPageInfo> Pages { get; set; }
public ICollection<PreviewPage> Pages { get; set; }
private float Width => (float)Bounds.Width;
private float Height => (float)Bounds.Height;
@@ -26,6 +24,8 @@ class InteractiveCanvas : ICustomDrawOperation
private const float PageSpacing = 50f;
private const float SafeZone = 50f;
#region transformations
private void LimitScale()
{
Scale = Math.Max(Scale, MinScale);
@@ -79,15 +79,15 @@ class InteractiveCanvas : ICustomDrawOperation
LimitTranslate();
}
#endregion
#region rendering
public void Render(IDrawingContextImpl context)
{
if (Pages.Count <= 0)
return;
LimitScale();
LimitTranslate();
var canvas = (context as ISkiaDrawingContextImpl)?.SkCanvas;
if (canvas == null)
@@ -95,7 +95,6 @@ class InteractiveCanvas : ICustomDrawOperation
var originalMatrix = canvas.TotalMatrix;
canvas.Translate(Width / 2, Height / 2);
canvas.Scale(Scale);
@@ -104,7 +103,7 @@ class InteractiveCanvas : ICustomDrawOperation
foreach (var page in Pages)
{
canvas.Translate(-page.Size.Width / 2f, 0);
DrawPageShadow(canvas, page.Size);
DrawBlankPage(canvas, page.Size);
canvas.DrawPicture(page.Picture);
canvas.Translate(page.Size.Width / 2f, page.Size.Height + PageSpacing);
}
@@ -119,19 +118,27 @@ class InteractiveCanvas : ICustomDrawOperation
public bool Equals(ICustomDrawOperation? other) => false;
public bool HitTest(Point p) => true;
#region page shadow
private static readonly SKImageFilter PageShadow1 = SKImageFilter.CreateDropShadowOnly(0, 6, 6, 6, SKColors.Black.WithAlpha(64));
private static readonly SKImageFilter PageShadow2 = SKImageFilter.CreateDropShadowOnly(0, 10, 14, 14, SKColors.Black.WithAlpha(32));
#endregion
private static SKPaint PageShadowPaint = new SKPaint
#region blank page
private static SKPaint BlankPagePaint = new SKPaint
{
ImageFilter = SKImageFilter.CreateBlendMode(SKBlendMode.Overlay, PageShadow1, PageShadow2)
Color = SKColors.White
};
private void DrawPageShadow(SKCanvas canvas, QuestPDF.Infrastructure.Size size)
private static SKPaint BlankPageShadowPaint = new SKPaint
{
canvas.DrawRect(0, 0, size.Width, size.Height, PageShadowPaint);
ImageFilter = SKImageFilter.CreateBlendMode(
SKBlendMode.Overlay,
SKImageFilter.CreateDropShadowOnly(0, 6, 6, 6, SKColors.Black.WithAlpha(64)),
SKImageFilter.CreateDropShadowOnly(0, 10, 14, 14, SKColors.Black.WithAlpha(32)))
};
private void DrawBlankPage(SKCanvas canvas, QuestPDF.Infrastructure.Size size)
{
canvas.DrawRect(0, 0, size.Width, size.Height, BlankPageShadowPaint);
canvas.DrawRect(0, 0, size.Width, size.Height, BlankPagePaint);
}
#endregion
+14 -17
View File
@@ -4,16 +4,15 @@ using SkiaSharp;
namespace QuestPDF.Previewer
{
public record RenderedPageInfo(SKPicture Picture, Size Size);
public record PreviewPage(SKPicture Picture, Size Size);
internal sealed class PreviewerCanvas : SkiaCanvasBase, IRenderingCanvas
{
private SKPictureRecorder? _currentRecorder;
private SKPictureRecorder? PictureRecorder { get; set; }
private Size? CurrentPageSize { get; set; }
public ICollection<PreviewPage> Pictures { get; } = new List<PreviewPage>();
public ICollection<RenderedPageInfo> Pictures { get; } = new List<RenderedPageInfo>();
private Size? _currentSize;
public override void BeginDocument()
{
Pictures.Clear();
@@ -21,23 +20,21 @@ namespace QuestPDF.Previewer
public override void BeginPage(Size size)
{
_currentSize = size;
_currentRecorder = new SKPictureRecorder();
Canvas = _currentRecorder.BeginRecording(new SKRect(0, 0, size.Width, size.Height));
using var paint = new SKPaint() { Color = SKColors.White };
Canvas.DrawRect(0, 0, size.Width, size.Height, paint);
CurrentPageSize = size;
PictureRecorder = new SKPictureRecorder();
Canvas = PictureRecorder.BeginRecording(new SKRect(0, 0, size.Width, size.Height));
}
public override void EndPage()
{
var picture = _currentRecorder?.EndRecording();
var picture = PictureRecorder?.EndRecording();
if (picture != null && _currentSize.HasValue)
Pictures.Add(new RenderedPageInfo(picture, _currentSize.Value));
if (picture != null && CurrentPageSize.HasValue)
Pictures.Add(new PreviewPage(picture, CurrentPageSize.Value));
_currentRecorder?.Dispose();
_currentRecorder = null;
PictureRecorder?.Dispose();
PictureRecorder = null;
}
public override void EndDocument() { }
+3 -8
View File
@@ -1,24 +1,19 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reactive.Linq;
using System.Runtime.InteropServices.ComTypes;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
namespace QuestPDF.Previewer
{
internal class PreviewerControl : Control
{
public static readonly StyledProperty<ObservableCollection<RenderedPageInfo>?> PagesProperty =
AvaloniaProperty.Register<PreviewerControl, ObservableCollection<RenderedPageInfo>>(nameof(Pages));
public static readonly StyledProperty<ObservableCollection<PreviewPage>?> PagesProperty =
AvaloniaProperty.Register<PreviewerControl, ObservableCollection<PreviewPage>>(nameof(Pages));
private InteractiveCanvas InteractiveCanvas { get; set; } = new InteractiveCanvas();
public ObservableCollection<RenderedPageInfo>? Pages
public ObservableCollection<PreviewPage>? Pages
{
get => GetValue(PagesProperty);
set => SetValue(PagesProperty, value);
@@ -1,39 +0,0 @@
using Avalonia;
using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Skia;
using SkiaSharp;
namespace QuestPDF.Previewer
{
internal sealed class SkCustomDrawOperation : ICustomDrawOperation
{
private readonly Action<SKCanvas> _renderFunc;
public Rect Bounds { get; }
public SkCustomDrawOperation(Rect bounds, Action<SKCanvas> renderFunc)
{
Bounds = bounds;
_renderFunc = renderFunc;
}
public void Dispose() { }
public bool Equals(ICustomDrawOperation? other)
{
return false;
}
public bool HitTest(Point p)
{
return false;
}
public void Render(IDrawingContextImpl context)
{
var canvas = (context as ISkiaDrawingContextImpl)?.SkCanvas;
if (canvas == null)
throw new InvalidOperationException($"Context needs to be ISkiaDrawingContextImpl but got {nameof(context)}");
_renderFunc(canvas);
}
}
}
@@ -1,3 +1,4 @@
using System;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
@@ -47,7 +48,8 @@ namespace QuestPDF.ReportSample.Layouts
container.Border(0.75f).BorderColor(Colors.Grey.Medium).Grid(grid =>
{
grid.Columns(6);
grid.Item().LabelCell().Text("Date");
grid.Item(2).ValueCell().Text(Model.Date?.ToString("g") ?? string.Empty);
grid.Item().LabelCell().Text("Location");