From 689f67732231af29705fe8bdecf038acae159049 Mon Sep 17 00:00:00 2001 From: Ben Olden-Cooligan Date: Fri, 12 Jan 2024 23:24:20 -0800 Subject: [PATCH] ShowPageNumbers fixes --- .../EtoForms/WinForms/WinFormsListView.cs | 118 +++++++++++------- NAPS2.Lib/EtoForms/Ui/SettingsForm.cs | 6 +- .../EtoForms/Widgets/ImageListViewBehavior.cs | 6 +- .../EtoForms/Widgets/ListViewBehavior.cs | 2 +- 4 files changed, 85 insertions(+), 47 deletions(-) diff --git a/NAPS2.Lib.WinForms/EtoForms/WinForms/WinFormsListView.cs b/NAPS2.Lib.WinForms/EtoForms/WinForms/WinFormsListView.cs index dd2260735a..7a6d6ac2ea 100644 --- a/NAPS2.Lib.WinForms/EtoForms/WinForms/WinFormsListView.cs +++ b/NAPS2.Lib.WinForms/EtoForms/WinForms/WinFormsListView.cs @@ -10,12 +10,14 @@ namespace NAPS2.EtoForms.WinForms; public class WinFormsListView : IListView where T : notnull { - private const int TextPadding = 6; - private const int SelectionPadding = 3; private static readonly Pen DefaultPen = new(Color.Black, 1); - private static readonly SolidBrush OutlineBrush = new(Color.FromArgb(0x60, 0xa0, 0xe8)); - private static readonly SolidBrush SelectionBrush = new(Color.FromArgb(0xcc, 0xe8, 0xff)); - private static readonly StringFormat LabelFormat = new() { Alignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter }; + private static readonly Pen BasicSelectionPen = new(Color.FromArgb(0x60, 0xa0, 0xe8), 3); + private const int PageNumberTextPadding = 6; + private const int PageNumberSelectionPadding = 3; + private static readonly SolidBrush PageNumberOutlineBrush = new(Color.FromArgb(0x60, 0xa0, 0xe8)); + private static readonly SolidBrush PageNumberSelectionBrush = new(Color.FromArgb(0xcc, 0xe8, 0xff)); + private static readonly StringFormat PageNumberLabelFormat = new() + { Alignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter }; private readonly ListView _view; private readonly Eto.Forms.Control _viewEtoControl; @@ -80,64 +82,92 @@ public WinFormsListView(ListViewBehavior behavior) private void CustomRenderItem(object? sender, DrawListViewItemEventArgs e) { var image = ImageList.Get(e.Item); - string? label = null; - SizeF textSize = SizeF.Empty; - int textOffset = 0; if (_behavior.ShowPageNumbers) { - label = $"{e.ItemIndex + 1} / {_view.Items.Count}"; - textSize = e.Graphics.MeasureString(label, _view.Font); - textOffset = (int)(textSize.Height + TextPadding); - } + // When page numbers are shown, we use a completely different drawing path, as we need to offset the image + // to have room for the page numbers, and the selection rectangle has a completely different style to + // encompass the page numbers too. + string label = $"{e.ItemIndex + 1} / {_view.Items.Count}"; + SizeF textSize = e.Graphics.MeasureString(label, _view.Font); + int textOffset = (int) (textSize.Height + PageNumberTextPadding); - float scaleHeight = (float)(ImageSize - textOffset) / image.Height; - float scaleWidth = (float)ImageSize / image.Width; + float scaleHeight = (float) (ImageSize - textOffset) / image.Height; + float scaleWidth = (float) ImageSize / image.Width; - float scale = Math.Min(scaleWidth, scaleHeight); - int height = (int)Math.Round(image.Height * scale); - int width = (int)Math.Round(image.Width * scale); + float scale = Math.Min(scaleWidth, scaleHeight); + int height = (int) Math.Round(image.Height * scale); + int width = (int) Math.Round(image.Width * scale); - var x = e.Bounds.Left + (e.Bounds.Width - width) / 2; - var y = e.Bounds.Top + (e.Bounds.Height - height - textOffset) / 2; + var x = e.Bounds.Left + (e.Bounds.Width - width) / 2; + var y = e.Bounds.Top + (e.Bounds.Height - height - textOffset) / 2; - if (e.Item.Selected) - { - Size intTextSize = Size.Ceiling(textSize); + // Draw selection rectangle/background + if (e.Item.Selected) + { + Size intTextSize = Size.Ceiling(textSize); - int selectionWidth = Math.Max(width, intTextSize.Width); - int selectionHeight = height + TextPadding + intTextSize.Height; + int selectionWidth = Math.Max(width, intTextSize.Width); + int selectionHeight = height + PageNumberTextPadding + intTextSize.Height; - var selectionX = e.Bounds.Left + (e.Bounds.Width - width) / 2; + var selectionX = e.Bounds.Left + (e.Bounds.Width - width) / 2; - var selectionRect = new Rectangle(selectionX, y, selectionWidth, selectionHeight); - selectionRect.Inflate(SelectionPadding, SelectionPadding); + var selectionRect = new Rectangle(selectionX, y, selectionWidth, selectionHeight); + selectionRect.Inflate(PageNumberSelectionPadding, PageNumberSelectionPadding); - var outlineRect = selectionRect; - outlineRect.Inflate(1, 1); - e.Graphics.FillRectangle(OutlineBrush, outlineRect); + var outlineRect = selectionRect; + outlineRect.Inflate(1, 1); + e.Graphics.FillRectangle(PageNumberOutlineBrush, outlineRect); - e.Graphics.FillRectangle(SelectionBrush, selectionRect); - } + e.Graphics.FillRectangle(PageNumberSelectionBrush, selectionRect); + } + + // Draw image + e.Graphics.DrawImage(image, new Rectangle(x, y, width, height)); - e.Graphics.DrawImage(image, new Rectangle(x, y, width, height)); - if (!string.IsNullOrEmpty(label)) - { // Draw the text below the image var drawBrush = Brushes.Black; - - float x1 = x + width / 2; - float y1 = y + height + TextPadding; - + float x1 = x + width / 2f; + float y1 = y + height + PageNumberTextPadding; RectangleF labelRect = new(x1, y1, 0, textSize.Height); - float maxLabelWidth = Math.Min(textSize.Width, e.Bounds.Width - 2 * TextPadding); + float maxLabelWidth = Math.Min(textSize.Width, e.Bounds.Width - 2 * PageNumberTextPadding); labelRect.Inflate(maxLabelWidth / 2, 0); + e.Graphics.DrawString(label, _view.Font, drawBrush, labelRect, PageNumberLabelFormat); - e.Graphics.DrawString(label, _view.Font, drawBrush, labelRect, LabelFormat); + // Draw unselected border + if (!e.Item.Selected) + { + e.Graphics.DrawRectangle(DefaultPen, x - 1, y - 1, width + 1, height + 1); + } } - // Draw border - if (!e.Item.Selected) + else { - e.Graphics.DrawRectangle(DefaultPen, x - 1, y - 1, width + 1, height + 1); + // The basic no-page-numbers drawing path + int width, height; + if (image.Width > image.Height) + { + width = ImageSize; + height = (int) Math.Round(width * (image.Height / (double) image.Width)); + } + else + { + height = ImageSize; + width = (int) Math.Round(height * (image.Width / (double) image.Height)); + } + var x = e.Bounds.Left + (e.Bounds.Width - width) / 2; + var y = e.Bounds.Top + (e.Bounds.Height - height) / 2; + + // Draw image + e.Graphics.DrawImage(image, new Rectangle(x, y, width, height)); + + // Draw border + if (e.Item.Selected) + { + e.Graphics.DrawRectangle(BasicSelectionPen, x - 2, y - 2, width + 3, height + 3); + } + else + { + e.Graphics.DrawRectangle(DefaultPen, x, y, width, height); + } } } diff --git a/NAPS2.Lib/EtoForms/Ui/SettingsForm.cs b/NAPS2.Lib/EtoForms/Ui/SettingsForm.cs index f4041a60b9..e2caa56244 100644 --- a/NAPS2.Lib/EtoForms/Ui/SettingsForm.cs +++ b/NAPS2.Lib/EtoForms/Ui/SettingsForm.cs @@ -7,6 +7,7 @@ namespace NAPS2.EtoForms.Ui; internal class SettingsForm : EtoDialogBase { + private readonly DesktopFormProvider _desktopFormProvider; private readonly CheckBox _scanChangesDefaultProfile = C.CheckBox(UiStrings.ScanChangesDefaultProfile); private readonly CheckBox _showProfilesToolbar = C.CheckBox(UiStrings.ShowProfilesToolbar); private readonly CheckBox _showPageNumbers = C.CheckBox(UiStrings.ShowPageNumbers); @@ -18,8 +19,10 @@ internal class SettingsForm : EtoDialogBase private Command _emailSettingsCommand; private readonly Button _restoreDefaults = new() { Text = UiStrings.RestoreDefaults }; - public SettingsForm(Naps2Config config, DesktopSubFormController desktopSubFormController) : base(config) + public SettingsForm(Naps2Config config, DesktopSubFormController desktopSubFormController, + DesktopFormProvider desktopFormProvider) : base(config) { + _desktopFormProvider = desktopFormProvider; UpdateValues(Config); _restoreDefaults.Click += RestoreDefaults_Click; @@ -108,6 +111,7 @@ private void Save() transact.Set(c => c.DeleteAfterSaving, _clearAfterSaving.IsChecked()); transact.Set(c => c.SingleInstance, _singleInstance.IsChecked()); transact.Commit(); + _desktopFormProvider.DesktopForm.Invalidate(); } private void RestoreDefaults_Click(object? sender, EventArgs e) diff --git a/NAPS2.Lib/EtoForms/Widgets/ImageListViewBehavior.cs b/NAPS2.Lib/EtoForms/Widgets/ImageListViewBehavior.cs index cac6dbfdea..7cfe359398 100644 --- a/NAPS2.Lib/EtoForms/Widgets/ImageListViewBehavior.cs +++ b/NAPS2.Lib/EtoForms/Widgets/ImageListViewBehavior.cs @@ -8,18 +8,22 @@ namespace NAPS2.EtoForms.Widgets; public class ImageListViewBehavior : ListViewBehavior { private readonly UiThumbnailProvider _thumbnailProvider; + private readonly Naps2Config _config; private readonly ImageTransfer _imageTransfer = new(); public ImageListViewBehavior(UiThumbnailProvider thumbnailProvider, ColorScheme colorScheme, Naps2Config config) : base(colorScheme) { _thumbnailProvider = thumbnailProvider; + _config = config; MultiSelect = true; ShowLabels = false; ScrollOnDrag = true; UseHandCursor = true; - ShowPageNumbers = config.Get(c => c.ShowPageNumbers); } + + public override bool ShowPageNumbers => _config.Get(c => c.ShowPageNumbers); + public override Image GetImage(UiImage item, int imageSize) { return _thumbnailProvider.GetThumbnail(item, imageSize).ToEtoImage(); diff --git a/NAPS2.Lib/EtoForms/Widgets/ListViewBehavior.cs b/NAPS2.Lib/EtoForms/Widgets/ListViewBehavior.cs index b4bd94cce9..e3b3e97582 100644 --- a/NAPS2.Lib/EtoForms/Widgets/ListViewBehavior.cs +++ b/NAPS2.Lib/EtoForms/Widgets/ListViewBehavior.cs @@ -16,7 +16,7 @@ protected ListViewBehavior(ColorScheme colorScheme) public bool ShowLabels { get; protected set; } - public bool ShowPageNumbers { get; protected set; } + public virtual bool ShowPageNumbers => false; public bool ScrollOnDrag { get; protected set; }