Removing tiny icons

Prepping for improved folder views
Fixing warnings
This commit is contained in:
LarsBrubaker 2020-08-01 08:58:50 -07:00
parent 333ef89a9f
commit 0eec29e84d
43 changed files with 466 additions and 463 deletions

View file

@ -35,31 +35,15 @@ namespace MatterHackers.MatterControl.Library
{
public class DynamicContainerLink : ILibraryContainerLink, IThumbnail
{
public string ID { get; set; }
private readonly Func<ILibraryContainer> containerCreator;
public string Category { get; set; }
private readonly Func<string> nameResolver;
public bool IsProtected { get; set; } = true;
private readonly ImageBuffer thumbnail;
public bool IsReadOnly { get; set; } = false;
private readonly Func<bool> visibilityResolver;
public DateTime DateCreated { get; } = DateTime.Now;
public DateTime DateModified { get; } = DateTime.Now;
private ImageBuffer thumbnail;
private Func<ILibraryContainer> containerCreator;
private Func<bool> visibilityResolver;
private Func<string> nameResolver;
private ImageBuffer microIcon;
public DynamicContainerLink(Func<string> nameResolver, ImageBuffer microIcon, ImageBuffer thumbnail, Func<ILibraryContainer> creator = null, Func<bool> visibilityResolver = null)
: this(nameResolver, thumbnail, creator, visibilityResolver)
{
this.microIcon = microIcon;
}
private DynamicContainerLink(Func<string> nameResolver, ImageBuffer thumbnail, Func<ILibraryContainer> creator = null, Func<bool> visibilityResolver = null)
public DynamicContainerLink(Func<string> nameResolver, ImageBuffer thumbnail, Func<ILibraryContainer> creator = null, Func<bool> visibilityResolver = null)
{
this.thumbnail = thumbnail?.SetPreMultiply();
this.nameResolver = nameResolver;
@ -67,10 +51,22 @@ namespace MatterHackers.MatterControl.Library
this.visibilityResolver = visibilityResolver ?? (() => true);
}
public string Name => nameResolver?.Invoke();
public string Category { get; set; }
public DateTime DateCreated { get; } = DateTime.Now;
public DateTime DateModified { get; } = DateTime.Now;
public string ID { get; set; }
public bool IsProtected { get; set; } = true;
public bool IsReadOnly { get; set; } = false;
public bool IsVisible => this.visibilityResolver();
public string Name => nameResolver?.Invoke();
public Task<ILibraryContainer> GetContainer(Action<double, string> reportProgress)
{
return Task.FromResult(this.containerCreator());
@ -78,15 +74,7 @@ namespace MatterHackers.MatterControl.Library
public Task<ImageBuffer> GetThumbnail(int width, int height)
{
if (microIcon != null
&& width < 24
&& height < 24)
{
return Task.FromResult(microIcon?.AlphaToPrimaryAccent());
}
//return Task.FromResult(thumbnail);
return Task.FromResult(thumbnail?.AlphaToPrimaryAccent());
}
}
}
}

View file

