diff --git a/QuestPDF.Previewer/DocumentPreviewerExtensions.cs b/QuestPDF.Previewer/DocumentPreviewerExtensions.cs
deleted file mode 100644
index 1537c50..0000000
--- a/QuestPDF.Previewer/DocumentPreviewerExtensions.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Avalonia;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.ReactiveUI;
-using QuestPDF.Infrastructure;
-
-namespace QuestPDF.Previewer
-{
- public static class DocumentPreviewerExtensions
- {
- ///
- /// Opens document in the QuestPDF previewer tool.
- /// Improves development speed by supporting hot reloading.
- /// Shows document preview and refreshes it after each code change.
- ///
- ///
- /// Intended for development only. Do not use in production environment.
- ///
- public static void ShowInPreviewer(this IDocument document)
- {
- ArgumentNullException.ThrowIfNull(document);
-
- // currently there is no way to utilize a previously run Avalonia app.
- // so we need to check if the previewer was already run and show the window again.
- if(Application.Current?.ApplicationLifetime is ClassicDesktopStyleApplicationLifetime desktop)
- {
- desktop.MainWindow = new PreviewerWindow()
- {
- DataContext = new PreviewerWindowViewModel()
- {
- Document = document,
- }
- };
-
- desktop.MainWindow.Show();
- desktop.Start(Array.Empty());
-
- return;
- }
-
- AppBuilder
- .Configure(() => new PreviewerApp()
- {
- Document = document,
- })
- .UsePlatformDetect()
- .UseReactiveUI()
- .StartWithClassicDesktopLifetime(Array.Empty());
- }
- }
-}
diff --git a/QuestPDF.Previewer/DocumentRenderer.cs b/QuestPDF.Previewer/DocumentRenderer.cs
deleted file mode 100644
index c861914..0000000
--- a/QuestPDF.Previewer/DocumentRenderer.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using Avalonia.Threading;
-using QuestPDF.Drawing;
-using QuestPDF.Infrastructure;
-
-namespace QuestPDF.Previewer
-{
- internal class DocumentRenderer : INotifyPropertyChanged
- {
- public IDocument? Document { get; private set; }
-
- public event PropertyChangedEventHandler? PropertyChanged;
-
- private ObservableCollection _pages = new();
- public ObservableCollection Pages
- {
- get => _pages;
- set
- {
- if (_pages != value)
- {
- _pages = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Pages)));
- }
- }
- }
-
- public void UpdateDocument(IDocument? document)
- {
- Document = document;
-
- if (document == null)
- return;
-
- try
- {
- RenderDocument(document);
- }
- catch (Exception exception)
- {
- var exceptionDocument = new ExceptionDocument(exception);
- RenderDocument(exceptionDocument);
- }
- }
-
- private void RenderDocument(IDocument document)
- {
- var canvas = new PreviewerCanvas();
-
- DocumentGenerator.RenderDocument(canvas, document);
-
- foreach (var pages in Pages)
- pages?.Picture?.Dispose();
-
- Dispatcher.UIThread.Post(() =>
- {
- Pages.Clear();
- Pages = new ObservableCollection(canvas.Pictures);
- });
- }
- }
-}
diff --git a/QuestPDF.Previewer/ExceptionDocument.cs b/QuestPDF.Previewer/ExceptionDocument.cs
deleted file mode 100644
index fbe8e0f..0000000
--- a/QuestPDF.Previewer/ExceptionDocument.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-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);
- }
- });
- });
- }
-}
\ No newline at end of file
diff --git a/QuestPDF.Previewer/HotReloadManager.cs b/QuestPDF.Previewer/HotReloadManager.cs
deleted file mode 100644
index a8d34fe..0000000
--- a/QuestPDF.Previewer/HotReloadManager.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-[assembly: System.Reflection.Metadata.MetadataUpdateHandler(typeof(QuestPDF.Previewer.HotReloadManager))]
-
-namespace QuestPDF.Previewer
-{
- ///
- /// Helper for subscribing to hot reload notifications.
- ///
- internal static class HotReloadManager
- {
- public static event EventHandler? UpdateApplicationRequested;
-
- public static void UpdateApplication(Type[]? _)
- {
- UpdateApplicationRequested?.Invoke(null, EventArgs.Empty);
- }
- }
-}
diff --git a/QuestPDF.Previewer/Images/Logo.png b/QuestPDF.Previewer/Images/Logo.png
deleted file mode 100644
index a0f1a19..0000000
Binary files a/QuestPDF.Previewer/Images/Logo.png and /dev/null differ
diff --git a/QuestPDF.Previewer/InteractiveCanvas.cs b/QuestPDF.Previewer/InteractiveCanvas.cs
deleted file mode 100644
index 69a786c..0000000
--- a/QuestPDF.Previewer/InteractiveCanvas.cs
+++ /dev/null
@@ -1,205 +0,0 @@
-using System.Diagnostics;
-using Avalonia;
-using Avalonia.Platform;
-using Avalonia.Rendering.SceneGraph;
-using Avalonia.Skia;
-using SkiaSharp;
-
-namespace QuestPDF.Previewer;
-
-class InteractiveCanvas : ICustomDrawOperation
-{
- public Rect Bounds { get; set; }
- public ICollection Pages { get; set; }
-
- private float Width => (float)Bounds.Width;
- private float Height => (float)Bounds.Height;
-
- public float Scale { get; private set; } = 1;
- public float TranslateX { get; set; }
- public float TranslateY { get; set; }
-
- private const float MinScale = 0.1f;
- private const float MaxScale = 10f;
-
- private const float PageSpacing = 25f;
- private const float SafeZone = 25f;
-
- public float TotalPagesHeight => Pages.Sum(x => x.Size.Height) + (Pages.Count - 1) * PageSpacing;
- public float TotalHeight => TotalPagesHeight + SafeZone * 2 / Scale;
- public float MaxWidth => Pages.Any() ? Pages.Max(x => x.Size.Width) : 0;
-
- public float MaxTranslateY => TotalHeight - Height / Scale;
-
- public float ScrollPercentY
- {
- get
- {
- return TranslateY / MaxTranslateY;
- }
- set
- {
- TranslateY = value * MaxTranslateY;
- }
- }
-
- public float ScrollViewportSizeY
- {
- get
- {
- var viewPortSize = Height / Scale / TotalHeight;
- return Math.Clamp(viewPortSize, 0, 1);
- }
- }
-
- #region transformations
-
- private void LimitScale()
- {
- Scale = Math.Max(Scale, MinScale);
- Scale = Math.Min(Scale, MaxScale);
- }
-
- private void LimitTranslate()
- {
- if (TotalPagesHeight > Height / Scale)
- {
- TranslateY = Math.Min(TranslateY, MaxTranslateY);
- TranslateY = Math.Max(TranslateY, 0);
- }
- else
- {
- TranslateY = (TotalPagesHeight - Height / Scale) / 2;
- }
-
- if (Width / Scale < MaxWidth)
- {
- var maxTranslateX = (Width / 2 - SafeZone) / Scale - MaxWidth / 2;
-
- TranslateX = Math.Min(TranslateX, -maxTranslateX);
- TranslateX = Math.Max(TranslateX, maxTranslateX);
- }
- else
- {
- TranslateX = 0;
- }
- }
-
- public void TranslateWithCurrentScale(float x, float y)
- {
- TranslateX += x / Scale;
- TranslateY += y / Scale;
-
- LimitTranslate();
- }
-
- public void ZoomToPoint(float x, float y, float factor)
- {
- var oldScale = Scale;
- Scale *= factor;
-
- LimitScale();
-
- factor = Scale / oldScale;
-
- TranslateX -= x / (oldScale * factor) - x / oldScale;
- TranslateY -= y / (oldScale * factor) - y / oldScale;
-
- 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)
- throw new InvalidOperationException($"Context needs to be ISkiaDrawingContextImpl but got {nameof(context)}");
-
- var originalMatrix = canvas.TotalMatrix;
-
- canvas.Translate(Width / 2, 0);
-
- canvas.Scale(Scale);
- canvas.Translate(TranslateX, -TranslateY + SafeZone / Scale);
-
- foreach (var page in Pages)
- {
- canvas.Translate(-page.Size.Width / 2f, 0);
- DrawBlankPage(canvas, page.Size);
- canvas.DrawPicture(page.Picture);
- canvas.Translate(page.Size.Width / 2f, page.Size.Height + PageSpacing);
- }
-
- canvas.SetMatrix(originalMatrix);
- DrawInnerGradient(canvas);
- }
-
- public void Dispose() { }
- public bool Equals(ICustomDrawOperation? other) => false;
- public bool HitTest(Point p) => true;
-
- #endregion
-
- #region blank page
-
- private static SKPaint BlankPagePaint = new SKPaint
- {
- Color = SKColors.White
- };
-
- private static SKPaint BlankPageShadowPaint = new SKPaint
- {
- 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
-
- #region inner viewport gradient
-
- private const int InnerGradientSize = (int)SafeZone;
- private static readonly SKColor InnerGradientColor = SKColor.Parse("#666");
-
- private void DrawInnerGradient(SKCanvas canvas)
- {
- // gamma correction
- var colors = Enumerable
- .Range(0, InnerGradientSize)
- .Select(x => 1f - x / (float) InnerGradientSize)
- .Select(x => Math.Pow(x, 2f))
- .Select(x => (byte)(x * 255))
- .Select(x => InnerGradientColor.WithAlpha(x))
- .ToArray();
-
- using var fogPaint = new SKPaint
- {
- Shader = SKShader.CreateLinearGradient(
- new SKPoint(0, 0),
- new SKPoint(0, InnerGradientSize),
- colors,
- SKShaderTileMode.Clamp)
- };
-
- canvas.DrawRect(0, 0, Width, InnerGradientSize, fogPaint);
- }
-
- #endregion
-}
diff --git a/QuestPDF.Previewer/PreviewerApp.axaml b/QuestPDF.Previewer/PreviewerApp.axaml
deleted file mode 100644
index 725db69..0000000
--- a/QuestPDF.Previewer/PreviewerApp.axaml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/QuestPDF.Previewer/PreviewerApp.axaml.cs b/QuestPDF.Previewer/PreviewerApp.axaml.cs
deleted file mode 100644
index 9dccf3c..0000000
--- a/QuestPDF.Previewer/PreviewerApp.axaml.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Avalonia;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Markup.Xaml;
-using QuestPDF.Infrastructure;
-
-namespace QuestPDF.Previewer
-{
- internal class PreviewerApp : Application
- {
- public IDocument? Document { get; init; }
-
- public override void Initialize()
- {
- AvaloniaXamlLoader.Load(this);
- }
-
- public override void OnFrameworkInitializationCompleted()
- {
- if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
- {
- desktop.MainWindow = new PreviewerWindow()
- {
- DataContext = new PreviewerWindowViewModel()
- {
- Document = Document,
- }
- };
- }
-
- base.OnFrameworkInitializationCompleted();
- }
- }
-}
diff --git a/QuestPDF.Previewer/PreviewerCanvas.cs b/QuestPDF.Previewer/PreviewerCanvas.cs
deleted file mode 100644
index cf9d222..0000000
--- a/QuestPDF.Previewer/PreviewerCanvas.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using QuestPDF.Drawing;
-using QuestPDF.Infrastructure;
-using SkiaSharp;
-
-namespace QuestPDF.Previewer
-{
- record PreviewPage(SKPicture Picture, Size Size);
-
- sealed class PreviewerCanvas : SkiaCanvasBase, IRenderingCanvas
- {
- private SKPictureRecorder? PictureRecorder { get; set; }
- private Size? CurrentPageSize { get; set; }
-
- public ICollection Pictures { get; } = new List();
-
- public override void BeginDocument()
- {
- Pictures.Clear();
- }
-
- public override void BeginPage(Size size)
- {
- CurrentPageSize = size;
- PictureRecorder = new SKPictureRecorder();
-
- Canvas = PictureRecorder.BeginRecording(new SKRect(0, 0, size.Width, size.Height));
- }
-
- public override void EndPage()
- {
- var picture = PictureRecorder?.EndRecording();
-
- if (picture != null && CurrentPageSize.HasValue)
- Pictures.Add(new PreviewPage(picture, CurrentPageSize.Value));
-
- PictureRecorder?.Dispose();
- PictureRecorder = null;
- }
-
- public override void EndDocument() { }
- }
-}
diff --git a/QuestPDF.Previewer/PreviewerControl.cs b/QuestPDF.Previewer/PreviewerControl.cs
deleted file mode 100644
index a0e91a2..0000000
--- a/QuestPDF.Previewer/PreviewerControl.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Input;
-using Avalonia.Media;
-using ReactiveUI;
-
-namespace QuestPDF.Previewer
-{
- class PreviewerControl : Control
- {
- private InteractiveCanvas InteractiveCanvas { get; set; } = new ();
-
- public static readonly StyledProperty> PagesProperty =
- AvaloniaProperty.Register>(nameof(Pages));
-
- public ObservableCollection? Pages
- {
- get => GetValue(PagesProperty);
- set => SetValue(PagesProperty, value);
- }
-
- public static readonly StyledProperty CurrentScrollProperty = AvaloniaProperty.Register(nameof(CurrentScroll));
-
- public float CurrentScroll
- {
- get => GetValue(CurrentScrollProperty);
- set => SetValue(CurrentScrollProperty, value);
- }
-
- public static readonly StyledProperty ScrollViewportSizeProperty = AvaloniaProperty.Register(nameof(ScrollViewportSize));
-
- public float ScrollViewportSize
- {
- get => GetValue(ScrollViewportSizeProperty);
- set => SetValue(ScrollViewportSizeProperty, value);
- }
-
- public PreviewerControl()
- {
- PagesProperty.Changed.Subscribe(x =>
- {
- InteractiveCanvas.Pages = x.NewValue.Value;
- InvalidateVisual();
- });
-
- CurrentScrollProperty.Changed.Subscribe(x =>
- {
- InteractiveCanvas.ScrollPercentY = x.NewValue.Value;
- InvalidateVisual();
- });
-
- ClipToBounds = true;
- }
-
- protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
- {
- base.OnPointerWheelChanged(e);
-
- if ((e.KeyModifiers & KeyModifiers.Control) != 0)
- {
- var scaleFactor = 1 + e.Delta.Y / 10f;
- var point = new Point(Bounds.Center.X, Bounds.Top) - e.GetPosition(this);
-
- InteractiveCanvas.ZoomToPoint((float)point.X, -(float)point.Y, (float)scaleFactor);
- }
-
- if (e.KeyModifiers == KeyModifiers.None)
- {
- var translation = (float)e.Delta.Y * 25;
- InteractiveCanvas.TranslateWithCurrentScale(0, -translation);
- }
-
- InvalidateVisual();
- }
-
- private bool IsMousePressed { get; set; }
- private Vector MousePosition { get; set; }
-
- protected override void OnPointerMoved(PointerEventArgs e)
- {
- base.OnPointerMoved(e);
-
- if (IsMousePressed)
- {
- var currentPosition = e.GetPosition(this);
- var translation = currentPosition - MousePosition;
- InteractiveCanvas.TranslateWithCurrentScale((float)translation.X, -(float)translation.Y);
-
- InvalidateVisual();
- }
-
- MousePosition = e.GetPosition(this);
- }
-
- protected override void OnPointerPressed(PointerPressedEventArgs e)
- {
- base.OnPointerPressed(e);
- IsMousePressed = true;
- }
-
- protected override void OnPointerReleased(PointerReleasedEventArgs e)
- {
- base.OnPointerReleased(e);
- IsMousePressed = false;
- }
-
- public override void Render(DrawingContext context)
- {
- CurrentScroll = InteractiveCanvas.ScrollPercentY;
- ScrollViewportSize = InteractiveCanvas.ScrollViewportSizeY;
-
- InteractiveCanvas.Bounds = new Rect(0, 0, Bounds.Width, Bounds.Height);
-
- context.Custom(InteractiveCanvas);
- base.Render(context);
- }
- }
-}
diff --git a/QuestPDF.Previewer/PreviewerWindow.axaml b/QuestPDF.Previewer/PreviewerWindow.axaml
deleted file mode 100644
index 067e28c..0000000
--- a/QuestPDF.Previewer/PreviewerWindow.axaml
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/QuestPDF.Previewer/PreviewerWindow.axaml.cs b/QuestPDF.Previewer/PreviewerWindow.axaml.cs
deleted file mode 100644
index 1a91a81..0000000
--- a/QuestPDF.Previewer/PreviewerWindow.axaml.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
-
-namespace QuestPDF.Previewer
-{
- class PreviewerWindow : Window
- {
- public PreviewerWindow()
- {
- InitializeComponent();
- }
-
- protected override void OnClosed(EventArgs e)
- {
- (DataContext as PreviewerWindowViewModel)?.UnregisterHotReloadHandler();
- }
-
- private void InitializeComponent()
- {
- AvaloniaXamlLoader.Load(this);
- }
- }
-}
diff --git a/QuestPDF.Previewer/PreviewerWindowViewModel.cs b/QuestPDF.Previewer/PreviewerWindowViewModel.cs
deleted file mode 100644
index 70f94a3..0000000
--- a/QuestPDF.Previewer/PreviewerWindowViewModel.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using QuestPDF.Fluent;
-using System.Diagnostics;
-using ReactiveUI;
-using QuestPDF.Infrastructure;
-using Unit = System.Reactive.Unit;
-using Avalonia.Threading;
-
-namespace QuestPDF.Previewer
-{
- internal class PreviewerWindowViewModel : ReactiveObject
- {
- public DocumentRenderer DocumentRenderer { get; } = new();
-
- private IDocument? _document;
- public IDocument? Document
- {
- get => _document;
- set
- {
- this.RaiseAndSetIfChanged(ref _document, value);
- UpdateDocument(value);
- }
- }
-
- private float _currentScroll;
- public float CurrentScroll
- {
- get => _currentScroll;
- set => this.RaiseAndSetIfChanged(ref _currentScroll, value);
- }
-
- private float _scrollViewportSize;
- public float ScrollViewportSize
- {
- get => _scrollViewportSize;
- set
- {
- this.RaiseAndSetIfChanged(ref _scrollViewportSize, value);
- VerticalScrollbarVisible = value < 1;
- }
- }
-
- private bool _verticalScrollbarVisible;
- public bool VerticalScrollbarVisible
- {
- get => _verticalScrollbarVisible;
- private set => Dispatcher.UIThread.Post(() => this.RaiseAndSetIfChanged(ref _verticalScrollbarVisible, value));
- }
-
- public ReactiveCommand ShowPdfCommand { get; }
- public ReactiveCommand ShowDocumentationCommand { get; }
- public ReactiveCommand SponsorProjectCommand { get; }
-
- public PreviewerWindowViewModel()
- {
- HotReloadManager.UpdateApplicationRequested += InvalidateDocument;
-
- ShowPdfCommand = ReactiveCommand.Create(ShowPdf);
- ShowDocumentationCommand = ReactiveCommand.Create(() => OpenLink("https://www.questpdf.com/documentation/api-reference.html"));
- SponsorProjectCommand = ReactiveCommand.Create(() => OpenLink("https://github.com/sponsors/QuestPDF"));
- }
-
- public void UnregisterHotReloadHandler()
- {
- HotReloadManager.UpdateApplicationRequested -= InvalidateDocument;
- }
-
- private void InvalidateDocument(object? sender, EventArgs e)
- {
- UpdateDocument(Document);
- }
-
- private Task UpdateDocument(IDocument? document)
- {
- return Task.Run(() => DocumentRenderer.UpdateDocument(document));
- }
-
- private void ShowPdf()
- {
- var filePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.pdf");
-
- try
- {
- Document?.GeneratePdf(filePath);
- }
- catch (Exception exception)
- {
- new ExceptionDocument(exception).GeneratePdf(filePath);
- }
-
- OpenLink(filePath);
- }
-
- private void OpenLink(string path)
- {
- var openBrowserProcess = new Process
- {
- StartInfo = new()
- {
- UseShellExecute = true,
- FileName = path
- }
- };
-
- openBrowserProcess.Start();
- }
- }
-}
diff --git a/QuestPDF.Previewer/QuestPDF.Previewer.csproj b/QuestPDF.Previewer/QuestPDF.Previewer.csproj
deleted file mode 100644
index 7c2ca1e..0000000
--- a/QuestPDF.Previewer/QuestPDF.Previewer.csproj
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- net6.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-