From 1fda0e73202664d375e2b13ea4d21470c8f32773 Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Wed, 24 Nov 2021 16:25:34 -0800 Subject: [PATCH 1/2] Improving store page --- .../{ExploreItem.cs => ArticleItem.cs} | 8 +- .../{ExploreSection.cs => ArticleSection.cs} | 29 ++-- .../Library/Widgets/StorePage/ExplorePanel.cs | 79 +++++++--- .../Library/Widgets/StorePage/FeedItemData.cs | 1 + .../Library/Widgets/StorePage/ProductItem.cs | 135 ++++++++++++++++++ .../Widgets/StorePage/ProductSection.cs | 88 ++++++++++++ .../Library/Widgets/StorePage/StoreTabPage.cs | 9 +- .../Utilities/WebUtilities/WebCache.cs | 4 + Submodules/MatterSlice | 2 +- Submodules/agg-sharp | 2 +- 10 files changed, 303 insertions(+), 54 deletions(-) rename MatterControlLib/Library/Widgets/StorePage/{ExploreItem.cs => ArticleItem.cs} (92%) rename MatterControlLib/Library/Widgets/StorePage/{ExploreSection.cs => ArticleSection.cs} (81%) create mode 100644 MatterControlLib/Library/Widgets/StorePage/ProductItem.cs create mode 100644 MatterControlLib/Library/Widgets/StorePage/ProductSection.cs diff --git a/MatterControlLib/Library/Widgets/StorePage/ExploreItem.cs b/MatterControlLib/Library/Widgets/StorePage/ArticleItem.cs similarity index 92% rename from MatterControlLib/Library/Widgets/StorePage/ExploreItem.cs rename to MatterControlLib/Library/Widgets/StorePage/ArticleItem.cs index 5896e8ac9..0753397f0 100644 --- a/MatterControlLib/Library/Widgets/StorePage/ExploreItem.cs +++ b/MatterControlLib/Library/Widgets/StorePage/ArticleItem.cs @@ -33,7 +33,7 @@ using MatterHackers.Agg.UI; namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab { - public class ExploreItem : FlowLayoutWidget + public class ArticleItem : FlowLayoutWidget { private FeedItemData item; private ThemeConfig theme; @@ -41,7 +41,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab public static int IconSize => (int)(40 * GuiWidget.DeviceScale); public static int ItemSpacing { get; } = 10; - public ExploreItem(FeedItemData item, ThemeConfig theme) + public ArticleItem(FeedItemData item, ThemeConfig theme) { this.HAnchor = HAnchor.Absolute; this.Width = 400 * GuiWidget.DeviceScale; @@ -61,7 +61,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab Margin = new BorderDouble(right: ItemSpacing) }; - imageWidget.Load += (s, e) => WebCache.RetrieveImageAsync(image, item.icon, true, new BlenderPreMultBGRA()); + WebCache.RetrieveImageAsync(image, item.icon, true, new BlenderPreMultBGRA()); this.AddChild(imageWidget); } else if (item.widget_url != null) @@ -80,7 +80,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab VAnchor = VAnchor.Center, }; - imageWidget.Load += (s, e) => WebCache.RetrieveImageAsync(image, item.widget_url, true, new BlenderPreMultBGRA()); + WebCache.RetrieveImageAsync(image, item.widget_url, true, new BlenderPreMultBGRA()); whiteBackground.AddChild(imageWidget); } diff --git a/MatterControlLib/Library/Widgets/StorePage/ExploreSection.cs b/MatterControlLib/Library/Widgets/StorePage/ArticleSection.cs similarity index 81% rename from MatterControlLib/Library/Widgets/StorePage/ExploreSection.cs rename to MatterControlLib/Library/Widgets/StorePage/ArticleSection.cs index daa35ac17..bdf246547 100644 --- a/MatterControlLib/Library/Widgets/StorePage/ExploreSection.cs +++ b/MatterControlLib/Library/Widgets/StorePage/ArticleSection.cs @@ -27,35 +27,32 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ -using System; using System.Collections.Generic; using System.Linq; using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.Localizations; using MatterHackers.MatterControl.CustomWidgets; -using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab { - public class ExploreSection : FlowLayoutWidget + public class ArticleSection : FlowLeftRightWithWrapping { - private List allIconViews = new List(); + private List allIconViews = new List(); private FeedSectionData content; private ThemeConfig theme; - private TextButton moreButton; - int maxStuff = 7; + int maxStuff = 20; - public ExploreSection(FeedSectionData content, ThemeConfig theme) - : base(FlowDirection.TopToBottom) + public ArticleSection(FeedSectionData content, ThemeConfig theme) { + Proportional = true; VAnchor = VAnchor.Fit | VAnchor.Top; this.content = content; this.theme = theme; foreach (var item in content.group_items) { - allIconViews.Add(new ExploreItem(item, theme) + allIconViews.Add(new ArticleItem(item, theme) { BackgroundColor = theme.MinimalShade, VAnchor = VAnchor.Fit, @@ -80,15 +77,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab } this.CloseChildren(); - if (content.group_title != null) - { - this.AddChild(new TextWidget(content.group_title, pointSize: theme.H1PointSize, textColor: theme.TextColor, bold: true) - { - HAnchor = HAnchor.Left, - Margin = new BorderDouble(leftRightMargin, 5) - }); - } - int i = 0; foreach (var iconView in allIconViews) { @@ -103,10 +91,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab if (content.group_items.Count > maxStuff) { - moreButton = new TextButton("More".Localize() + "...", theme) + var moreButton = new TextButton("More".Localize() + "...", theme) { - VAnchor = VAnchor.Absolute, - HAnchor = HAnchor.Right, BackgroundColor = theme.MinimalShade, Margin = new BorderDouble(right: leftRightMargin), }; @@ -128,6 +114,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab scroll.ScrollPositionFromTop = position; } }; + this.AddChild(moreButton); } } diff --git a/MatterControlLib/Library/Widgets/StorePage/ExplorePanel.cs b/MatterControlLib/Library/Widgets/StorePage/ExplorePanel.cs index ad198b80d..761d638f1 100644 --- a/MatterControlLib/Library/Widgets/StorePage/ExplorePanel.cs +++ b/MatterControlLib/Library/Widgets/StorePage/ExplorePanel.cs @@ -29,15 +29,12 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Net.Http; using System.Threading.Tasks; using MatterControl.Printing; using MatterHackers.Agg; -using MatterHackers.Agg.Font; using MatterHackers.Agg.Image; using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.VectorMath; using Newtonsoft.Json; @@ -49,6 +46,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab private ThemeConfig theme; private object locker = new object(); + private GuiWidget topBanner; + private GuiWidget sectionSelectButtons; + private GuiWidget contentSection; + public ExplorePanel(ThemeConfig theme, string relativeUrl) : base(FlowDirection.TopToBottom) { @@ -59,6 +60,16 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab this.Margin = new BorderDouble(30 - 11, 0); this.theme = theme; + + topBanner = this.AddChild(new GuiWidget() { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Fit }); + sectionSelectButtons = this.AddChild(new FlowLeftRightWithWrapping() + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit, + Proportional = true, + Name = "Select Buttons" + }); + contentSection = this.AddChild(new GuiWidget() { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Fit }); } public override void OnLoad(EventArgs args) @@ -89,10 +100,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab GuiWidget currentContentContainer = null; foreach (var content in explorerFeed.Content) { - AddContentItem(container, ref currentContentContainer, theme, content); + AddContentItem(theme, content); } - this.CloseChildren(); foreach (var widget in container) { this.AddChild(widget); @@ -110,14 +120,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab } - private static void AddContentItem(List container, ref GuiWidget currentContentContainer, ThemeConfig theme, FeedSectionData content) + private void AddContentItem(ThemeConfig theme, FeedSectionData content) { switch (content.content_type) { case "headline": + /* { - break; - // use the Golden Ratio to calculate an attractive size relative to the banner var image = new ImageBuffer(1520, (int)(170 / 1.618)); var imageWidget = new ResponsiveImageWidget(image) @@ -154,12 +163,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab container.Add(imageWidget); } + */ break; case "banner_rotate": // TODO: make this make a carousel rather than add the first item and rotate between all the items var rand = new Random(); - AddContentItem(container, ref currentContentContainer, theme, content.banner_list[rand.Next(content.banner_list.Count)]); + AddContentItem(theme, content.banner_list[rand.Next(content.banner_list.Count)]); break; case "banner_image": @@ -193,24 +203,51 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab }; } - imageWidget.Load += (s, e) => WebCache.RetrieveImageAsync(image, content.image_url, false, new BlenderPreMultBGRA()); - container.Add(imageWidget); + WebCache.RetrieveImageAsync(image, content.image_url, false, new BlenderPreMultBGRA()); + topBanner.AddChild(imageWidget); } } break; case "article_group": - case "product_group": - if(currentContentContainer == null) { - currentContentContainer = new FlowLeftRightWithWrapping() - { - Proportional = true, - }; - - container.Add(currentContentContainer); + // add the article group button to the button group + // add a content section connected to the button + var sectionButton = new TextButton(content.group_title, theme); + sectionSelectButtons.AddChild(sectionButton); + var exploreSection = new ArticleSection(content, theme) + { + Visible = false, + Name = content.group_title + }; + contentSection.AddChild(exploreSection); + sectionButton.Click += (s, e) => + { + foreach (var contentWidget in contentSection.Children) + { + contentWidget.Visible = contentWidget == exploreSection; + } + }; + } + break; + + case "product_group": + { + var sectionButton = new TextButton(content.group_title, theme); + sectionSelectButtons.AddChild(sectionButton); + var exploreSection = new ProductSection(content, theme) + { + Name = content.group_title + }; + contentSection.AddChild(exploreSection); + sectionButton.Click += (s, e) => + { + foreach (var contentWidget in contentSection.Children) + { + contentWidget.Visible = contentWidget == exploreSection; + } + }; } - currentContentContainer.AddChild(new ExploreSection(content, theme)); break; } } diff --git a/MatterControlLib/Library/Widgets/StorePage/FeedItemData.cs b/MatterControlLib/Library/Widgets/StorePage/FeedItemData.cs index 2b54a512a..02916d44f 100644 --- a/MatterControlLib/Library/Widgets/StorePage/FeedItemData.cs +++ b/MatterControlLib/Library/Widgets/StorePage/FeedItemData.cs @@ -40,6 +40,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab public string icon; public string link; public string title; + public string subtitle; public string url; public string widget_url; } diff --git a/MatterControlLib/Library/Widgets/StorePage/ProductItem.cs b/MatterControlLib/Library/Widgets/StorePage/ProductItem.cs new file mode 100644 index 000000000..05bcaafaf --- /dev/null +++ b/MatterControlLib/Library/Widgets/StorePage/ProductItem.cs @@ -0,0 +1,135 @@ +/* +Copyright (c) 2017, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.Agg; +using MatterHackers.Agg.Image; +using MatterHackers.Agg.UI; + +namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab +{ + public class ProductItem : FlowLayoutWidget + { + private FeedItemData item; + private ThemeConfig theme; + + public static int IconSize => (int)(200 * GuiWidget.DeviceScale); + public static int ItemSpacing { get; } = 10; + + public ProductItem(FeedItemData item, ThemeConfig theme) + : base(FlowDirection.TopToBottom) + { + this.Padding = ItemSpacing; + this.item = item; + this.theme = theme; + + var image = new ImageBuffer(IconSize, IconSize); + + if (item.widget_url != null) + { + var whiteBackground = new GuiWidget(IconSize, IconSize) + { + // these images expect to be on white so change the background to white + BackgroundColor = Color.White, + Margin = new BorderDouble(right: ItemSpacing) + }; + this.AddChild(whiteBackground); + + var imageWidget = new ImageWidget(image) + { + Selectable = false, + VAnchor = VAnchor.Center, + }; + + WebCache.RetrieveImageAsync(image, item.widget_url, true, new BlenderPreMultBGRA()); + whiteBackground.AddChild(imageWidget); + } + + var titleText = new WrappedTextWidget(item.title, textColor: theme.TextColor, pointSize: theme.FontSize14) + { + Selectable = false, + VAnchor = VAnchor.Fit, + HAnchor = HAnchor.Stretch, + Margin = new BorderDouble(3, 3, 3, 9) + }; + this.AddChild(titleText); + + var descriptionText = new WrappedTextWidget(item.subtitle, textColor: theme.TextColor.WithAlpha(.7), pointSize: theme.FontSize8) + { + Selectable = false, + VAnchor = VAnchor.Fit, + HAnchor = HAnchor.Stretch, + Margin = 3 + }; + this.AddChild(descriptionText); + + this.Cursor = Cursors.Hand; + } + + public override Color BackgroundColor + { + get => (mouseInBounds) ? theme.AccentMimimalOverlay : base.BackgroundColor; + set => base.BackgroundColor = value; + } + + private bool mouseInBounds = false; + + public override void OnMouseEnterBounds(MouseEventArgs mouseEvent) + { + mouseInBounds = true; + base.OnMouseEnterBounds(mouseEvent); + + this.Invalidate(); + } + + public override void OnMouseLeaveBounds(MouseEventArgs mouseEvent) + { + mouseInBounds = false; + base.OnMouseLeaveBounds(mouseEvent); + + this.Invalidate(); + } + + protected override void OnClick(MouseEventArgs mouseEvent) + { + if (mouseEvent.Button == MouseButtons.Left) + { + if (item.url != null) + { + ApplicationController.LaunchBrowser("http://www.matterhackers.com/" + item.url); + } + else if (item.link != null) + { + ApplicationController.LaunchBrowser(item.link); + } + } + + base.OnClick(mouseEvent); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/Library/Widgets/StorePage/ProductSection.cs b/MatterControlLib/Library/Widgets/StorePage/ProductSection.cs new file mode 100644 index 000000000..b4ebd4195 --- /dev/null +++ b/MatterControlLib/Library/Widgets/StorePage/ProductSection.cs @@ -0,0 +1,88 @@ +/* +Copyright (c) 2017, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System.Collections.Generic; +using System.Linq; +using MatterHackers.Agg; +using MatterHackers.Agg.UI; +using MatterHackers.Localizations; +using MatterHackers.MatterControl.CustomWidgets; + +namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab +{ + public class ProductSection : FlowLeftRightWithWrapping + { + private List allIconViews = new List(); + private FeedSectionData content; + private ThemeConfig theme; + private TextButton moreButton; + + public ProductSection(FeedSectionData content, ThemeConfig theme) + { + Proportional = true; + VAnchor = VAnchor.Fit | VAnchor.Top; + this.content = content; + this.theme = theme; + + foreach (var item in content.group_items) + { + allIconViews.Add(new ProductItem(item, theme) + { + BackgroundColor = theme.MinimalShade, + VAnchor = VAnchor.Fit, + }); + } + + AddContent(); + } + + public void AddContent() + { + int leftRightMargin = 5; + int topBottomMargin = 5; + + // Reflow Children + foreach (var iconView in allIconViews) + { + if (this.Children.Contains(iconView)) + { + this.RemoveChild(iconView); + } + } + this.CloseChildren(); + + foreach (var iconView in allIconViews) + { + iconView.ClearRemovedFlag(); + iconView.Margin = new BorderDouble(leftRightMargin, topBottomMargin); + this.AddChild(iconView); + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/Library/Widgets/StorePage/StoreTabPage.cs b/MatterControlLib/Library/Widgets/StorePage/StoreTabPage.cs index 8b2814a1c..bac7c290f 100644 --- a/MatterControlLib/Library/Widgets/StorePage/StoreTabPage.cs +++ b/MatterControlLib/Library/Widgets/StorePage/StoreTabPage.cs @@ -64,12 +64,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab public override void OnMouseWheel(MouseEventArgs mouseEvent) { - if (mouseEvent.WheelDelta != 0) - { - int direction = (mouseEvent.WheelDelta > 0) ? -1 : 1; - this.ScrollPosition += new Vector2(0, (ExploreItem.IconSize + (ExploreItem.ItemSpacing * 2)) * direction); - mouseEvent.WheelDelta = 0; - } + mouseEvent.WheelDelta *= 3; + + base.OnMouseWheel(mouseEvent); } } } diff --git a/MatterControlLib/Utilities/WebUtilities/WebCache.cs b/MatterControlLib/Utilities/WebUtilities/WebCache.cs index f8a040f1f..a313f7c75 100644 --- a/MatterControlLib/Utilities/WebUtilities/WebCache.cs +++ b/MatterControlLib/Utilities/WebUtilities/WebCache.cs @@ -51,6 +51,10 @@ namespace MatterHackers.MatterControl public static void RetrieveImageAsync(ImageBuffer imageToLoadInto, string uriToLoad, bool scaleToImageX, IRecieveBlenderByte scalingBlender = null) { var longHash = uriToLoad.GetLongHashCode(); + if (scaleToImageX) + { + longHash = imageToLoadInto.Width.GetLongHashCode(longHash); + } var imageFileName = ApplicationController.CacheablePath("Images", longHash.ToString() + ".png"); if (File.Exists(imageFileName)) diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index ee639857d..18bb089df 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit ee639857de9d8157d9a656d3dc76c07aba02818b +Subproject commit 18bb089dfbd5474e518ce578826001f8b9e7f911 diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 183673e00..ca13554d4 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 183673e004d7c085cb970bd5b8f04fbd3f4750b1 +Subproject commit ca13554d458c15488c5e64f7c9dac984d3834aa0 From 6162ca25d445d1928f9d07544a2effcab0626558 Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Wed, 24 Nov 2021 17:02:26 -0800 Subject: [PATCH 2/2] Make sure we load our images asynch make sure we update them after load --- .../Library/Widgets/StorePage/ArticleItem.cs | 4 ++-- .../Library/Widgets/StorePage/ExplorePanel.cs | 13 +++++++++++-- .../Library/Widgets/StorePage/ProductItem.cs | 2 +- MatterControlLib/Utilities/WebUtilities/WebCache.cs | 2 ++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/MatterControlLib/Library/Widgets/StorePage/ArticleItem.cs b/MatterControlLib/Library/Widgets/StorePage/ArticleItem.cs index 0753397f0..1ee56b0b4 100644 --- a/MatterControlLib/Library/Widgets/StorePage/ArticleItem.cs +++ b/MatterControlLib/Library/Widgets/StorePage/ArticleItem.cs @@ -61,7 +61,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab Margin = new BorderDouble(right: ItemSpacing) }; - WebCache.RetrieveImageAsync(image, item.icon, true, new BlenderPreMultBGRA()); + Load += (s, e) => WebCache.RetrieveImageAsync(image, item.icon, true, new BlenderPreMultBGRA()); this.AddChild(imageWidget); } else if (item.widget_url != null) @@ -80,7 +80,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab VAnchor = VAnchor.Center, }; - WebCache.RetrieveImageAsync(image, item.widget_url, true, new BlenderPreMultBGRA()); + Load += (s, e) => WebCache.RetrieveImageAsync(image, item.widget_url, true, new BlenderPreMultBGRA()); whiteBackground.AddChild(imageWidget); } diff --git a/MatterControlLib/Library/Widgets/StorePage/ExplorePanel.cs b/MatterControlLib/Library/Widgets/StorePage/ExplorePanel.cs index 761d638f1..020473495 100644 --- a/MatterControlLib/Library/Widgets/StorePage/ExplorePanel.cs +++ b/MatterControlLib/Library/Widgets/StorePage/ExplorePanel.cs @@ -49,8 +49,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab private GuiWidget topBanner; private GuiWidget sectionSelectButtons; private GuiWidget contentSection; + private bool loaded; - public ExplorePanel(ThemeConfig theme, string relativeUrl) + public ExplorePanel(ThemeConfig theme, string relativeUrl) : base(FlowDirection.TopToBottom) { this.relativeUrl = relativeUrl; @@ -107,6 +108,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab { this.AddChild(widget); } + UiThread.RunOnIdle(() => { // Force layout to change to get it working @@ -203,7 +205,14 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab }; } - WebCache.RetrieveImageAsync(image, content.image_url, false, new BlenderPreMultBGRA()); + AfterDraw += (s, e) => + { + if (!loaded) + { + loaded = true; + WebCache.RetrieveImageAsync(image, content.image_url, false, new BlenderPreMultBGRA()); + } + }; topBanner.AddChild(imageWidget); } } diff --git a/MatterControlLib/Library/Widgets/StorePage/ProductItem.cs b/MatterControlLib/Library/Widgets/StorePage/ProductItem.cs index 05bcaafaf..e98549ca4 100644 --- a/MatterControlLib/Library/Widgets/StorePage/ProductItem.cs +++ b/MatterControlLib/Library/Widgets/StorePage/ProductItem.cs @@ -66,7 +66,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab VAnchor = VAnchor.Center, }; - WebCache.RetrieveImageAsync(image, item.widget_url, true, new BlenderPreMultBGRA()); + Load += (s, e) => WebCache.RetrieveImageAsync(image, item.widget_url, true, new BlenderPreMultBGRA()); whiteBackground.AddChild(imageWidget); } diff --git a/MatterControlLib/Utilities/WebUtilities/WebCache.cs b/MatterControlLib/Utilities/WebUtilities/WebCache.cs index a313f7c75..6a2837259 100644 --- a/MatterControlLib/Utilities/WebUtilities/WebCache.cs +++ b/MatterControlLib/Utilities/WebUtilities/WebCache.cs @@ -391,6 +391,8 @@ namespace MatterHackers.MatterControl { StaticData.Instance.LoadImageData(stream, imageToLoadInto); } + + imageToLoadInto.MarkImageChanged(); } } } \ No newline at end of file