@ -47,6 +47,10 @@ namespace MatterHackers.MatterControl.Library
private bool isDirty;
private string keywordFilter;
private long lastTimeContentsChanged;
private RunningInterval waitingForRefresh;
public FileSystemContainer(string fullPath)
{
this.CustomSearch = this;
@ -57,7 +61,7 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>();
#if !__ANDROID__
if (AggContext.OperatingSystem == OSType.Windows
&& Directory.Exists(fullPath))
{
@ -72,9 +76,10 @@ namespace MatterHackers.MatterControl.Library
// Begin watching.
directoryWatcher.EnableRaisingEvents = true;
}
#endif
}
public override ICustomSearch CustomSearch { get; }
public string FullPath { get; protected set; }
// Indicates if the new AMF file should use the original file name incremented until no name collision occurs
@ -86,7 +91,91 @@ namespace MatterHackers.MatterControl.Library
base.Activate();
}
public override ICustomSearch CustomSearch { get; }
public async override void Add(IEnumerable<ILibraryItem> items)
{
if (!items.Any())
{
return;
}
if (directoryWatcher != null)
{
directoryWatcher.EnableRaisingEvents = false;
}
Directory.CreateDirectory(this.FullPath);
await Task.Run(async () =>
{
foreach (var item in items)
{
switch (item)
{
case CreateFolderItem newFolder:
string targetFolderPath = Path.Combine(this.FullPath, newFolder.Name);
// TODO: write adaption of GetNonCollidingName for directories
Directory.CreateDirectory(targetFolderPath);
this.isDirty = true;
break;
case ILibraryAssetStream streamItem:
string targetPath = Path.Combine(this.FullPath, streamItem.FileName);
try
{
if (File.Exists(targetPath))
{
targetPath = GetNonCollidingName(Path.GetFileName(targetPath));
}
using (var outputStream = File.OpenWrite(targetPath))
using (var contentStream = await streamItem.GetStream(null))
{
contentStream.Stream.CopyTo(outputStream);
}
this.Items.Add(new FileSystemFileItem(targetPath));
this.isDirty = true;
}
catch (Exception ex)
{
UiThread.RunOnIdle(() =>
{
ApplicationController.Instance.LogError($"Error adding file: {targetPath}\r\n{ex.Message}");
});
}
break;
}
}
});
if (directoryWatcher != null)
{
directoryWatcher.EnableRaisingEvents = false;
}
if (this.isDirty)
{
this.ReloadContent();
}
}
public void ApplyFilter(string filter, ILibraryContext libraryContext)
{
keywordFilter = filter;
this.Load();
this.OnContentChanged();
}
public void ClearFilter()
{
keywordFilter = null;
this.Load();
this.OnContentChanged();
}
public override void Deactivate()
{
@ -107,37 +196,6 @@ namespace MatterHackers.MatterControl.Library
}
}
long lastTimeContentsChanged;
private RunningInterval waitingForRefresh;
private void DirectoryContentsChanged(object sender, EventArgs e)
{
// Flag for reload
isDirty = true;
lastTimeContentsChanged = UiThread.CurrentTimerMs;
// Only refresh content if we're the active container
if (isActiveContainer
&& waitingForRefresh == null)
{
waitingForRefresh = UiThread.SetInterval(WaitToRefresh, .5);
}
}
private void WaitToRefresh()
{
if (UiThread.CurrentTimerMs > lastTimeContentsChanged + 500
&& waitingForRefresh != null)
{
UiThread.ClearInterval(waitingForRefresh);
waitingForRefresh = null;
this.ReloadContent();
}
}
public override void Load()
{
this.Load(false);
@ -194,119 +252,6 @@ namespace MatterHackers.MatterControl.Library
}
}
private bool FileNameContainsFilter(string filename, string filter)
{
string nameWithSpaces = Path.GetFileNameWithoutExtension(filename.Replace('_', ' '));
// Split the filter on word boundaries and determine if all terms in the given file name
foreach (string word in filter.Split(' '))
{
if (nameWithSpaces.IndexOf(word, StringComparison.OrdinalIgnoreCase) == -1)
{
return false;
}
}
return true;
}
private string GetNonCollidingName(string fileName)
{
// Switching from .stl, .obj or similar to AMF. Save the file and update the
// the filename with an incremented (n) value to reflect the extension change in the UI
var similarFileNames = Directory.GetFiles(this.FullPath, $"{Path.GetFileNameWithoutExtension(fileName)}.*");
// ;
var validName = agg_basics.GetNonCollidingName(fileName, (testName) => !File.Exists(testName));
return validName;
}
public void ApplyFilter(string filter, ILibraryContext libraryContext)
{
keywordFilter = filter;
this.Load();
this.OnContentChanged();
}
public void ClearFilter()
{
keywordFilter = null;
this.Load();
this.OnContentChanged();
}
public async override void Add(IEnumerable<ILibraryItem> items)
{
if (!items.Any())
{
return;
}
if (directoryWatcher != null)
{
directoryWatcher.EnableRaisingEvents = false;
}
Directory.CreateDirectory(this.FullPath);
await Task.Run(async () =>
{
foreach (var item in items)
{
switch (item)
{
case CreateFolderItem newFolder:
string targetFolderPath = Path.Combine(this.FullPath, newFolder.Name);
// TODO: write adaption of GetNonCollidingName for directories
Directory.CreateDirectory(targetFolderPath);
this.isDirty = true;
break;
case ILibraryAssetStream streamItem:
string targetPath = Path.Combine(this.FullPath, streamItem.FileName);
try
{
if (File.Exists(targetPath))
{
targetPath = GetNonCollidingName(Path.GetFileName(targetPath));
}
using (var outputStream = File.OpenWrite(targetPath))
using (var contentStream = await streamItem.GetStream(null))
{
contentStream.Stream.CopyTo(outputStream);
}
this.Items.Add(new FileSystemFileItem(targetPath));
this.isDirty = true;
}
catch (Exception ex)
{
UiThread.RunOnIdle(() =>
{
ApplicationController.Instance.LogError($"Error adding file: {targetPath}\r\n{ex.Message}");
});
}
break;
}
}
});
if (directoryWatcher != null)
{
directoryWatcher.EnableRaisingEvents = false;
}
if (this.isDirty)
{
this.ReloadContent();
}
}
public override void Remove(IEnumerable<ILibraryItem> items)
{
// Removing content from the filesystem can have devastating effects - open a shell window allowing the customer make changes as they seem fit
@ -351,6 +296,61 @@ namespace MatterHackers.MatterControl.Library
}
}
private void DirectoryContentsChanged(object sender, EventArgs e)
{
// Flag for reload
isDirty = true;
lastTimeContentsChanged = UiThread.CurrentTimerMs;
// Only refresh content if we're the active container
if (isActiveContainer
&& waitingForRefresh == null)
{
waitingForRefresh = UiThread.SetInterval(WaitToRefresh, .5);
}
}
private bool FileNameContainsFilter(string filename, string filter)
{
string nameWithSpaces = Path.GetFileNameWithoutExtension(filename.Replace('_', ' '));
// Split the filter on word boundaries and determine if all terms in the given file name
foreach (string word in filter.Split(' '))
{
if (nameWithSpaces.IndexOf(word, StringComparison.OrdinalIgnoreCase) == -1)
{
return false;
}
}
return true;
}
private string GetNonCollidingName(string fileName)
{
// Switching from .stl, .obj or similar to AMF. Save the file and update the
// the filename with an incremented (n) value to reflect the extension change in the UI
var similarFileNames = Directory.GetFiles(this.FullPath, $"{Path.GetFileNameWithoutExtension(fileName)}.*");
// ;
var validName = agg_basics.GetNonCollidingName(fileName, (testName) => !File.Exists(testName));
return validName;
}
private void WaitToRefresh()
{
if (UiThread.CurrentTimerMs > lastTimeContentsChanged + 500
&& waitingForRefresh != null)
{
UiThread.ClearInterval(waitingForRefresh);
waitingForRefresh = null;
this.ReloadContent();
}
}
public class DirectoryContainerLink : FileSystemItem, ILibraryContainerLink
{
public DirectoryContainerLink(string path)
@ -372,4 +372,4 @@ namespace MatterHackers.MatterControl.Library
}
}
}
}
}

