WinForms: Checkbox list and other fixes

This commit is contained in:
Ben Olden-Cooligan 2022-11-12 10:33:08 -08:00
parent 8cc47e5fbe
commit 37bcb6770a
6 changed files with 74 additions and 46 deletions

View File

@ -42,7 +42,7 @@ public class MacIconProvider : IIconProvider
_defaultIconProvider = defaultIconProvider; _defaultIconProvider = defaultIconProvider;
} }
public Image GetIcon(string name) public Image? GetIcon(string name)
{ {
// TODO: Fix names (like "save") that have no non-mac image and will break on macOS 10.15 // TODO: Fix names (like "save") that have no non-mac image and will break on macOS 10.15
if (OperatingSystem.IsMacOSVersionAtLeast(11) && IconMap.ContainsKey(name)) if (OperatingSystem.IsMacOSVersionAtLeast(11) && IconMap.ContainsKey(name))

View File

@ -56,6 +56,12 @@ public class WinFormsDesktopForm : DesktopForm
NativeListView.Focus(); NativeListView.Focus();
} }
protected override void OnShown(EventArgs e)
{
_toolbarFormatter.RelayoutToolbar(_toolStrip);
base.OnShown(e);
}
protected override LayoutElement GetZoomButtons() protected override LayoutElement GetZoomButtons()
{ {
// Disabled buttons don't prevent click events from being sent to the listview below the button, so without this // Disabled buttons don't prevent click events from being sent to the listview below the button, so without this
@ -107,11 +113,6 @@ public class WinFormsDesktopForm : DesktopForm
return _container.ToEto(); return _container.ToEto();
} }
protected override void AfterLayout()
{
_toolbarFormatter.RelayoutToolbar(_toolStrip);
}
protected override void SetThumbnailSpacing(int thumbnailSize) protected override void SetThumbnailSpacing(int thumbnailSize)
{ {
NativeListView.Padding = new wf.Padding(0, 20, 0, 0); NativeListView.Padding = new wf.Padding(0, 20, 0, 0);

View File

@ -17,17 +17,27 @@ public class WinFormsListView<T> : IListView<T> where T : notnull
{ {
_behavior = behavior; _behavior = behavior;
_view = behavior.ScrollOnDrag ? new DragScrollListView() : new ListView(); _view = behavior.ScrollOnDrag ? new DragScrollListView() : new ListView();
_view.LargeImageList = new ImageList
{
ColorDepth = ColorDepth.Depth32Bit,
TransparentColor = Color.Transparent
};
_view.View = View.LargeIcon;
_view.MultiSelect = behavior.MultiSelect; _view.MultiSelect = behavior.MultiSelect;
WinFormsHacks.SetControlStyle(_view, ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, if (_behavior.Checkboxes)
true); {
_view.View = View.List;
_view.CheckBoxes = true;
_view.ItemChecked += OnSelectedIndexChanged;
}
else
{
_view.View = View.LargeIcon;
_view.LargeImageList = new ImageList
{
ColorDepth = ColorDepth.Depth32Bit,
TransparentColor = Color.Transparent
};
WinFormsHacks.SetControlStyle(_view,
ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint,
true);
_view.SelectedIndexChanged += OnSelectedIndexChanged;
}
_view.SelectedIndexChanged += OnSelectedIndexChanged;
_view.ItemActivate += OnItemActivate; _view.ItemActivate += OnItemActivate;
_view.ItemDrag += OnItemDrag; _view.ItemDrag += OnItemDrag;
_view.DragEnter += OnDragEnter; _view.DragEnter += OnDragEnter;
@ -84,11 +94,19 @@ public class WinFormsListView<T> : IListView<T> where T : notnull
} }
_refreshing = true; _refreshing = true;
Items.Clear(); Items.Clear();
ImageList.Clear(); if (!_behavior.Checkboxes)
{
ImageList.Clear();
}
foreach (var item in items) foreach (var item in items)
{ {
ImageList.Add(_behavior.GetImage(item, ImageSize).ToSD()); if (!_behavior.Checkboxes)
var listViewItem = Items.Add(GetLabel(item), ImageList.Count - 1); {
ImageList.Add(_behavior.GetImage(item, ImageSize).ToSD());
}
var listViewItem = _behavior.Checkboxes
? Items.Add(GetLabel(item))
: Items.Add(GetLabel(item), ImageList.Count - 1);
listViewItem.Tag = item; listViewItem.Tag = item;
} }
SetSelectedItems(); SetSelectedItems();
@ -99,7 +117,14 @@ public class WinFormsListView<T> : IListView<T> where T : notnull
{ {
for (int i = 0; i < Items.Count; i++) for (int i = 0; i < Items.Count; i++)
{ {
Items[i].Selected = Selection.Contains((T) Items[i].Tag); if (_behavior.Checkboxes)
{
Items[i].Checked = Selection.Contains((T) Items[i].Tag);
}
else
{
Items[i].Selected = Selection.Contains((T) Items[i].Tag);
}
} }
} }
@ -144,8 +169,8 @@ public class WinFormsListView<T> : IListView<T> where T : notnull
// TODO: We might want to make the differ even smarter. e.g. maybe it can generate an arbitrary order of operations that minimizes update cost // TODO: We might want to make the differ even smarter. e.g. maybe it can generate an arbitrary order of operations that minimizes update cost
// example: clear then append 1 instead of delete all but 1 // example: clear then append 1 instead of delete all but 1
var originalImagesList = Items.OfType<ListViewItem>().Select(x => (T) x.Tag).ToList(); var originalItemsList = Items.OfType<ListViewItem>().Select(x => (T) x.Tag).ToList();
var originalImagesSet = new HashSet<T>(originalImagesList); var originalItemsSet = new HashSet<T>(originalItemsList);
if (!diffs.AppendOperations.Any() && !diffs.ReplaceOperations.Any() && if (!diffs.AppendOperations.Any() && !diffs.ReplaceOperations.Any() &&
diffs.TrimOperations.Any(x => x.Count == Items.Count)) diffs.TrimOperations.Any(x => x.Count == Items.Count))
{ {
@ -160,30 +185,39 @@ public class WinFormsListView<T> : IListView<T> where T : notnull
// TODO: Use AddRange instead? // TODO: Use AddRange instead?
// TODO: Add this to the new ImageListViewBehavior // TODO: Add this to the new ImageListViewBehavior
// _thumbnailProvider.GetThumbnail(append.Image.Source, ThumbnailSize) // _thumbnailProvider.GetThumbnail(append.Image.Source, ThumbnailSize)
ImageList.Add(_behavior.GetImage(append.Item, ImageSize).ToSD());
var item = Items.Add(GetLabel(append.Item)); var item = Items.Add(GetLabel(append.Item));
item.Tag = append.Item; item.Tag = append.Item;
// TODO: This isn't used above, is it needed? if (!_behavior.Checkboxes)
item.ImageIndex = ImageList.Count - 1; {
ImageList.Add(_behavior.GetImage(append.Item, ImageSize).ToSD());
// TODO: This isn't used above, is it needed?
item.ImageIndex = ImageList.Count - 1;
}
} }
foreach (var replace in diffs.ReplaceOperations) foreach (var replace in diffs.ReplaceOperations)
{ {
ImageList[replace.Index] = _behavior.GetImage(replace.Item, ImageSize).ToSD(); if (!_behavior.Checkboxes)
{
ImageList[replace.Index] = _behavior.GetImage(replace.Item, ImageSize).ToSD();
}
Items[replace.Index].Tag = replace.Item; Items[replace.Index].Tag = replace.Item;
} }
foreach (var trim in diffs.TrimOperations) foreach (var trim in diffs.TrimOperations)
{ {
for (int i = 0; i < trim.Count; i++) for (int i = 0; i < trim.Count; i++)
{ {
ImageList.RemoveAt(ImageList.Count - 1); if (!_behavior.Checkboxes)
{
ImageList.RemoveAt(ImageList.Count - 1);
}
Items.RemoveAt(Items.Count - 1); Items.RemoveAt(Items.Count - 1);
} }
} }
} }
SetSelectedItems(); SetSelectedItems();
var newImagesList = Items.OfType<ListViewItem>().Select(x => (T) x.Tag).ToList(); var newItemsList = Items.OfType<ListViewItem>().Select(x => (T) x.Tag).ToList();
var newImagesSet = new HashSet<T>(newImagesList); var newItemsSet = new HashSet<T>(newItemsList);
if (originalImagesSet.SetEquals(newImagesSet) && !originalImagesList.SequenceEqual(newImagesList)) if (originalItemsSet.SetEquals(newItemsSet) && !originalItemsList.SequenceEqual(newItemsList))
{ {
ScrollToSelection(); ScrollToSelection();
} }
@ -219,21 +253,17 @@ public class WinFormsListView<T> : IListView<T> where T : notnull
} }
} }
private string GetLabel(T item) private string GetLabel(T item) => _behavior.ShowLabels ? _behavior.GetLabel(item) : "";
{
if (!_behavior.ShowLabels)
{
return PlatformCompat.Runtime.UseSpaceInListViewItem ? " " : "";
}
return _behavior.GetLabel(item);
}
private void OnSelectedIndexChanged(object? sender, EventArgs e) private void OnSelectedIndexChanged(object? sender, EventArgs e)
{ {
if (!_refreshing) if (!_refreshing)
{ {
_refreshing = true; _refreshing = true;
Selection = ListSelection.From(_view.SelectedItems.Cast<ListViewItem>().Select(x => (T) x.Tag)); var items = _behavior.Checkboxes
? _view.CheckedItems.Cast<ListViewItem>()
: _view.SelectedItems.Cast<ListViewItem>();
Selection = ListSelection.From(items.Select(x => (T) x.Tag));
_refreshing = false; _refreshing = false;
} }
} }

