Browse Source

Code refactorization + cleanup

MarcinZiabek 3 years ago
parent
commit
b2826a06b8

+ 19 - 57
QuestPDF.Previewer/DocumentRenderer.cs

@@ -2,10 +2,7 @@
 using System.ComponentModel;
 using System.ComponentModel;
 using Avalonia.Threading;
 using Avalonia.Threading;
 using QuestPDF.Drawing;
 using QuestPDF.Drawing;
-using QuestPDF.Fluent;
-using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
-using SkiaSharp;
 
 
 namespace QuestPDF.Previewer
 namespace QuestPDF.Previewer
 {
 {
@@ -17,8 +14,8 @@ namespace QuestPDF.Previewer
 
 
         public event PropertyChangedEventHandler? PropertyChanged;
         public event PropertyChangedEventHandler? PropertyChanged;
 
 
-        private ObservableCollection<RenderedPageInfo> _pages = new();
-        public ObservableCollection<RenderedPageInfo> Pages
+        private ObservableCollection<PreviewPage> _pages = new();
+        public ObservableCollection<PreviewPage> Pages
         {
         {
             get => _pages;
             get => _pages;
             set
             set
@@ -48,21 +45,23 @@ namespace QuestPDF.Previewer
         public void UpdateDocument(IDocument? document)
         public void UpdateDocument(IDocument? document)
         {
         {
             Document = 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(() =>
             Dispatcher.UIThread.Post(() =>
             {
             {
                 Pages.Clear();
                 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 - 0
QuestPDF.Previewer/ExceptionDocument.cs

@@ -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);
+                }
+            });
+        });
+    }
+}

+ 24 - 17
QuestPDF.Previewer/InteractiveCanvas.cs

@@ -1,9 +1,7 @@
-using System.Diagnostics;
-using Avalonia;
+using Avalonia;
 using Avalonia.Platform;
 using Avalonia.Platform;
 using Avalonia.Rendering.SceneGraph;
 using Avalonia.Rendering.SceneGraph;
 using Avalonia.Skia;
 using Avalonia.Skia;
-using QuestPDF.Helpers;
 using SkiaSharp;
 using SkiaSharp;
 
 
 namespace QuestPDF.Previewer;
 namespace QuestPDF.Previewer;
@@ -11,7 +9,7 @@ namespace QuestPDF.Previewer;
 class InteractiveCanvas : ICustomDrawOperation
 class InteractiveCanvas : ICustomDrawOperation
 {
 {
     public Rect Bounds { get; set; }
     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 Width => (float)Bounds.Width;
     private float Height => (float)Bounds.Height;
     private float Height => (float)Bounds.Height;
@@ -26,6 +24,8 @@ class InteractiveCanvas : ICustomDrawOperation
     private const float PageSpacing = 50f;
     private const float PageSpacing = 50f;
     private const float SafeZone = 50f;
     private const float SafeZone = 50f;
 
 
+    #region transformations
+    
     private void LimitScale()
     private void LimitScale()
     {
     {
         Scale = Math.Max(Scale, MinScale);
         Scale = Math.Max(Scale, MinScale);
@@ -79,15 +79,15 @@ class InteractiveCanvas : ICustomDrawOperation
         LimitTranslate();
         LimitTranslate();
     }
     }
     
     
+    #endregion
+    
+    #region rendering
+    
     public void Render(IDrawingContextImpl context)
     public void Render(IDrawingContextImpl context)
     {
     {
         if (Pages.Count <= 0)
         if (Pages.Count <= 0)
             return;
             return;
 
 
-        LimitScale();
-        LimitTranslate();
-
-        
         var canvas = (context as ISkiaDrawingContextImpl)?.SkCanvas;
         var canvas = (context as ISkiaDrawingContextImpl)?.SkCanvas;
         
         
         if (canvas == null)
         if (canvas == null)
@@ -95,7 +95,6 @@ class InteractiveCanvas : ICustomDrawOperation
 
 
         var originalMatrix = canvas.TotalMatrix;
         var originalMatrix = canvas.TotalMatrix;
 
 
-        
         canvas.Translate(Width / 2, Height / 2);
         canvas.Translate(Width / 2, Height / 2);
         
         
         canvas.Scale(Scale);
         canvas.Scale(Scale);
@@ -104,7 +103,7 @@ class InteractiveCanvas : ICustomDrawOperation
         foreach (var page in Pages)
         foreach (var page in Pages)
         {
         {
             canvas.Translate(-page.Size.Width / 2f, 0);
             canvas.Translate(-page.Size.Width / 2f, 0);
-            DrawPageShadow(canvas, page.Size);
+            DrawBlankPage(canvas, page.Size);
             canvas.DrawPicture(page.Picture);
             canvas.DrawPicture(page.Picture);
             canvas.Translate(page.Size.Width / 2f, page.Size.Height + PageSpacing);
             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 Equals(ICustomDrawOperation? other) => false;
     public bool HitTest(Point p) => true;
     public bool HitTest(Point p) => true;
 
 
-    #region page shadow
+    #endregion
+    
+    #region blank page
 
 
-    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));
+    private static SKPaint BlankPagePaint = new SKPaint
+    {
+        Color = SKColors.White
+    };
     
     
-    private static SKPaint PageShadowPaint = new SKPaint
+    private static SKPaint BlankPageShadowPaint = new SKPaint
     {
     {
-        ImageFilter = SKImageFilter.CreateBlendMode(SKBlendMode.Overlay, PageShadow1, PageShadow2)
+        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 DrawPageShadow(SKCanvas canvas, QuestPDF.Infrastructure.Size size)
+    private void DrawBlankPage(SKCanvas canvas, QuestPDF.Infrastructure.Size size)
     {
     {
-        canvas.DrawRect(0, 0, size.Width, size.Height, PageShadowPaint);
+        canvas.DrawRect(0, 0, size.Width, size.Height, BlankPageShadowPaint);
+        canvas.DrawRect(0, 0, size.Width, size.Height, BlankPagePaint);
     }
     }
     
     
     #endregion
     #endregion

+ 14 - 17
QuestPDF.Previewer/PreviewerCanvas.cs

@@ -4,16 +4,15 @@ using SkiaSharp;
 
 
 namespace QuestPDF.Previewer
 namespace QuestPDF.Previewer
 {
 {
-    public record RenderedPageInfo(SKPicture Picture, Size Size);
+    public record PreviewPage(SKPicture Picture, Size Size);
     
     
     internal sealed class PreviewerCanvas : SkiaCanvasBase, IRenderingCanvas
     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()
         public override void BeginDocument()
         {
         {
             Pictures.Clear();
             Pictures.Clear();
@@ -21,23 +20,21 @@ namespace QuestPDF.Previewer
 
 
         public override void BeginPage(Size size)
         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()
         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() { }
         public override void EndDocument() { }

+ 3 - 8
QuestPDF.Previewer/PreviewerControl.cs

@@ -1,24 +1,19 @@
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Reactive.Linq;
-using System.Runtime.InteropServices.ComTypes;
 using Avalonia;
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls;
-using Avalonia.Controls.Presenters;
 using Avalonia.Input;
 using Avalonia.Input;
-using Avalonia.Interactivity;
 using Avalonia.Media;
 using Avalonia.Media;
 
 
 namespace QuestPDF.Previewer
 namespace QuestPDF.Previewer
 {
 {
     internal class PreviewerControl : Control
     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();
         private InteractiveCanvas InteractiveCanvas { get; set; } = new InteractiveCanvas();
         
         
-        public ObservableCollection<RenderedPageInfo>? Pages
+        public ObservableCollection<PreviewPage>? Pages
         {
         {
             get => GetValue(PagesProperty);
             get => GetValue(PagesProperty);
             set => SetValue(PagesProperty, value);
             set => SetValue(PagesProperty, value);

+ 0 - 39
QuestPDF.Previewer/SkCustomDrawOperation.cs

@@ -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);
-        }
-    }
-}

+ 3 - 1
QuestPDF.ReportSample/Layouts/PhotoTemplate.cs

@@ -1,3 +1,4 @@
+using System;
 using QuestPDF.Fluent;
 using QuestPDF.Fluent;
 using QuestPDF.Helpers;
 using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
@@ -47,7 +48,8 @@ namespace QuestPDF.ReportSample.Layouts
             container.Border(0.75f).BorderColor(Colors.Grey.Medium).Grid(grid =>
             container.Border(0.75f).BorderColor(Colors.Grey.Medium).Grid(grid =>
             {
             {
                 grid.Columns(6);
                 grid.Columns(6);
-                
+
+
                 grid.Item().LabelCell().Text("Date");
                 grid.Item().LabelCell().Text("Date");
                 grid.Item(2).ValueCell().Text(Model.Date?.ToString("g") ?? string.Empty);
                 grid.Item(2).ValueCell().Text(Model.Date?.ToString("g") ?? string.Empty);
                 grid.Item().LabelCell().Text("Location");
                 grid.Item().LabelCell().Text("Location");