Decouple thumb generation for ListView control

- Issue MatterHackers/MCCentral#3357
ListView ActiveContainer_Changed fires far more than expected

- Issue MatterHackers/MCCentral#3363
Start page -> Part icon -> Click does not load workspace
This commit is contained in:
John Lewin 2018-05-11 18:41:34 -07:00
parent ad62450575
commit 7d8bb2d964
6 changed files with 76 additions and 51 deletions

View file

@ -277,7 +277,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
public override async void OnLoad(EventArgs args)
{
base.OnLoad(args);
await this.LoadItemThumbnail(listViewItem.ListView.ActiveContainer);
await this.LoadItemThumbnail();
}
public override Color BackgroundColor

View file

@ -212,7 +212,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
// Folder items
foreach (var childContainer in this.SortItems(containerItems))
{
var listViewItem = new ListViewItem(childContainer, this);
var listViewItem = new ListViewItem(childContainer, this.ActiveContainer);
listViewItem.DoubleClick += listViewItem_DoubleClick;
items.Add(listViewItem);
@ -231,7 +231,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
foreach (var item in this.SortItems(filteredResults))
{
var listViewItem = new ListViewItem(item, this);
var listViewItem = new ListViewItem(item, this.ActiveContainer, this);
listViewItem.DoubleClick += listViewItem_DoubleClick;
items.Add(listViewItem);
@ -280,10 +280,9 @@ namespace MatterHackers.MatterControl.CustomWidgets
private void WritableContainer_ItemContentChanged(object sender, ItemChangedEventArgs e)
{
var firstItem = items.Where(i => i.Model.ID == e.LibraryItem.ID).FirstOrDefault();
if (firstItem != null)
if (items.Where(i => i.Model.ID == e.LibraryItem.ID).FirstOrDefault() is ListViewItem listViewItem)
{
firstItem.ViewWidget.LoadItemThumbnail(firstItem.ListView.ActiveContainer).ConfigureAwait(false);
listViewItem.ViewWidget.LoadItemThumbnail().ConfigureAwait(false);
}
}
@ -326,16 +325,16 @@ namespace MatterHackers.MatterControl.CustomWidgets
}
}
internal static ImageBuffer LoadCachedImage(ListViewItem listViewItem, int width, int height)
internal static ImageBuffer LoadCachedImage(ILibraryItem libraryItem, int width, int height)
{
ImageBuffer cachedItem = LoadImage(ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model, width, height));
ImageBuffer cachedItem = LoadImage(ApplicationController.Instance.ThumbnailCachePath(libraryItem, width, height));
if (cachedItem != null)
{
return cachedItem;
}
// Check for big render, resize, cache and return
var bigRender = LoadImage(ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model));
var bigRender = LoadImage(ApplicationController.Instance.ThumbnailCachePath(libraryItem));
if (bigRender != null)
{
try
@ -344,7 +343,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
// Cache at requested size
AggContext.ImageIO.SaveImageData(
ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model, width, height),
ApplicationController.Instance.ThumbnailCachePath(libraryItem, width, height),
thumbnail);
return thumbnail;
@ -378,7 +377,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
}
// TODO: ResizeCanvas is also colorizing thumbnails as a proof of concept
public ImageBuffer ResizeCanvas(ImageBuffer originalImage, int width, int height)
public static ImageBuffer ResizeCanvas(ImageBuffer originalImage, int width, int height)
{
var destImage = new ImageBuffer(width, height, 32, originalImage.GetRecieveBlender());

View file

@ -43,12 +43,15 @@ namespace MatterHackers.MatterControl.CustomWidgets
public ListViewItemBase ViewWidget { get; set; }
public ListViewItem(ILibraryItem libraryItem, ListView listView)
public ListViewItem(ILibraryItem libraryItem, ILibraryContainer container, ListView listView = null)
{
this.Container = container;
this.ListView = listView;
this.Model = libraryItem;
}
public ILibraryContainer Container { get; }
internal void OnDoubleClick()
{
DoubleClick?.Invoke(this, null);

View file

@ -27,6 +27,7 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.IO;
using System.Threading.Tasks;
using MatterHackers.Agg;
@ -64,6 +65,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
this.thumbHeight = height;
}
// TODO: Why is this static?
private static bool WidgetOnScreen(GuiWidget widget, RectangleDouble bounds)
{
if (!widget.Visible)
@ -89,33 +91,42 @@ namespace MatterHackers.MatterControl.CustomWidgets
return true;
}
public async Task LoadItemThumbnail(ILibraryContainer libraryContainer)
public Task LoadItemThumbnail()
{
var thumbnail = ListView.LoadCachedImage(listViewItem, thumbWidth, thumbHeight);
return LoadItemThumbnail(
listViewItem.Model,
listViewItem.Container,
this.thumbWidth,
this.thumbHeight,
this.SetItemThumbnail,
() => ListViewItemBase.WidgetOnScreen(this, this.LocalBounds));
}
private static async Task LoadItemThumbnail(ILibraryItem libraryItem, ILibraryContainer libraryContainer, int thumbWidth, int thumbHeight, Action<ImageBuffer, bool> thumbnailSetter, Func<bool> shouldGenerateThumbnail)
{
var thumbnail = ListView.LoadCachedImage(libraryItem, thumbWidth, thumbHeight);
if (thumbnail != null)
{
SetItemThumbnail(thumbnail);
thumbnailSetter(thumbnail, false);
return;
}
var itemModel = listViewItem.Model;
if (thumbnail == null)
{
// Ask the container - allows the container to provide its own interpretation of the item thumbnail
thumbnail = await libraryContainer.GetThumbnail(itemModel, thumbWidth, thumbHeight);
thumbnail = await libraryContainer.GetThumbnail(libraryItem, thumbWidth, thumbHeight);
}
if (thumbnail == null && itemModel is IThumbnail)
if (thumbnail == null && libraryItem is IThumbnail)
{
// If the item provides its own thumbnail, try to collect it
thumbnail = await (itemModel as IThumbnail).GetThumbnail(thumbWidth, thumbHeight);
thumbnail = await (libraryItem as IThumbnail).GetThumbnail(thumbWidth, thumbHeight);
}
if (thumbnail == null)
{
// Ask content provider - allows type specific thumbnail creation
var contentProvider = ApplicationController.Instance.Library.GetContentProvider(itemModel);
var contentProvider = ApplicationController.Instance.Library.GetContentProvider(libraryItem);
if (contentProvider is MeshContentProvider)
{
// Before we have a thumbnail set to the content specific thumbnail
@ -124,19 +135,19 @@ namespace MatterHackers.MatterControl.CustomWidgets
ApplicationController.Instance.QueueForGeneration(async () =>
{
// When this widget is dequeued for generation, validate before processing. Off-screen widgets should be skipped and will requeue next time they become visible
if (ListViewItemBase.WidgetOnScreen(this, this.LocalBounds))
if (shouldGenerateThumbnail?.Invoke() == true)
{
SetItemThumbnail(generatingThumbnailIcon);
thumbnailSetter(generatingThumbnailIcon, false);
// Then try to load a content specific thumbnail
await contentProvider.GetThumbnail(
itemModel,
libraryItem,
thumbWidth,
thumbHeight,
(image) =>
{
// Use the content providers default image if an image failed to load
SetItemThumbnail(image ?? contentProvider.DefaultImage, true);
thumbnailSetter(image ?? contentProvider.DefaultImage, true);
});
}
});
@ -145,7 +156,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
// Then try to load a content specific thumbnail
await contentProvider.GetThumbnail(
itemModel,
libraryItem,
thumbWidth,
thumbHeight,
(image) => thumbnail = image);
@ -155,10 +166,10 @@ namespace MatterHackers.MatterControl.CustomWidgets
if (thumbnail == null)
{
// Use the listview defaults
thumbnail = ((itemModel is ILibraryContainerLink) ? defaultFolderIcon : defaultItemIcon).AlphaToPrimaryAccent();
thumbnail = ((libraryItem is ILibraryContainerLink) ? defaultFolderIcon : defaultItemIcon).AlphaToPrimaryAccent();
}
SetItemThumbnail(thumbnail);
thumbnailSetter(thumbnail, false);
}
internal void EnsureSelection()
@ -168,13 +179,13 @@ namespace MatterHackers.MatterControl.CustomWidgets
// Existing selection only survives with ctrl->click
if (!Keyboard.IsKeyDown(Keys.ControlKey))
{
listViewItem.ListView.SelectedItems.Clear();
listViewItem.ListView?.SelectedItems.Clear();
}
// Any mouse down ensures selection - mouse up will evaluate if DragDrop occurred and toggle selection if not
if (!listViewItem.ListView.SelectedItems.Contains(listViewItem))
if (!listViewItem.ListView?.SelectedItems.Contains(listViewItem) == true)
{
listViewItem.ListView.SelectedItems.Add(listViewItem);
listViewItem.ListView?.SelectedItems.Add(listViewItem);
}
Invalidate();
@ -188,7 +199,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
if (wasSelected)
{
listViewItem.ListView.SelectedItems.Remove(listViewItem);
listViewItem.ListView?.SelectedItems.Remove(listViewItem);
}
Invalidate();
@ -218,7 +229,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
// Resize canvas to target as fallback
if (thumbnail.Width < thumbWidth || thumbnail.Height < thumbHeight)
{
thumbnail = listViewItem.ListView.ResizeCanvas(thumbnail, thumbWidth, thumbHeight);
thumbnail = ListView.ResizeCanvas(thumbnail, thumbWidth, thumbHeight);
}
else if (thumbnail.Width > thumbWidth || thumbnail.Height > thumbHeight)
{

View file

@ -103,7 +103,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
public override async void OnLoad(EventArgs args)
{
base.OnLoad(args);
await this.LoadItemThumbnail(listViewItem.ListView.ActiveContainer);
await this.LoadItemThumbnail();
}
private bool isHoverItem = false;