From ff95fe287a5e5a56c80b2103885854414b1b86de Mon Sep 17 00:00:00 2001 From: MarcinZiabek Date: Wed, 23 Mar 2022 01:10:15 +0100 Subject: [PATCH] Added scrollbar interactions --- QuestPDF.Previewer.Examples/Program.cs | 6 +- QuestPDF.Previewer/InteractiveCanvas.cs | 66 ++++++++++++++----- QuestPDF.Previewer/PreviewerControl.cs | 35 +++++++++- QuestPDF.Previewer/PreviewerWindow.axaml | 19 ++++-- QuestPDF.Previewer/PreviewerWindow.axaml.cs | 44 ++++++++++++- .../Layouts/PhotoTemplate.cs | 1 - 6 files changed, 137 insertions(+), 34 deletions(-) diff --git a/QuestPDF.Previewer.Examples/Program.cs b/QuestPDF.Previewer.Examples/Program.cs index 7e218a8..fb2d971 100644 --- a/QuestPDF.Previewer.Examples/Program.cs +++ b/QuestPDF.Previewer.Examples/Program.cs @@ -7,9 +7,9 @@ using QuestPDF.ReportSample; using QuestPDF.ReportSample.Layouts; using Colors = QuestPDF.Helpers.Colors; -var model = DataSource.GetReport(); -var report = new StandardReport(model); -report.ShowInPreviewer(); +// var model = DataSource.GetReport(); +// var report = new StandardReport(model); +// report.ShowInPreviewer(); Document .Create(container => diff --git a/QuestPDF.Previewer/InteractiveCanvas.cs b/QuestPDF.Previewer/InteractiveCanvas.cs index cfbaecf..63ca72b 100644 --- a/QuestPDF.Previewer/InteractiveCanvas.cs +++ b/QuestPDF.Previewer/InteractiveCanvas.cs @@ -1,4 +1,5 @@ -using Avalonia; +using System.Diagnostics; +using Avalonia; using Avalonia.Platform; using Avalonia.Rendering.SceneGraph; using Avalonia.Skia; @@ -13,17 +14,45 @@ class InteractiveCanvas : ICustomDrawOperation private float Width => (float)Bounds.Width; private float Height => (float)Bounds.Height; - + public float Scale { get; private set; } = 1; - public float TranslateX { get; private set; } - public float TranslateY { get; private set; } + 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 = 50f; + public float TotalHeight => Pages.Sum(x => x.Size.Height) + (Pages.Count - 1) * PageSpacing; + public float MaxWidth => Pages.Max(x => x.Size.Width); + public float MaxTranslateY => -(Height / 2 - SafeZone) / Scale; + public float MinTranslateY => (Height / 2 - SafeZone) / Scale - TotalHeight; + + public float ScrollPercentY + { + get + { + return Math.Clamp(1 - (TranslateY - MinTranslateY) / (MaxTranslateY - MinTranslateY), 0, 1); + } + set + { + TranslateY = (1 - value) * (MaxTranslateY - MinTranslateY) + MinTranslateY; + } + } + + public float ScrollViewportSizeY + { + get + { + if (TotalHeight * Scale < Height) + return 1; + + return Math.Clamp(Height / Scale / (MaxTranslateY - MinTranslateY), 0, 1); + } + } + #region transformations private void LimitScale() @@ -34,26 +63,27 @@ class InteractiveCanvas : ICustomDrawOperation private void LimitTranslate() { - var totalHeight = Pages.Sum(x => x.Size.Height) + (Pages.Count - 1) * PageSpacing; - var maxWidth = Pages.Max(x => x.Size.Width); - - var maxTranslateY = - (Height / 2 - SafeZone) / Scale; - var minTranslateY = (Height / 2 - SafeZone) / Scale - totalHeight; - - TranslateY = Math.Min(TranslateY, maxTranslateY); - TranslateY = Math.Max(TranslateY, minTranslateY); - - if (maxWidth < Width / Scale) + if (TotalHeight * Scale > Height) { - TranslateX = 0; + TranslateY = Math.Min(TranslateY, MaxTranslateY); + TranslateY = Math.Max(TranslateY, MinTranslateY); } else { - var maxTranslateX = (Width / 2 - SafeZone) / Scale - maxWidth / 2; - + TranslateY = -TotalHeight / 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) diff --git a/QuestPDF.Previewer/PreviewerControl.cs b/QuestPDF.Previewer/PreviewerControl.cs index 24b501b..8eb05a3 100644 --- a/QuestPDF.Previewer/PreviewerControl.cs +++ b/QuestPDF.Previewer/PreviewerControl.cs @@ -1,17 +1,19 @@ 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 { - public static readonly StyledProperty?> PagesProperty = + private InteractiveCanvas InteractiveCanvas { get; set; } = new (); + + public static readonly StyledProperty> PagesProperty = AvaloniaProperty.Register>(nameof(Pages)); - - private InteractiveCanvas InteractiveCanvas { get; set; } = new InteractiveCanvas(); public ObservableCollection? Pages { @@ -19,14 +21,38 @@ namespace QuestPDF.Previewer 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() { + ScrollViewportSize = 0.5f; + PagesProperty.Changed.Subscribe(p => { InteractiveCanvas.Pages = Pages; InvalidateVisual(); }); + CurrentScrollProperty.Changed.Subscribe(p => + { + InteractiveCanvas.ScrollPercentY = CurrentScroll; + InvalidateVisual(); + }); + ClipToBounds = true; } @@ -84,6 +110,9 @@ namespace QuestPDF.Previewer 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); diff --git a/QuestPDF.Previewer/PreviewerWindow.axaml b/QuestPDF.Previewer/PreviewerWindow.axaml index 9e362d6..34a2a14 100644 --- a/QuestPDF.Previewer/PreviewerWindow.axaml +++ b/QuestPDF.Previewer/PreviewerWindow.axaml @@ -19,7 +19,6 @@ - @@ -29,15 +28,23 @@ + TextAlignment="Center" Text="QuestPDF Document Preview" FontSize="14" Foreground="#DFFF" FontWeight="Regular" IsHitTestVisible="False" /> - - - - + + + \ No newline at end of file diff --git a/QuestPDF.Previewer/PreviewerWindow.axaml.cs b/QuestPDF.Previewer/PreviewerWindow.axaml.cs index 92eb547..27de11e 100644 --- a/QuestPDF.Previewer/PreviewerWindow.axaml.cs +++ b/QuestPDF.Previewer/PreviewerWindow.axaml.cs @@ -1,8 +1,13 @@ -using Avalonia; +using System.Diagnostics; +using Avalonia; using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.Threading; +using QuestPDF.Helpers; using QuestPDF.Infrastructure; +using ReactiveUI; namespace QuestPDF.Previewer { @@ -18,11 +23,44 @@ namespace QuestPDF.Previewer get => GetValue(DocumentProperty); set => SetValue(DocumentProperty, 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 static readonly StyledProperty VerticalScrollbarVisibleProperty = AvaloniaProperty.Register(nameof(VerticalScrollbarVisible)); + + public bool VerticalScrollbarVisible + { + get => GetValue(VerticalScrollbarVisibleProperty); + set => SetValue(VerticalScrollbarVisibleProperty, value); + } + + public PreviewerWindow() { InitializeComponent(); - // + + ScrollViewportSizeProperty.Changed.Subscribe(_ => + { + VerticalScrollbarVisible = ScrollViewportSize < 1; + Debug.WriteLine($"Scrollbar visible: {VerticalScrollbarVisible}"); + }); + // this.FindControl