Added DescriptionDisplayDialog and ImageDisplayDialog
This commit is contained in:
parent
1578be2520
commit
ad6b86fcb4
@ -0,0 +1,19 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="540" d:DesignHeight="140"
|
||||||
|
x:Class="LibationWinForms.AvaloniaUI.Views.Dialogs.DescriptionDisplayDialog"
|
||||||
|
SystemDecorations="None"
|
||||||
|
Title="DescriptionDisplay">
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
Text="{Binding DescriptionText}"
|
||||||
|
IsReadOnly="True"
|
||||||
|
MinWidth="540"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Name="DescriptionTextBox"
|
||||||
|
CaretBrush="{StaticResource SystemControlTransparentBrush}"
|
||||||
|
LostFocus="DescriptionTextBox_LostFocus" />
|
||||||
|
|
||||||
|
</Window>
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||||
|
{
|
||||||
|
public partial class DescriptionDisplayDialog : Window
|
||||||
|
{
|
||||||
|
public Point SpawnLocation { get; set; }
|
||||||
|
public string DescriptionText { get; init; }
|
||||||
|
public DescriptionDisplayDialog()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
#if DEBUG
|
||||||
|
this.AttachDevTools();
|
||||||
|
#endif
|
||||||
|
DescriptionTextBox = this.FindControl<TextBox>(nameof(DescriptionTextBox));
|
||||||
|
this.Activated += DescriptionDisplay_Activated;
|
||||||
|
Opened += DescriptionDisplay_Opened;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DescriptionDisplay_Opened(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
DescriptionTextBox.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DescriptionDisplay_Activated(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
DataContext = this;
|
||||||
|
var workingHeight = this.Screens.Primary.WorkingArea.Height;
|
||||||
|
DescriptionTextBox.Measure(new Size(DescriptionTextBox.MinWidth, workingHeight * 0.8));
|
||||||
|
|
||||||
|
this.Width = DescriptionTextBox.DesiredSize.Width;
|
||||||
|
this.Height = DescriptionTextBox.DesiredSize.Height;
|
||||||
|
this.MinWidth = this.Width;
|
||||||
|
this.MaxWidth = this.Width;
|
||||||
|
this.MinHeight = this.Height;
|
||||||
|
this.MaxHeight = this.Height;
|
||||||
|
|
||||||
|
DescriptionTextBox.Width = this.Width;
|
||||||
|
DescriptionTextBox.Height = this.Height;
|
||||||
|
DescriptionTextBox.MinWidth = this.Width;
|
||||||
|
DescriptionTextBox.MaxWidth = this.Width;
|
||||||
|
DescriptionTextBox.MinHeight = this.Height;
|
||||||
|
DescriptionTextBox.MaxHeight = this.Height;
|
||||||
|
|
||||||
|
this.Position = new PixelPoint((int)SpawnLocation.X, (int)Math.Min(SpawnLocation.Y, (double)workingHeight - DescriptionTextBox.DesiredSize.Height));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DescriptionTextBox_LostFocus(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="500"
|
||||||
|
x:Class="LibationWinForms.AvaloniaUI.Views.Dialogs.ImageDisplayDialog"
|
||||||
|
MinWidth="500" MinHeight="500"
|
||||||
|
Title="Cover"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
Icon="/AvaloniaUI/Assets/libation.ico">
|
||||||
|
|
||||||
|
<Image Stretch="Uniform" Source="{Binding CoverImage}">
|
||||||
|
<Image.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<MenuItem
|
||||||
|
Click="SaveImage_Clicked"
|
||||||
|
Header="Save Picture to File"/>
|
||||||
|
</ContextMenu>
|
||||||
|
</Image.ContextMenu>
|
||||||
|
</Image>
|
||||||
|
</Window>
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
|
using Avalonia.Platform;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||||
|
{
|
||||||
|
public partial class ImageDisplayDialog : DialogWindow, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public string PictureFileName { get; set; }
|
||||||
|
public string BookSaveDirectory { get; set; }
|
||||||
|
|
||||||
|
private byte[] _coverBytes;
|
||||||
|
public byte[] CoverBytes
|
||||||
|
{
|
||||||
|
get => _coverBytes;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_coverBytes = value;
|
||||||
|
var ms = new MemoryStream(_coverBytes);
|
||||||
|
ms.Position = 0;
|
||||||
|
_bitmapHolder.CoverImage = new Bitmap(ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private readonly BitmapHolder _bitmapHolder = new BitmapHolder();
|
||||||
|
|
||||||
|
|
||||||
|
public ImageDisplayDialog()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = _bitmapHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void SaveImage_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
SaveFileDialog saveFileDialog = new();
|
||||||
|
saveFileDialog.Filters.Add(new FileDialogFilter { Name = "Jpeg", Extensions = new System.Collections.Generic.List<string>() { "jpg" } });
|
||||||
|
saveFileDialog.Directory = Directory.Exists(BookSaveDirectory) ? BookSaveDirectory : Path.GetDirectoryName(BookSaveDirectory);
|
||||||
|
saveFileDialog.InitialFileName = PictureFileName;
|
||||||
|
|
||||||
|
var fileName = await saveFileDialog.ShowAsync(this);
|
||||||
|
|
||||||
|
if (fileName is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.WriteAllBytes(fileName, CoverBytes);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, $"Failed to save picture to {fileName}");
|
||||||
|
await MessageBox.Show(this, $"An error was encountered while trying to save the picture\r\n\r\n{ex.Message}", "Failed to save picture", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BitmapHolder : ViewModels.ViewModelBase
|
||||||
|
{
|
||||||
|
private Bitmap _coverImage;
|
||||||
|
public Bitmap CoverImage
|
||||||
|
{
|
||||||
|
get => _coverImage;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref _coverImage, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,7 +18,7 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
public event EventHandler<LibraryBook> LiberateClicked;
|
public event EventHandler<LibraryBook> LiberateClicked;
|
||||||
|
|
||||||
private ProductsDisplayViewModel _viewModel => DataContext as ProductsDisplayViewModel;
|
private ProductsDisplayViewModel _viewModel => DataContext as ProductsDisplayViewModel;
|
||||||
private GridView.ImageDisplay imageDisplay;
|
ImageDisplayDialog imageDisplayDialog;
|
||||||
|
|
||||||
public ProductsDisplay2()
|
public ProductsDisplay2()
|
||||||
{
|
{
|
||||||
@ -211,12 +211,18 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
if (sender is not Image tblock || tblock.DataContext is not GridEntry2 gEntry)
|
if (sender is not Image tblock || tblock.DataContext is not GridEntry2 gEntry)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
if (imageDisplayDialog is null || !imageDisplayDialog.IsVisible)
|
||||||
|
{
|
||||||
|
imageDisplayDialog = new ImageDisplayDialog();
|
||||||
|
}
|
||||||
|
|
||||||
var picDef = new PictureDefinition(gEntry.LibraryBook.Book.PictureLarge ?? gEntry.LibraryBook.Book.PictureId, PictureSize.Native);
|
var picDef = new PictureDefinition(gEntry.LibraryBook.Book.PictureLarge ?? gEntry.LibraryBook.Book.PictureId, PictureSize.Native);
|
||||||
|
|
||||||
void PictureCached(object sender, PictureCachedEventArgs e)
|
void PictureCached(object sender, PictureCachedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Definition.PictureId == picDef.PictureId)
|
if (e.Definition.PictureId == picDef.PictureId)
|
||||||
imageDisplay.CoverPicture = e.Picture;
|
imageDisplayDialog.CoverBytes = e.Picture;
|
||||||
|
|
||||||
PictureStorage.PictureCached -= PictureCached;
|
PictureStorage.PictureCached -= PictureCached;
|
||||||
}
|
}
|
||||||
@ -224,24 +230,20 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
PictureStorage.PictureCached += PictureCached;
|
PictureStorage.PictureCached += PictureCached;
|
||||||
(bool isDefault, byte[] initialImageBts) = PictureStorage.GetPicture(picDef);
|
(bool isDefault, byte[] initialImageBts) = PictureStorage.GetPicture(picDef);
|
||||||
|
|
||||||
|
|
||||||
var windowTitle = $"{gEntry.Title} - Cover";
|
var windowTitle = $"{gEntry.Title} - Cover";
|
||||||
|
|
||||||
if (imageDisplay is null || imageDisplay.IsDisposed || !imageDisplay.Visible)
|
|
||||||
{
|
|
||||||
imageDisplay = new GridView.ImageDisplay();
|
|
||||||
imageDisplay.RestoreSizeAndLocation(Configuration.Instance);
|
|
||||||
imageDisplay.FormClosed += (_, _) => imageDisplay.SaveSizeAndLocation(Configuration.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
imageDisplay.BookSaveDirectory = AudibleFileStorage.Audio.GetDestinationDirectory(gEntry.LibraryBook);
|
imageDisplayDialog.BookSaveDirectory = AudibleFileStorage.Audio.GetDestinationDirectory(gEntry.LibraryBook);
|
||||||
imageDisplay.PictureFileName = System.IO.Path.GetFileName(AudibleFileStorage.Audio.GetBooksDirectoryFilename(gEntry.LibraryBook, ".jpg"));
|
imageDisplayDialog.PictureFileName = System.IO.Path.GetFileName(AudibleFileStorage.Audio.GetBooksDirectoryFilename(gEntry.LibraryBook, ".jpg"));
|
||||||
imageDisplay.Text = windowTitle;
|
imageDisplayDialog.Title = windowTitle;
|
||||||
imageDisplay.CoverPicture = initialImageBts;
|
imageDisplayDialog.CoverBytes = initialImageBts;
|
||||||
|
|
||||||
if (!isDefault)
|
if (!isDefault)
|
||||||
PictureStorage.PictureCached -= PictureCached;
|
PictureStorage.PictureCached -= PictureCached;
|
||||||
|
|
||||||
if (!imageDisplay.Visible)
|
if (!imageDisplayDialog.IsVisible)
|
||||||
imageDisplay.Show(null);
|
imageDisplayDialog.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Description_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
public void Description_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
@ -249,11 +251,10 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
if (sender is TextBlock tblock && tblock.DataContext is GridEntry2 gEntry)
|
if (sender is TextBlock tblock && tblock.DataContext is GridEntry2 gEntry)
|
||||||
{
|
{
|
||||||
var pt = tblock.Parent.PointToScreen(tblock.Parent.Bounds.TopRight);
|
var pt = tblock.Parent.PointToScreen(tblock.Parent.Bounds.TopRight);
|
||||||
var displayWindow = new GridView.DescriptionDisplay
|
var displayWindow = new DescriptionDisplayDialog
|
||||||
{
|
{
|
||||||
SpawnLocation = new System.Drawing.Point(pt.X, pt.Y),
|
SpawnLocation = new Point(pt.X, pt.Y),
|
||||||
DescriptionText = gEntry.LongDescription,
|
DescriptionText = gEntry.LongDescription,
|
||||||
BorderThickness = 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void CloseWindow(object o, DataGridRowEventArgs e)
|
void CloseWindow(object o, DataGridRowEventArgs e)
|
||||||
@ -261,7 +262,7 @@ namespace LibationWinForms.AvaloniaUI.Views
|
|||||||
displayWindow.Close();
|
displayWindow.Close();
|
||||||
}
|
}
|
||||||
productsGrid.LoadingRow += CloseWindow;
|
productsGrid.LoadingRow += CloseWindow;
|
||||||
displayWindow.FormClosed += (_, _) =>
|
displayWindow.Closing += (_, _) =>
|
||||||
{
|
{
|
||||||
productsGrid.LoadingRow -= CloseWindow;
|
productsGrid.LoadingRow -= CloseWindow;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -109,6 +109,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Update="AvaloniaUI\Views\Dialogs\DescriptionDisplayDialog.axaml.cs">
|
||||||
|
<DependentUpon>DescriptionDisplayDialog.axaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Update="AvaloniaUI\Views\Dialogs\EditQuickFilters.axaml.cs">
|
<Compile Update="AvaloniaUI\Views\Dialogs\EditQuickFilters.axaml.cs">
|
||||||
<DependentUpon>EditQuickFilters.axaml</DependentUpon>
|
<DependentUpon>EditQuickFilters.axaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -118,6 +121,9 @@
|
|||||||
<Compile Update="AvaloniaUI\Views\Dialogs\SearchSyntaxDialog.axaml.cs">
|
<Compile Update="AvaloniaUI\Views\Dialogs\SearchSyntaxDialog.axaml.cs">
|
||||||
<DependentUpon>SearchSyntaxDialog.axaml</DependentUpon>
|
<DependentUpon>SearchSyntaxDialog.axaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="AvaloniaUI\Views\Dialogs\ImageDisplayDialog.axaml.cs">
|
||||||
|
<DependentUpon>ImageDisplayDialog.axaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Update="Properties\Resources.Designer.cs">
|
<Compile Update="Properties\Resources.Designer.cs">
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user