Merge pull request #157 from Bebo-Maker/previewer
Previewer - ViewModel for PreviewerWindow
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.ReactiveUI;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuestPDF.Previewer
|
||||
@@ -24,7 +25,10 @@ namespace QuestPDF.Previewer
|
||||
{
|
||||
desktop.MainWindow = new PreviewerWindow()
|
||||
{
|
||||
Document = document,
|
||||
DataContext = new PreviewerWindowViewModel()
|
||||
{
|
||||
Document = document,
|
||||
}
|
||||
};
|
||||
|
||||
desktop.MainWindow.Show();
|
||||
@@ -39,6 +43,7 @@ namespace QuestPDF.Previewer
|
||||
Document = document,
|
||||
})
|
||||
.UsePlatformDetect()
|
||||
.UseReactiveUI()
|
||||
.StartWithClassicDesktopLifetime(Array.Empty<string>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,10 @@ namespace QuestPDF.Previewer
|
||||
{
|
||||
desktop.MainWindow = new PreviewerWindow()
|
||||
{
|
||||
Document = Document
|
||||
DataContext = new PreviewerWindowViewModel()
|
||||
{
|
||||
Document = Document,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
Background="#666"
|
||||
Icon="/Images/Logo.png"
|
||||
UseLayoutRounding="True"
|
||||
x:Name="Window"
|
||||
Title="QuestPDF Document Preview">
|
||||
|
||||
<Panel>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -33,14 +31,14 @@
|
||||
<previewer:PreviewerControl Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
CurrentScroll="{Binding #Window.CurrentScroll, Mode=TwoWay}"
|
||||
ScrollViewportSize="{Binding #Window.ScrollViewportSize, Mode=OneWayToSource}"
|
||||
Pages="{Binding #Window.DocumentRenderer.Pages, Mode=OneWay}" />
|
||||
CurrentScroll="{Binding CurrentScroll, Mode=TwoWay}"
|
||||
ScrollViewportSize="{Binding ScrollViewportSize, Mode=OneWayToSource}"
|
||||
Pages="{Binding DocumentRenderer.Pages, Mode=OneWay}" />
|
||||
|
||||
<Button Grid.Row="1" Grid.Column="0"
|
||||
VerticalAlignment="Bottom" HorizontalAlignment="Left"
|
||||
Margin="32" Padding="10" CornerRadius="100"
|
||||
Click="ShowPDF"
|
||||
Command="{Binding ShowPdfCommand, Mode=OneTime}"
|
||||
ToolTip.Tip="Generates PDF file and shows it in the default browser. Useful for testing compatibility and interactive links.">
|
||||
<Viewbox Width="24" Height="24">
|
||||
<Canvas Width="24" Height="24">
|
||||
@@ -53,9 +51,9 @@
|
||||
Orientation="Vertical"
|
||||
AllowAutoHide="False"
|
||||
Minimum="0" Maximum="1"
|
||||
IsVisible="{Binding #Window.VerticalScrollbarVisible, Mode=OneWay}"
|
||||
Value="{Binding #Window.CurrentScroll, Mode=TwoWay}"
|
||||
ViewportSize="{Binding #Window.ScrollViewportSize, Mode=OneWay}"></ScrollBar>
|
||||
IsVisible="{Binding VerticalScrollbarVisible, Mode=OneWay}"
|
||||
Value="{Binding CurrentScroll, Mode=TwoWay}"
|
||||
ViewportSize="{Binding ScrollViewportSize, Mode=OneWay}"></ScrollBar>
|
||||
</Grid>
|
||||
</Panel>
|
||||
</Window>
|
||||
@@ -1,112 +1,23 @@
|
||||
using System.Diagnostics;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Threading;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace QuestPDF.Previewer
|
||||
{
|
||||
class PreviewerWindow : Window
|
||||
{
|
||||
public DocumentRenderer DocumentRenderer { get; } = new();
|
||||
|
||||
public static readonly StyledProperty<IDocument?> DocumentProperty =
|
||||
AvaloniaProperty.Register<PreviewerWindow, IDocument?>(nameof(Document));
|
||||
|
||||
public IDocument? Document
|
||||
{
|
||||
get => GetValue(DocumentProperty);
|
||||
set => SetValue(DocumentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<float> CurrentScrollProperty = AvaloniaProperty.Register<PreviewerWindow, float>(nameof(CurrentScroll));
|
||||
|
||||
public float CurrentScroll
|
||||
{
|
||||
get => GetValue(CurrentScrollProperty);
|
||||
set => SetValue(CurrentScrollProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<float> ScrollViewportSizeProperty = AvaloniaProperty.Register<PreviewerWindow, float>(nameof(ScrollViewportSize));
|
||||
|
||||
public float ScrollViewportSize
|
||||
{
|
||||
get => GetValue(ScrollViewportSizeProperty);
|
||||
set => SetValue(ScrollViewportSizeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> VerticalScrollbarVisibleProperty = AvaloniaProperty.Register<PreviewerWindow, bool>(nameof(VerticalScrollbarVisible));
|
||||
|
||||
public bool VerticalScrollbarVisible
|
||||
{
|
||||
get => GetValue(VerticalScrollbarVisibleProperty);
|
||||
set => SetValue(VerticalScrollbarVisibleProperty, value);
|
||||
}
|
||||
|
||||
public PreviewerWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
ScrollViewportSizeProperty.Changed
|
||||
.Subscribe(e => Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
VerticalScrollbarVisible = e.NewValue.Value < 1;
|
||||
}));
|
||||
|
||||
DocumentProperty.Changed.Subscribe(v => Task.Run(() => DocumentRenderer.UpdateDocument(v.NewValue.Value)));
|
||||
HotReloadManager.UpdateApplicationRequested += InvalidatePreview;
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
HotReloadManager.UpdateApplicationRequested -= InvalidatePreview;
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
private void InvalidatePreview(object? sender, EventArgs e) => InvalidatePreview();
|
||||
private void InvalidatePreview()
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
var document = Document;
|
||||
_ = Task.Run(() => DocumentRenderer.UpdateDocument(document));
|
||||
});
|
||||
(DataContext as PreviewerWindowViewModel)?.UnregisterHotReloadHandler();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void ShowPDF(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var path = Path.GetTempPath() + ".pdf";
|
||||
|
||||
try
|
||||
{
|
||||
DocumentRenderer.Document?.GeneratePdf(path);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
new ExceptionDocument(exception).GeneratePdf(path);
|
||||
}
|
||||
|
||||
var openBrowserProcess = new Process
|
||||
{
|
||||
StartInfo = new()
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = path
|
||||
}
|
||||
};
|
||||
|
||||
openBrowserProcess.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
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<Unit, Unit> ShowPdfCommand { get; }
|
||||
|
||||
public PreviewerWindowViewModel()
|
||||
{
|
||||
HotReloadManager.UpdateApplicationRequested += InvalidateDocument;
|
||||
ShowPdfCommand = ReactiveCommand.Create(ShowPdf);
|
||||
}
|
||||
|
||||
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 path = Path.Combine(Path.GetTempPath(), ".pdf");
|
||||
|
||||
try
|
||||
{
|
||||
Document?.GeneratePdf(path);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
new ExceptionDocument(exception).GeneratePdf(path);
|
||||
}
|
||||
|
||||
var openBrowserProcess = new Process
|
||||
{
|
||||
StartInfo = new()
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = path
|
||||
}
|
||||
};
|
||||
|
||||
openBrowserProcess.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user