View file

@ -30,24 +30,12 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.IO;
using System.Threading.Tasks;
using MatterHackers.DataConverters3D;
namespace MatterHackers.MatterControl.Library
{
public class FileSystemFileItem : FileSystemItem, ILibraryAssetStream
{
public string FileName => System.IO.Path.GetFileName(this.Path);
public string ContentType => System.IO.Path.GetExtension(this.Path).ToLower().Trim('.');
public string AssetPath => this.Path;
/// <summary>
// Gets the size, in bytes, of the current file.
/// </summary>
public long FileSize { get; private set; }
public FileSystemFileItem(string path)
public FileSystemFileItem(string path)
: base(path)
{
var fileInfo = new FileInfo(path);
@ -57,6 +45,17 @@ namespace MatterHackers.MatterControl.Library
}
}
public string AssetPath => this.Path;
public string ContentType => System.IO.Path.GetExtension(this.Path).ToLower().Trim('.');
public string FileName => System.IO.Path.GetFileName(this.Path);
/// <summary>
/// Gets the size, in bytes, of the current file.
/// </summary>
public long FileSize { get; private set; }
public Task<StreamAndLength> GetStream(Action<double, string> reportProgress)
{
if (File.Exists(this.Path)
@ -75,4 +74,4 @@ namespace MatterHackers.MatterControl.Library
return Task.FromResult<StreamAndLength>(null);
}
}
}
}

View file

@ -27,9 +27,9 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using MatterHackers.Agg;
using System;
using System.IO;
using MatterHackers.Agg;
namespace MatterHackers.MatterControl.Library
{
@ -40,12 +40,6 @@ namespace MatterHackers.MatterControl.Library
{
private string fileName;
public string Path { get; set; }
public string Category { get; set; }
public virtual bool IsProtected => false;
public virtual bool IsVisible => true;
public virtual bool LocalContentExists => true;
public FileSystemItem(string path)
{
this.Path = path;
@ -76,12 +70,20 @@ namespace MatterHackers.MatterControl.Library
}
}
public virtual string ID => agg_basics.GetLongHashCode(this.Path).ToString();
public string Category { get; set; }
public DateTime DateCreated { get; }
public DateTime DateModified { get; }
public virtual string ID => agg_basics.GetLongHashCode(this.Path).ToString();
public virtual bool IsProtected => false;
public virtual bool IsVisible => true;
public virtual bool LocalContentExists => true;
public virtual string Name
{
get
@ -93,25 +95,13 @@ namespace MatterHackers.MatterControl.Library
return fileName;
}
set
{
fileName = value;
}
}
public string Path { get; set; }
}
public class MockLibraryItem : ILibraryItem
{
public string ID { get; set; }
public string Name { get; set; }
public bool IsProtected => true;
public bool IsVisible => true;
public DateTime DateCreated { get; } = DateTime.Now;
public DateTime DateModified { get; } = DateTime.Now;
}
}
}

View file