View File

@ -4,8 +4,10 @@ namespace NAPS2.EtoForms;
public class DefaultIconProvider : IIconProvider public class DefaultIconProvider : IIconProvider
{ {
public Image GetIcon(string name) public Image? GetIcon(string name)
{ {
return new Bitmap((byte[]) (Icons.ResourceManager.GetObject(name) ?? throw new ArgumentException())); var data = (byte[]?) Icons.ResourceManager.GetObject(name);
if (data == null) return null;
return new Bitmap(data);
} }
} }

View File

@ -4,5 +4,5 @@ namespace NAPS2.EtoForms;
public interface IIconProvider public interface IIconProvider
{ {
Image GetIcon(string name); Image? GetIcon(string name);
} }

View File

@ -89,7 +89,6 @@ public abstract class DesktopForm : EtoFormBase
L.Row(GetZoomButtons(), C.Filler()) L.Row(GetZoomButtons(), C.Filler())
).Padding(10) ).Padding(10)
); );
AfterLayout();
// //
// Shown += FDesktop_Shown; // Shown += FDesktop_Shown;
@ -259,10 +258,6 @@ public abstract class DesktopForm : EtoFormBase
return new MenuProvider().Dynamic(_languageMenuCommands); return new MenuProvider().Dynamic(_languageMenuCommands);
} }
protected virtual void AfterLayout()
{
}
protected virtual void ConfigureToolbar() protected virtual void ConfigureToolbar()
{ {
} }