@ -0,0 +1,51 @@
/*
Copyright (c) 2017, 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 System;
using System.IO;
namespace MatterHackers.MatterControl.Library
{
public class MockLibraryItem : ILibraryItem
{
public DateTime DateCreated { get; } = DateTime.Now;
public DateTime DateModified { get; } = DateTime.Now;
public string ID { get; set; }
public bool IsProtected => true;
public bool IsVisible => true;
public string Name { get; set; }
}
}

View file

@ -30,7 +30,6 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using MatterHackers.Agg;
@ -55,7 +54,7 @@ namespace MatterHackers.MatterControl.Library
public string self;
}
private PrinterConfig printer;
private readonly PrinterConfig printer;
public string Account { get; }
@ -91,7 +90,7 @@ namespace MatterHackers.MatterControl.Library
// Get all files from a repo
public async Task GetRepo()
{
HttpClient client = new HttpClient();
var client = new HttpClient();
await ReadDirectory("root",
client,
$"https://api.github.com/repos/{Account}/{Repository}/contents/{RepoDirectory}");
@ -101,7 +100,7 @@ namespace MatterHackers.MatterControl.Library
private async Task ReadDirectory(string name, HttpClient client, string uri)
{
// get the directory contents
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
var request = new HttpRequestMessage(HttpMethod.Get, uri);
AddCromeHeaders(request);
// parse result
@ -118,7 +117,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => file.name,
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "calibration_library_folder.png")),
() => new GitHubContainer(printer, file.name, Account, Repository, RepoDirectory + "/" + file.name),
() =>

View file

@ -58,7 +58,7 @@ namespace MatterHackers.MatterControl.Library
public long FileSize { get; private set; }
public string ID { get; set; }
public string ID => agg_basics.GetLongHashCode(Url).ToString();
public bool IsLocked { get; internal set; }
@ -144,7 +144,7 @@ namespace MatterHackers.MatterControl.Library
try
{
// get the file contents;
HttpRequestMessage downLoadUrl = new HttpRequestMessage(HttpMethod.Get, Url);
var downLoadUrl = new HttpRequestMessage(HttpMethod.Get, Url);
GitHubContainer.AddCromeHeaders(downLoadUrl);
using (var client = new HttpClient())

View file

@ -32,7 +32,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
@ -43,9 +42,11 @@ namespace MatterHackers.MatterControl.Library
{
public interface ILibraryContext
{
ILibraryContainer ActiveContainer { get; set; }
event EventHandler<ContainerChangedEventArgs> ContainerChanged;
event EventHandler<ContainerChangedEventArgs> ContentChanged;
ILibraryContainer ActiveContainer { get; set; }
}
public class ContainerChangedEventArgs : EventArgs
@ -57,24 +58,21 @@ namespace MatterHackers.MatterControl.Library
}
public ILibraryContainer ActiveContainer { get; }
public ILibraryContainer PreviousContainer { get; }
}
public class LibraryConfig : ILibraryContext
{
public event EventHandler<ContainerChangedEventArgs> ContainerChanged;
public Dictionary<string, IContentProvider> ContentProviders = new Dictionary<string, IContentProvider>();
public event EventHandler<ContainerChangedEventArgs> ContentChanged;
private static ImageBuffer defaultFolderIcon = AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder.png")).SetPreMultiply();
private List<ILibraryContainerLink> libraryProviders;
private static ImageBuffer defaultItemIcon = AggContext.StaticData.LoadIcon(Path.Combine("Library", "file.png"));
private ILibraryContainer activeContainer;
private static ImageBuffer defaultFolderIcon = AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder.png")).SetPreMultiply();
private static ImageBuffer defaultFolderIconx20 = AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder_20x20.png")).SetPreMultiply();
private static ImageBuffer defaultItemIcon = AggContext.StaticData.LoadIcon(Path.Combine("Library", "file.png"));
private static ImageBuffer defaultItemIconx20 = AggContext.StaticData.LoadIcon(Path.Combine("Library", "file_20x20.png"));
private List<ILibraryContainerLink> libraryProviders;
public LibraryConfig()
{
@ -85,13 +83,14 @@ namespace MatterHackers.MatterControl.Library
this.ActiveContainer = this.RootLibaryContainer;
}
public ILibraryContainer RootLibaryContainer { get; }
public event EventHandler<ContainerChangedEventArgs> ContainerChanged;
public Dictionary<string, IContentProvider> ContentProviders = new Dictionary<string, IContentProvider>();
public event EventHandler<ContainerChangedEventArgs> ContentChanged;
public ILibraryContainer ActiveContainer
{
get => activeContainer;
set
{
if (activeContainer == value)
@ -133,12 +132,34 @@ namespace MatterHackers.MatterControl.Library
}
}
public PlatingHistoryContainer PlatingHistory { get; internal set; }
public LibraryCollectionContainer LibraryCollectionContainer { get; internal set; }
public List<LibraryAction> MenuExtensions { get; } = new List<LibraryAction>();
public PlatingHistoryContainer PlatingHistory { get; internal set; }
public ILibraryContainer RootLibaryContainer { get; }
public ImageBuffer EnsureCorrectThumbnailSizing(ImageBuffer thumbnail, int thumbWidth, int thumbHeight)
{
// Resize canvas to target as fallback
if (thumbnail.Width < thumbWidth || thumbnail.Height < thumbHeight)
{
thumbnail = LibraryListView.ResizeCanvas(thumbnail, thumbWidth, thumbHeight);
}
else if (thumbnail.Width > thumbWidth || thumbnail.Height > thumbHeight)
{
thumbnail = LibraryProviderHelpers.ResizeImage(thumbnail, thumbWidth, thumbHeight);
}
if (GuiWidget.DeviceScale != 1)
{
thumbnail = thumbnail.CreateScaledImage(GuiWidget.DeviceScale);
}
return thumbnail;
}
public IContentProvider GetContentProvider(ILibraryItem item)
{
string contentType = (item as ILibraryAssetStream)?.ContentType ?? (item as ILibraryObject3D)?.ContentType;
@ -158,43 +179,6 @@ namespace MatterHackers.MatterControl.Library
return provider;
}
public void RegisterContainer(ILibraryContainerLink containerItem)
{
libraryProviders.Add(containerItem);
libraryProviders.Sort(SortOnName);
}
private int SortOnName(ILibraryContainerLink x, ILibraryContainerLink y)
{
if (x != null && x.Name != null
&& y != null && y.Name != null)
{
return string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
}
return 0;
}
public void RegisterCreator(ILibraryObject3D libraryItem)
{
this.RootLibaryContainer.Items.Add(libraryItem);
}
public void RegisterCreator(ILibraryAssetStream libraryItem)
{
this.RootLibaryContainer.Items.Add(libraryItem);
}
private void ActiveContainer_ContentChanged(object sender, EventArgs args)
{
this.OnContainerChanged(this.ActiveContainer);
}
private void OnContainerChanged(ILibraryContainer container)
{
ContentChanged?.Invoke(this, new ContainerChangedEventArgs(container, null));
}
public bool IsContentFileType(string fileName)
{
string fileExtensionLower = Path.GetExtension(fileName).ToLower().Trim('.');
@ -275,21 +259,7 @@ namespace MatterHackers.MatterControl.Library
if (thumbnail == null)
{
// Use the listview defaults
if (thumbHeight < 24 && thumbWidth < 24)
{
thumbnail = ((libraryItem is ILibraryContainerLink) ? defaultFolderIconx20 : defaultItemIconx20);
//if (!theme.InvertIcons)
//{
// thumbnail = thumbnail.InvertLightness();
//}
thumbnail = thumbnail.MultiplyWithPrimaryAccent();
}
else
{
thumbnail = ((libraryItem is ILibraryContainerLink) ? defaultFolderIcon : defaultItemIcon).AlphaToPrimaryAccent();
}
thumbnail = ((libraryItem is ILibraryContainerLink) ? defaultFolderIcon : defaultItemIcon).AlphaToPrimaryAccent();
}
// TODO: Resolve and implement
@ -299,24 +269,20 @@ namespace MatterHackers.MatterControl.Library
setItemThumbnail(thumbnail);
}
public ImageBuffer EnsureCorrectThumbnailSizing(ImageBuffer thumbnail, int thumbWidth, int thumbHeight)
public void RegisterContainer(ILibraryContainerLink containerItem)
{
// Resize canvas to target as fallback
if (thumbnail.Width < thumbWidth || thumbnail.Height < thumbHeight)
{
thumbnail = LibraryListView.ResizeCanvas(thumbnail, thumbWidth, thumbHeight);
}
else if (thumbnail.Width > thumbWidth || thumbnail.Height > thumbHeight)
{
thumbnail = LibraryProviderHelpers.ResizeImage(thumbnail, thumbWidth, thumbHeight);
}
libraryProviders.Add(containerItem);
libraryProviders.Sort(SortOnName);
}
if (GuiWidget.DeviceScale != 1)
{
thumbnail = thumbnail.CreateScaledImage(GuiWidget.DeviceScale);
}
public void RegisterCreator(ILibraryObject3D libraryItem)
{
this.RootLibaryContainer.Items.Add(libraryItem);
}
return thumbnail;
public void RegisterCreator(ILibraryAssetStream libraryItem)
{
this.RootLibaryContainer.Items.Add(libraryItem);
}
/// <summary>
@ -326,5 +292,26 @@ namespace MatterHackers.MatterControl.Library
{
this.OnContainerChanged(this.ActiveContainer);
}
private void ActiveContainer_ContentChanged(object sender, EventArgs args)
{
this.OnContainerChanged(this.ActiveContainer);
}
private void OnContainerChanged(ILibraryContainer container)
{
ContentChanged?.Invoke(this, new ContainerChangedEventArgs(container, null));
}
private int SortOnName(ILibraryContainerLink x, ILibraryContainerLink y)
{
if (x != null && x.Name != null
&& y != null && y.Name != null)
{
return string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
}
return 0;
}
}
}
}

View file

@ -54,11 +54,6 @@ namespace MatterHackers.MatterControl.Library
public virtual Task<ImageBuffer> GetThumbnail(ILibraryItem item, int width, int height)
{
if (item is LocalZipContainerLink)
{
return Task.FromResult(AggContext.StaticData.LoadIcon(Path.Combine("Library", "zip_folder.png")).AlphaToPrimaryAccent().SetPreMultiply());
}
return Task.FromResult<ImageBuffer>(null);
}

View file

@ -55,7 +55,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Local Library".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "local_library_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "local_library_folder.png")),
() => new SqliteLibraryContainer(rootLibraryCollection.Id)));
}
@ -63,7 +62,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Calibration Parts".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "calibration_library_folder.png")),
() => new CalibrationPartsContainer())
{
@ -73,7 +71,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Primitives".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "primitives_library_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "primitives_library_folder.png")),
() => new PrimitivesContainer())
{
@ -91,7 +88,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Print Queue".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "queue_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "queue_folder.png")),
() => new PrintQueueContainer()));
}
@ -100,7 +96,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Pipe Works".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder.png")),
() => new PipeWorksContainer()));
@ -109,7 +104,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Experimental".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder.png")),
() => new DynamicContainer()
{

View file

@ -50,7 +50,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Plating History".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "history_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "history_folder.png")),
() => new PlatingHistoryContainer())
{
@ -60,7 +59,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Print History".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "history_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "history_folder.png")),
() => new PrintHistoryContainer()
{

View file

@ -54,7 +54,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => printer.Settings.GetValue(SettingsKey.printer_name),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "sd_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "sd_folder.png")),
() => new PrinterContainer(printer),
() =>

View file

@ -56,7 +56,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "SD Card".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "sd_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "sd_folder.png")),
() => new SDCardContainer(printer),
() =>
@ -71,16 +70,18 @@ namespace MatterHackers.MatterControl.Library
var containerName = $"{printer.Settings.GetValue(SettingsKey.make)} {"Parts".Localize()}";
var settings = printer.Settings;
var repository = "Machine_Library_Parts";
repository = "PulseOpenSource";
var subPath = $"{settings.GetValue(SettingsKey.make)}/{settings.GetValue(SettingsKey.model)}";
subPath = "C Frame";
this.ChildContainers.Add(
new DynamicContainerLink(
() => containerName,
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder.png")),
() => new GitHubContainer(printer,
containerName,
"MatterHackers",
repository,
$"{settings.GetValue(SettingsKey.make)}/{settings.GetValue(SettingsKey.model)}"),
subPath),
() => printer.Settings.GetValue<bool>(SettingsKey.has_fan)) // visibility
{
IsReadOnly = true
@ -89,7 +90,6 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers.Add(
new DynamicContainerLink(
() => "Calibration Parts".Localize(),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder_20x20.png")),
AggContext.StaticData.LoadIcon(Path.Combine("Library", "folder.png")),
() => new CalibrationPartsContainer())
{

View file

@ -42,12 +42,12 @@ namespace MatterHackers.MatterControl.Library
{
public class SDCardContainer : LibraryContainer
{
private bool gotBeginFileList;
private PrinterConfig printer;
private readonly PrinterConfig printer;
private AutoResetEvent autoResetEvent;
private bool gotBeginFileList;
public SDCardContainer(PrinterConfig printer)
{
this.ChildContainers = new List<ILibraryContainerLink>();
@ -73,10 +73,26 @@ namespace MatterHackers.MatterControl.Library
break;
}
}
printer.Connection.CommunicationStateChanged += CommunicationStateChanged;
printer.Disposed += (s, e) => printer.Connection.CommunicationStateChanged -= CommunicationStateChanged;
}
public override void Dispose()
{
// Ensure released
autoResetEvent?.Set();
}
// Container override of child thumbnails
public override Task<ImageBuffer> GetThumbnail(ILibraryItem item, int width, int height)
{
return Task.FromResult(
AggContext.StaticData.LoadIcon(
Path.Combine((width > 50 || height > 50) ? "icon_sd_card_115x115.png" : "icon_sd_card_50x50.png"),
ApplicationController.Instance.Theme.InvertIcons));
}
public override void Load()
{
this.Items.Clear();
@ -96,15 +112,6 @@ namespace MatterHackers.MatterControl.Library
}
}
// Container override of child thumbnails
public override Task<ImageBuffer> GetThumbnail(ILibraryItem item, int width, int height)
{
return Task.FromResult(
AggContext.StaticData.LoadIcon(
Path.Combine((width > 50 || height > 50) ? "icon_sd_card_115x115.png" : "icon_sd_card_50x50.png"),
ApplicationController.Instance.Theme.InvertIcons));
}
private void Printer_LineRead(object sender, string line)
{
if (line != null)
@ -139,16 +146,11 @@ namespace MatterHackers.MatterControl.Library
});
}
}
break;
}
}
}
}
public override void Dispose()
{
// Ensure released
autoResetEvent?.Set();
}
}
}
}

View file

@ -33,16 +33,16 @@ namespace MatterHackers.MatterControl.Library
{
public class SDCardFileItem : ILibraryItem
{
public string ID { get; } = Guid.NewGuid().ToString();
public DateTime DateCreated { get; } = DateTime.Now;
public string Name { get; set; }
public DateTime DateModified { get; } = DateTime.Now;
public string ID { get; } = Guid.NewGuid().ToString();
public bool IsProtected { get; } = true;
public bool IsVisible { get; } = true;
public DateTime DateCreated { get; } = DateTime.Now;
public DateTime DateModified { get; } = DateTime.Now;
public string Name { get; set; }
}
}
}

View file

@ -27,15 +27,15 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrintQueue;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrintQueue;
namespace MatterHackers.MatterControl.Library
{
@ -65,40 +65,6 @@ namespace MatterHackers.MatterControl.Library
public override ICustomSearch CustomSearch { get; }
public override void Load()
{
var childCollections = this.GetChildCollections();
var allFiles = this.GetLibraryItems(keywordFilter);
var zipFiles = allFiles.Where(f => string.Equals(Path.GetExtension(f.FileLocation), ".zip", StringComparison.OrdinalIgnoreCase));
var nonZipFiles = allFiles.Except(zipFiles);
IEnumerable<ILibraryContainerLink> childContainers = childCollections.Select(c => new SqliteLibraryContainerLink()
{
CollectionID = c.Id,
Name = c.Name
});
this.ChildContainers = childContainers.Concat(
zipFiles.Select(f => new LocalLibraryZipContainerLink(f.Id, f.FileLocation, f.Name))).OrderBy(d => d.Name).ToList();
// PrintItems projected onto FileSystemFileItem
this.Items = nonZipFiles.Select<PrintItem, ILibraryItem>(printItem =>
{
if (File.Exists(printItem.FileLocation))
{
return new SqliteFileItem(printItem);
}
else
{
return new MessageItem($"{printItem.Name} (Missing)");
// return new MissingFileItem() // Needs to return a content specific icon with a missing overlay - needs to lack all print operations
}
}).ToList();
}
public override async void Add(IEnumerable<ILibraryItem> items)
{
await Task.Run(async () =>
@ -149,20 +115,56 @@ namespace MatterHackers.MatterControl.Library
});
}
private List<PrintItem> GetLibraryItems(string keyphrase = null)
public void ApplyFilter(string filter, ILibraryContext libraryContext)
{
// TODO: String concatenation to build sql statements is the root of all sql injection attacks. This needs to be changed to use parameter objects as would be expected
string query;
if (string.IsNullOrEmpty(keyphrase))
{
query = $"SELECT * FROM PrintItem WHERE PrintItemCollectionID = {CollectionID} ORDER BY Name ASC;";
}
else
{
query = $"SELECT * FROM PrintItem WHERE PrintItemCollectionID = {CollectionID} AND Name LIKE '%{keyphrase}%' ORDER BY Name ASC;";
}
keywordFilter = filter;
this.Load();
this.OnContentChanged();
}
return Datastore.Instance.dbSQLite.Query<PrintItem>(query).ToList();
public void ClearFilter()
{
keywordFilter = null;
this.Load();
this.OnContentChanged();
}
public override void Dispose()
{
}
public override void Load()
{
var childCollections = this.GetChildCollections();
var allFiles = this.GetLibraryItems(keywordFilter);
var zipFiles = allFiles.Where(f => string.Equals(Path.GetExtension(f.FileLocation), ".zip", StringComparison.OrdinalIgnoreCase));
var nonZipFiles = allFiles.Except(zipFiles);
IEnumerable<ILibraryContainerLink> childContainers = childCollections.Select(c => new SqliteLibraryContainerLink()
{
CollectionID = c.Id,
Name = c.Name
});
this.ChildContainers = childContainers.Concat(
zipFiles.Select(f => new LocalLibraryZipContainerLink(f.Id, f.FileLocation, f.Name))).OrderBy(d => d.Name).ToList();
// PrintItems projected onto FileSystemFileItem
this.Items = nonZipFiles.Select<PrintItem, ILibraryItem>(printItem =>
{
if (File.Exists(printItem.FileLocation))
{
return new SqliteFileItem(printItem);
}
else
{
return new MessageItem($"{printItem.Name} (Missing)");
// return new MissingFileItem() // Needs to return a content specific icon with a missing overlay - needs to lack all print operations
}
}).ToList();
}
public override void Remove(IEnumerable<ILibraryItem> items)
@ -207,6 +209,12 @@ namespace MatterHackers.MatterControl.Library
this.ReloadContent();
}
protected List<PrintItemCollection> GetChildCollections()
{
return Datastore.Instance.dbSQLite.Query<PrintItemCollection>(
$"SELECT * FROM PrintItemCollection WHERE ParentCollectionID = {CollectionID} ORDER BY Name ASC;").ToList();
}
/// <summary>
/// Creates a database PrintItem entity, copies the source file to a new library
/// path and updates the PrintItem to point at the new target
@ -229,37 +237,31 @@ namespace MatterHackers.MatterControl.Library
printItem.Commit();
}
protected List<PrintItemCollection> GetChildCollections()
private List<PrintItem> GetLibraryItems(string keyphrase = null)
{
return Datastore.Instance.dbSQLite.Query<PrintItemCollection>(
$"SELECT * FROM PrintItemCollection WHERE ParentCollectionID = {CollectionID} ORDER BY Name ASC;").ToList();
}
// TODO: String concatenation to build sql statements is the root of all sql injection attacks. This needs to be changed to use parameter objects as would be expected
string query;
if (string.IsNullOrEmpty(keyphrase))
{
query = $"SELECT * FROM PrintItem WHERE PrintItemCollectionID = {CollectionID} ORDER BY Name ASC;";
}
else
{
query = $"SELECT * FROM PrintItem WHERE PrintItemCollectionID = {CollectionID} AND Name LIKE '%{keyphrase}%' ORDER BY Name ASC;";
}
public override void Dispose()
{
}
public void ApplyFilter(string filter, ILibraryContext libraryContext)
{
keywordFilter = filter;
this.Load();
this.OnContentChanged();
}
public void ClearFilter()
{
keywordFilter = null;
this.Load();
this.OnContentChanged();
return Datastore.Instance.dbSQLite.Query<PrintItem>(query).ToList();
}
public class SqliteLibraryContainerLink : ILibraryContainerLink
{
public string ID => "SqliteContainer" + this.CollectionID;
public int CollectionID { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; } = DateTime.Now;
public DateTime DateModified { get; } = DateTime.Now;
public string ID => "SqliteContainer" + this.CollectionID;
public bool IsProtected { get; set; } = false;
@ -267,9 +269,7 @@ namespace MatterHackers.MatterControl.Library
public bool IsVisible { get; set; } = true;
public DateTime DateCreated { get; } = DateTime.Now;
public DateTime DateModified { get; } = DateTime.Now;
public string Name { get; set; }
public Task<ILibraryContainer> GetContainer(Action<double, string> reportProgress)
{
@ -281,4 +281,4 @@ namespace MatterHackers.MatterControl.Library
}
}
}
}
}

View file

@ -32,7 +32,7 @@ namespace MatterHackers.MatterControl.Library
public class LocalLibraryZipContainerLink : LocalZipContainerLink
{
public LocalLibraryZipContainerLink(int id, string filePath, string nameOverride = null)
: base (filePath, nameOverride)
: base(filePath, nameOverride)
{
this.RowID = id;
}

View file

@ -37,12 +37,17 @@ namespace MatterHackers.MatterControl.Library
{
public class LocalZipContainerLink : FileSystemItem, ILibraryContainerLink
{
private static ImageBuffer thumbnail;
private static readonly ImageBuffer Thumbnail;
private string currentDirectory = "";
static LocalZipContainerLink()
{
thumbnail = AggContext.StaticData.LoadIcon(System.IO.Path.Combine("Library", "zip_folder.png")).SetPreMultiply();
Thumbnail = AggContext.StaticData.LoadIcon(System.IO.Path.Combine("Library", "zip_folder.png")).AlphaToPrimaryAccent().SetPreMultiply();
}
public virtual Task<ImageBuffer> GetThumbnail(ILibraryItem item, int width, int height)
{
return Task.FromResult<ImageBuffer>(Thumbnail);
}
public bool IsReadOnly { get; } = true;

View file

@ -27,13 +27,10 @@ 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.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.Library
{
@ -41,15 +38,19 @@ namespace MatterHackers.MatterControl.Library
{
private static char[] pathSeparators = new[] { '/', '\\' };
public string RelativeDirectory { get; set; }
private string pathSeparator = null;
public string Path { get; set; }
private string pathSeparator = null;
public string RelativeDirectory { get; set; }
public override void Dispose()
{
}
public override void Load()
{
//string hashCode = this.Url.GetHashCode().ToString();
// string hashCode = this.Url.GetHashCode().ToString();
var items = new Dictionary<string, long>();
var directories = new HashSet<string>();
@ -93,9 +94,5 @@ namespace MatterHackers.MatterControl.Library
this.Items = items.Select(kvp => new ZipMemoryItem(this.Path, RelativeDirectory.Length == 0 ? kvp.Key : $"{RelativeDirectory}{pathSeparator}{kvp.Key}", kvp.Value)).ToList<ILibraryItem>();
}
public override void Dispose()
{
}
}
}
}

View file

@ -27,12 +27,12 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using MatterHackers.Agg;
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg;
namespace MatterHackers.MatterControl.Library
{
@ -46,21 +46,21 @@ namespace MatterHackers.MatterControl.Library
this.FileSize = fileSize;
}
public override string ID => agg_basics.GetLongHashCode($"{this.Path}/{this.RelativePath}").ToString();
public string RelativePath { get; set; }
public string AssetPath { get; } = null;
public string ContentType => System.IO.Path.GetExtension(this.Name).ToLower().Trim('.');
public string AssetPath { get; } = null;
public string FileName => System.IO.Path.GetFileName(this.Name);
/// <summary>
// Gets the size, in bytes, of the current file.
/// Gets the size, in bytes, of the current file.
/// </summary>
public long FileSize { get; private set; }
public override string ID => agg_basics.GetLongHashCode($"{this.Path}/{this.RelativePath}").ToString();
public string RelativePath { get; set; }
public async Task<StreamAndLength> GetStream(Action<double, string> reportProgress)
{
var memStream = await Task.Run(() =>
@ -87,4 +87,4 @@ namespace MatterHackers.MatterControl.Library
};
}
}
}
}

View file

@ -656,7 +656,7 @@ namespace MatterHackers.MatterControl.PrintLibrary
menuActions.Add(new LibraryAction(ActionScope.ListView)
{
Title = "Create Folder...".Localize(),
Title = "Create Folder".Localize() + "...",
Icon = AggContext.StaticData.LoadIcon("fa-folder-new_16.png", 16, 16, ApplicationController.Instance.MenuTheme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{

View file

@ -38,7 +38,9 @@ namespace MatterHackers.MatterControl.PrintQueue
public enum ActionScope
{
ListItem,
ListView,
None
}
@ -49,14 +51,17 @@ namespace MatterHackers.MatterControl.PrintQueue
this.Scope = scope;
}
public string Title { get; set; }
public Action<IEnumerable<ILibraryItem>, LibraryListView> Action { get; set; }
public Func<IEnumerable<ListViewItem>, LibraryListView, bool> IsEnabled { get; set; }
public string ToolTipText { get; internal set; }
public ImageBuffer Icon { get; internal set; }
public Func<IEnumerable<ListViewItem>, LibraryListView, bool> IsEnabled { get; set; }
public ActionScope Scope { get; }
public string Title { get; set; }
public string ToolTipText { get; internal set; }
}
public class MenuSeparator : LibraryAction