Merge pull request #2528 from jlewin/design_tools

Design tools
This commit is contained in:
johnlewin 2017-10-09 15:01:09 -07:00 committed by GitHub
commit 486adee702
28 changed files with 679 additions and 429 deletions

View file

@ -195,8 +195,7 @@ namespace MatterHackers.MatterControl
{
lock(thumbsLock)
{
if (thumbnailGenerator == null
|| thumbnailGenerator.IsCompleted)
if (thumbnailGenerator == null)
{
// Spin up a new thread once needed
thumbnailGenerator = Task.Run((Action)ThumbGeneration);
@ -211,7 +210,7 @@ namespace MatterHackers.MatterControl
{
Thread.CurrentThread.Name = $"ThumbnailGeneration";
while(!MatterControlApplication.Instance.HasBeenClosed)
while(!MatterControlApplication.Instance.ApplicationExiting)
{
Thread.Sleep(100);
@ -235,13 +234,16 @@ namespace MatterHackers.MatterControl
}
catch (ThreadAbortException e)
{
return;
Console.WriteLine("ThumbGeneration Thread abort");
}
catch (Exception ex)
{
Console.WriteLine("Error generating thumbnail: " + ex.Message);
}
}
// Null task reference on exit
thumbnailGenerator = null;
}
public static Func<PrinterInfo,string, Task<PrinterSettings>> GetPrinterProfileAsync;
@ -343,20 +345,18 @@ namespace MatterHackers.MatterControl
var rootLibraryCollection = Datastore.Instance.dbSQLite.Table<PrintItemCollection>().Where(v => v.Name == "_library").Take(1).FirstOrDefault();
if (rootLibraryCollection != null)
{
int rooteLibraryID = rootLibraryCollection.Id;
this.Library.RegisterRootProvider(
new DynamicContainerLink(
"Local Library".Localize(),
LibraryProviderHelpers.LoadInvertIcon("FileDialog", "library_folder.png"),
() => new SqliteLibraryContainer(rooteLibraryID)));
() => new SqliteLibraryContainer(rootLibraryCollection.Id)));
}
this.Library.RegisterRootProvider(
new DynamicContainerLink(
"Print History".Localize(),
LibraryProviderHelpers.LoadInvertIcon("FileDialog", "folder.png"),
() => new HistoryContainer())
() => new PrintHistoryContainer())
{
IsReadOnly = true
});
@ -478,6 +478,14 @@ namespace MatterHackers.MatterControl
}, ref unregisterEvents);
}
internal void Shutdown()
{
// Ensure all threads shutdown gracefully on close
// Release any waiting generator threads
thumbGenResetEvent?.Set();
}
public void StartSignIn()
{
if (this.ActivePrinter.Connection.PrinterIsPrinting
@ -619,7 +627,7 @@ namespace MatterHackers.MatterControl
}, "Are you sure you want to sign out? You will not have access to your printer profiles or cloud library.".Localize(), "Sign Out?".Localize(), StyledMessageBox.MessageType.YES_NO, "Sign Out".Localize(), "Cancel".Localize());
}
else // just run the sign out event
{
{
SignOutAction?.Invoke();
}
}
@ -823,7 +831,6 @@ namespace MatterHackers.MatterControl
}
}
if (this.ActivePrinter.Settings.PrinterSelected
&& this.ActivePrinter.Settings.GetValue<bool>(SettingsKey.auto_connect))
{

View file

@ -53,7 +53,7 @@ namespace MatterHackers.MatterControl.PrintHistory
public ListViewItemBase AddItem(ListViewItem item)
{
var historyRowItem = item.Model as HistoryRowItem;
var historyRowItem = item.Model as PrintHistoryItem;
var detailsView = new PrintHistoryListItem(item, this.ThumbWidth, this.ThumbHeight, historyRowItem?.PrintTask, true);
this.AddChild(detailsView);

View file

@ -49,11 +49,6 @@ namespace MatterHackers.MatterControl.Library
}
}
public static void AddItem(this ILibraryContainer container, PrintItemWrapper printeItemWrapper)
{
throw new NotImplementedException("container.AddItem(PrintItemWrapper)");
}
public static void Add(this Dictionary<string, IContentProvider> list, IEnumerable<string> extensions, IContentProvider provider)
{
foreach (var extension in extensions)

View file

@ -44,7 +44,7 @@ namespace MatterHackers.MatterControl.Library
Type DefaultView { get; }
event EventHandler Reloaded;
event EventHandler ContentChanged;
List<ILibraryContainerLink> ChildContainers { get; }
List<ILibraryItem> Items { get; }
@ -55,6 +55,7 @@ namespace MatterHackers.MatterControl.Library
void Deactivate();
void Activate();
void Load();
}
public interface ILibraryWritableContainer : ILibraryContainer

View file

@ -72,7 +72,6 @@ namespace MatterHackers.MatterControl.Library
directoryWatcher.EnableRaisingEvents = true;
}
#endif
GetFilesAndCollectionsInCurrentDirectory();
}
// Indicates if the new AMF file should use the original file name incremented until no name collision occurs
@ -81,12 +80,6 @@ namespace MatterHackers.MatterControl.Library
public override void Activate()
{
this.isActiveContainer = true;
if (isDirty)
{
// Requires reload
GetFilesAndCollectionsInCurrentDirectory();
}
base.Activate();
}
@ -109,11 +102,6 @@ namespace MatterHackers.MatterControl.Library
if (keywordFilter != value)
{
keywordFilter = value;
if (isActiveContainer)
{
GetFilesAndCollectionsInCurrentDirectory(true);
}
}
}
}
@ -139,66 +127,63 @@ namespace MatterHackers.MatterControl.Library
// Only refresh content if we're the active container
if (isActiveContainer)
{
GetFilesAndCollectionsInCurrentDirectory();
this.Load(false);
}
}
private async void GetFilesAndCollectionsInCurrentDirectory(bool recursive = false)
public override void Load()
{
this.Load(false);
}
public void Load(bool recursive)
{
SearchOption searchDepth = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
await Task.Run(() =>
try
{
try
string filter = this.KeywordFilter.Trim();
var allFiles = Directory.GetFiles(fullPath, "*.*", searchDepth);
var zipFiles = allFiles.Where(f => Path.GetExtension(f).IndexOf(".zip", StringComparison.OrdinalIgnoreCase) != -1);
var nonZipFiles = allFiles.Except(zipFiles);
List<ILibraryContainerLink> containers;
if (filter == "")
{
string filter = this.KeywordFilter.Trim();
var allFiles = Directory.GetFiles(fullPath, "*.*", searchDepth);
var zipFiles = allFiles.Where(f => Path.GetExtension(f).IndexOf(".zip", StringComparison.OrdinalIgnoreCase) != -1);
var nonZipFiles = allFiles.Except(zipFiles);
List<ILibraryContainerLink> containers;
if (filter == "")
{
var directories = Directory.GetDirectories(fullPath, "*.*", searchDepth).Select(p => new DirectoryContainerLink(p)).ToList<ILibraryContainerLink>();
containers = directories.Concat(zipFiles.Select(f => new LocalZipContainerLink(f))).OrderBy(d => d.Name).ToList();
}
else
{
containers = new List<ILibraryContainerLink>();
}
var matchedFiles = (filter == "") ? nonZipFiles : nonZipFiles.Where(filePath =>
{
string fileName = Path.GetFileName(filePath);
return FileNameContainsFilter(filePath, filter)
&& ApplicationController.Instance.Library.IsContentFileType(fileName);
});
UiThread.RunOnIdle(() =>
{
// Matched containers
this.ChildContainers = containers;
// Matched files projected onto FileSystemFileItem
this.Items = matchedFiles.OrderBy(f => f).Select(f => new FileSystemFileItem(f)).ToList<ILibraryItem>();
this.isDirty = false;
this.OnReloaded();
});
var directories = Directory.GetDirectories(fullPath, "*.*", searchDepth).Select(p => new DirectoryContainerLink(p)).ToList<ILibraryContainerLink>();
containers = directories.Concat(zipFiles.Select(f => new LocalZipContainerLink(f))).OrderBy(d => d.Name).ToList();
}
catch (Exception ex)
else
{
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>()
{
new MessageItem("Error loading container - " + ex.Message)
};
containers = new List<ILibraryContainerLink>();
}
});
var matchedFiles = (filter == "") ? nonZipFiles : nonZipFiles.Where(filePath =>
{
string fileName = Path.GetFileName(filePath);
return FileNameContainsFilter(filePath, filter)
&& ApplicationController.Instance.Library.IsContentFileType(fileName);
});
// Matched containers
this.ChildContainers = containers;
// Matched files projected onto FileSystemFileItem
this.Items = matchedFiles.OrderBy(f => f).Select(f => new FileSystemFileItem(f)).ToList<ILibraryItem>();
this.isDirty = false;
}
catch (Exception ex)
{
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>()
{
new MessageItem("Error loading container - " + ex.Message)
};
}
}
private bool FileNameContainsFilter(string filename, string filter)
@ -217,8 +202,6 @@ namespace MatterHackers.MatterControl.Library
return true;
}
#region Container Actions
private string GetNonCollidingName(string fileName)
{
string incrementedFilePath;
@ -241,7 +224,7 @@ namespace MatterHackers.MatterControl.Library
incrementedFilePath = Path.Combine(this.fullPath, $"{fileName} ({foundCount++}){fileExtension}");
// Continue incrementing while any matching file exists
} while (Directory.GetFiles(incrementedFilePath).Any());
} while (File.Exists(incrementedFilePath));
return incrementedFilePath;
}
@ -307,10 +290,9 @@ namespace MatterHackers.MatterControl.Library
if (this.isDirty)
{
this.GetFilesAndCollectionsInCurrentDirectory();
this.OnContentChanged();
}
}
public override void Remove(IEnumerable<ILibraryItem> items)
{
@ -324,12 +306,7 @@ namespace MatterHackers.MatterControl.Library
{
if (Directory.Exists(directoryLink.Path))
{
//string destPath = Path.Combine(Path.GetDirectoryName(fileSystemContainer.fullPath), revisedName);
//Directory.Move(fileSystemContainer.fullPath, destPath);
//await Task.Delay(150);
//GetFilesAndCollectionsInCurrentDirectory();
Process.Start(this.fullPath);
}
}
else if (item is FileSystemFileItem fileItem)
@ -345,13 +322,11 @@ namespace MatterHackers.MatterControl.Library
fileItem.Path = destFile;
this.OnReloaded();
this.OnContentChanged();
}
}
}
#endregion
public class DirectoryContainerLink : FileSystemItem, ILibraryContainerLink
{
public DirectoryContainerLink(string path)

View file

@ -39,7 +39,7 @@ namespace MatterHackers.MatterControl.Library
{
ILibraryContainer ActiveContainer { get; set; }
event EventHandler<ContainerChangedEventArgs> ContainerChanged;
event EventHandler<ContainerChangedEventArgs> ContainerReloaded;
event EventHandler<ContainerChangedEventArgs> ContentChanged;
}
public class ContainerChangedEventArgs : EventArgs
@ -57,7 +57,7 @@ namespace MatterHackers.MatterControl.Library
public class LibraryConfig : ILibraryContext
{
public event EventHandler<ContainerChangedEventArgs> ContainerChanged;
public event EventHandler<ContainerChangedEventArgs> ContainerReloaded;
public event EventHandler<ContainerChangedEventArgs> ContentChanged;
// TODO: Needed?
public event EventHandler LibraryItemsChanged;
@ -65,7 +65,7 @@ namespace MatterHackers.MatterControl.Library
private List<ILibraryContainerLink> libraryProviders;
private ILibraryContainer activeContainer;
public LibraryConfig()
{
libraryProviders = new List<ILibraryContainerLink>();
@ -101,7 +101,7 @@ namespace MatterHackers.MatterControl.Library
if (activeContainer != null)
{
activeContainer.Deactivate();
activeContainer.Reloaded -= ActiveContainer_Reloaded;
activeContainer.ContentChanged -= ActiveContainer_ContentChanged;
activeContainer.KeywordFilter = "";
// If the new container is an ancestor of the active container we need to Dispose everyone up to that point
@ -118,7 +118,7 @@ namespace MatterHackers.MatterControl.Library
activeContainer = newContainer;
activeContainer.Activate();
activeContainer.Reloaded += ActiveContainer_Reloaded;
activeContainer.ContentChanged += ActiveContainer_ContentChanged;
ContainerChanged?.Invoke(this, eventArgs);
}
@ -149,12 +149,6 @@ namespace MatterHackers.MatterControl.Library
OnLibraryItemsChanged();
}
public void RegisterCreator(ILibraryContainerLink containerItem)
{
this.RootLibaryContainer.ChildContainers.Add(containerItem);
OnLibraryItemsChanged();
}
public void RegisterCreator(ILibraryContentItem libraryItem)
{
this.RootLibaryContainer.Items.Add(libraryItem);
@ -172,14 +166,14 @@ namespace MatterHackers.MatterControl.Library
LibraryItemsChanged?.Invoke(this, null);
}
private void ActiveContainer_Reloaded(object sender, EventArgs args)
private void ActiveContainer_ContentChanged(object sender, EventArgs args)
{
this.OnContainerChanged(this.ActiveContainer);
}
private void OnContainerChanged(ILibraryContainer container)
{
ContainerReloaded?.Invoke(this, new ContainerChangedEventArgs(container, null));
ContentChanged?.Invoke(this, new ContainerChangedEventArgs(container, null));
}
public bool IsContentFileType(string fileName)

View file

@ -36,7 +36,7 @@ namespace MatterHackers.MatterControl.Library
{
public abstract class LibraryContainer : ILibraryContainer
{
public event EventHandler Reloaded;
public event EventHandler ContentChanged;
public string ID { get; set; }
public string Name { get; set; }
@ -59,11 +59,13 @@ namespace MatterHackers.MatterControl.Library
public virtual string KeywordFilter { get; set; } = "";
protected void OnReloaded()
protected void OnContentChanged()
{
this.Reloaded?.Invoke(this, null);
this.ContentChanged?.Invoke(this, null);
}
public abstract void Load();
public virtual void Dispose()
{
}

View file

@ -30,7 +30,6 @@ either expressed or implied, of the FreeBSD Project.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
@ -44,43 +43,36 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>();
this.Name = "Calibration Parts".Localize();
this.ReloadContainer();
}
private void ReloadContainer()
public override void Load()
{
Task.Run(() =>
// TODO: Long term do we want to have multiple categories in the view - OEM parts and printer specific calibration parts? Easy to do if so
/*
IEnumerable<string> printerFiles;
string printerCalibrationFiles = ActiveSliceSettings.Instance.GetValue("calibration_files");
if (string.IsNullOrEmpty(printerCalibrationFiles))
{
// TODO: Long term do we want to have multiple categories in the view - OEM parts and printer specific calibration parts? Easy to do if so
/*
IEnumerable<string> printerFiles;
return;
}
string printerCalibrationFiles = ActiveSliceSettings.Instance.GetValue("calibration_files");
if (string.IsNullOrEmpty(printerCalibrationFiles))
{
return;
}
string[] calibrationPrintFileNames = printerCalibrationFiles.Split(';');
if (calibrationPrintFileNames.Length < 0)
{
printerFiles = Enumerable.Empty<string>();
}
else
{
printerFiles = calibrationPrintFileNames;
} */
string[] calibrationPrintFileNames = printerCalibrationFiles.Split(';');
if (calibrationPrintFileNames.Length < 0)
{
printerFiles = Enumerable.Empty<string>();
}
else
{
printerFiles = calibrationPrintFileNames;
} */
var oemParts = AggContext.StaticData.GetFiles(Path.Combine("OEMSettings", "SampleParts"));
Items = oemParts.Select(s =>
{
// TODO: Won't work on Android - make stream based
return new FileSystemFileItem(AggContext.StaticData.MapPath(s));
}).ToList<ILibraryItem>();
UiThread.RunOnIdle(this.OnReloaded);
});
var oemParts = AggContext.StaticData.GetFiles(Path.Combine("OEMSettings", "SampleParts"));
Items = oemParts.Select(s =>
{
// TODO: Won't work on Android - make stream based
return new FileSystemFileItem(AggContext.StaticData.MapPath(s));
}).ToList<ILibraryItem>();
}
public override void Dispose()

View file

@ -27,17 +27,27 @@ 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.Localizations;
using MatterHackers.MatterControl.PrintHistory;
namespace MatterHackers.MatterControl.Library
{
public class CreatorsContainer : LibraryContainer
public class PrintHistoryContainer : LibraryContainer
{
public CreatorsContainer()
public PrintHistoryContainer()
{
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>();
this.Name = "Print History".Localize();
this.DefaultView = typeof(HistoryListView);
}
public override void Dispose()
public override void Load()
{
// PrintItems projected onto FileSystemFileItem
Items = PrintHistoryData.Instance.GetHistoryItems(25).Select(f => new PrintHistoryItem(f)).ToList<ILibraryItem>();
}
}
}

View file

@ -28,19 +28,14 @@ either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrintHistory;
namespace MatterHackers.MatterControl.Library
{
public class HistoryRowItem : ILibraryContentStream
public class PrintHistoryItem : ILibraryContentStream
{
public HistoryRowItem(PrintTask printTask)
public PrintHistoryItem(PrintTask printTask)
{
this.PrintTask = printTask;
}
@ -64,38 +59,10 @@ namespace MatterHackers.MatterControl.Library
public bool IsVisible => true;
public bool LocalContentExists => true;
public Task<StreamAndLength> GetContentStream(Action<double, string> reportProgress)
{
throw new NotImplementedException();
}
}
public class HistoryContainer : LibraryContainer
{
public HistoryContainer()
{
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>();
this.Name = "Print History".Localize();
this.DefaultView = typeof(HistoryListView);
//PrintHistoryData.Instance.ItemAdded.RegisterEvent((sender, e) => OnDataReloaded(null), ref unregisterEvent);
this.ReloadContainer();
}
private void ReloadContainer()
{
Task.Run(() =>
{
var printHistory = PrintHistoryData.Instance.GetHistoryItems(25);
// PrintItems projected onto FileSystemFileItem
Items = printHistory.Select(f => new HistoryRowItem(f)).ToList<ILibraryItem>();
UiThread.RunOnIdle(this.OnReloaded);
});
}
}
}

View file

@ -46,28 +46,20 @@ namespace MatterHackers.MatterControl.Library
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>();
this.Name = "Print Queue".Localize();
Task.Run(() =>
{
this.ReloadContainer();
});
}
private void ReloadContainer()
public override void Load()
{
this.Items = QueueData.Instance.PrintItems.Select(p => new FileSystemFileItem(p.FileLocation)
{
Name = p.Name
}).ToList<ILibraryItem>();
UiThread.RunOnIdle(this.OnReloaded);
}
public override async void Add(IEnumerable<ILibraryItem> items)
{
await AddAllItems(items);
this.ReloadContainer();
this.OnContentChanged();
}
public static async Task AddAllItems(IEnumerable<ILibraryItem> items)
@ -131,7 +123,7 @@ namespace MatterHackers.MatterControl.Library
}
}
this.ReloadContainer();
this.OnContentChanged();
}
public override bool AllowAction(ContainerActions containerActions)

View file

@ -37,14 +37,10 @@ using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.PolygonMesh;
using MatterHackers.PolygonMesh.Processors;
namespace MatterHackers.MatterControl.Library
{
public class SqliteFileItem : FileSystemFileItem
@ -63,17 +59,24 @@ namespace MatterHackers.MatterControl.Library
{
protected List<PrintItemCollection> childCollections = new List<PrintItemCollection>();
public SqliteLibraryContainer()
{
var rootCollection = Datastore.Instance.dbSQLite.Table<PrintItemCollection>().Where(v => v.Name == "_library").Take(1).FirstOrDefault();
this.Initialize(rootCollection?.Id ?? 0);
}
public SqliteLibraryContainer(int collectionID)
{
this.Initialize(collectionID);
}
private void Initialize(int collectionID)
{
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>();
this.Name = "Local Library".Localize();
this.CollectionID = collectionID;
//PrintHistoryData.Instance.ItemAdded.RegisterEvent((sender, e) => OnDataReloaded(null), ref unregisterEvent);
// ItemAdded.RegisterEvent(DatabaseFileChange, ref unregisterEvents);
this.ReloadContainer();
}
public int CollectionID { get; private set; }
@ -89,44 +92,38 @@ namespace MatterHackers.MatterControl.Library
if (base.KeywordFilter != value)
{
base.KeywordFilter = value;
this.ReloadContainer();
this.OnContentChanged();
}
}
}
private void ReloadContainer()
public override void Load()
{
Task.Run(() =>
childCollections = GetChildCollections();
this.ChildContainers = childCollections.Select(c => new SqliteLibraryContainerLink()
{
childCollections = GetChildCollections();
ContainerID = c.Id, Name = c.Name }).ToList<ILibraryContainerLink>(); //
this.ChildContainers = childCollections.Select(c => new SqliteLibraryContainerLink()
// PrintItems projected onto FileSystemFileItem
Items = GetLibraryItems(KeywordFilter).Select<PrintItem, ILibraryItem>(printItem =>
{
if (File.Exists(printItem.FileLocation))
{
ContainerID = c.Id, Name = c.Name }).ToList<ILibraryContainerLink>(); //
// PrintItems projected onto FileSystemFileItem
Items = GetLibraryItems(KeywordFilter).Select<PrintItem, ILibraryItem>(printItem =>
return new SqliteFileItem(printItem);
}
else
{
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();
UiThread.RunOnIdle(this.OnReloaded);
});
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 () =>
{
foreach (var item in items)
{
switch (item)
@ -203,8 +200,7 @@ namespace MatterHackers.MatterControl.Library
}
}
this.ReloadContainer();
this.OnReloaded();
this.OnContentChanged();
});
}
@ -237,7 +233,7 @@ namespace MatterHackers.MatterControl.Library
this.Items.Remove(item);
}
this.OnReloaded();
this.OnContentChanged();
}
public override void Rename(ILibraryItem selectedItem, string revisedName)
@ -259,7 +255,7 @@ namespace MatterHackers.MatterControl.Library
}
}
this.ReloadContainer();
this.OnContentChanged();
}
/// <summary>
@ -354,7 +350,7 @@ namespace MatterHackers.MatterControl.Library
public bool IsProtected { get; set; } = false;
public bool IsReadOnly { get; set; } = false;
public bool IsVisible { get; set; } = true;
public Task<ILibraryContainer> GetContainer(Action<double, string> reportProgress)

View file

@ -29,16 +29,14 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.Library
{
public partial class RootLibraryContainer : ILibraryContainer
public class RootLibraryContainer : ILibraryContainer
{
public event EventHandler Reloaded;
public event EventHandler ContentChanged;
public RootLibraryContainer(List<ILibraryContainerLink> items)
{
@ -69,6 +67,8 @@ namespace MatterHackers.MatterControl.Library
return Task.FromResult<ImageBuffer>(null);
}
public void Load() { }
public void Dispose()
{
}

View file

@ -29,9 +29,11 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
namespace MatterHackers.MatterControl.Library
@ -42,26 +44,33 @@ namespace MatterHackers.MatterControl.Library
private EventHandler unregisterEvents;
private PrinterConfig printer;
private AutoResetEvent autoResetEvent;
public SDCardContainer()
{
this.ChildContainers = new List<ILibraryContainerLink>();
this.Items = new List<ILibraryItem>();
this.Name = "SD Card".Localize();
LoadFilesFromSD();
printer = ApplicationController.Instance.ActivePrinter;
}
public void LoadFilesFromSD()
public override void Load()
{
var printer = ApplicationController.Instance.ActivePrinter;
if (printer.Connection.PrinterIsConnected
&& !(printer.Connection.PrinterIsPrinting || printer.Connection.PrinterIsPaused))
{
autoResetEvent = new AutoResetEvent(false);
printer.Connection.ReadLine.RegisterEvent(Printer_LineRead, ref unregisterEvents);
gotBeginFileList = false;
printer.Connection.SendLineToPrinterNow("M21\r\nM20");
// Ask for files and wait for response
autoResetEvent.WaitOne();
}
}
@ -76,8 +85,7 @@ namespace MatterHackers.MatterControl.Library
private void Printer_LineRead(object sender, EventArgs e)
{
var currentEvent = e as StringEventArgs;
if (currentEvent != null)
if (e is StringEventArgs currentEvent)
{
if (!currentEvent.Data.StartsWith("echo:"))
{
@ -88,6 +96,13 @@ namespace MatterHackers.MatterControl.Library
this.Items.Clear();
break;
case "End file list":
printer.Connection.ReadLine.UnregisterEvent(Printer_LineRead, ref unregisterEvents);
// Release the Load WaitOne
autoResetEvent.Set();
break;
default:
if (gotBeginFileList)
{
@ -103,11 +118,6 @@ namespace MatterHackers.MatterControl.Library
}
}
break;
case "End file list":
ApplicationController.Instance.ActivePrinter.Connection.ReadLine.UnregisterEvent(Printer_LineRead, ref unregisterEvents);
this.OnReloaded();
break;
}
}
}
@ -116,7 +126,10 @@ namespace MatterHackers.MatterControl.Library
public override void Dispose()
{
// In case "End file list" is never received
ApplicationController.Instance.ActivePrinter.Connection.ReadLine.UnregisterEvent(Printer_LineRead, ref unregisterEvents);
printer.Connection.ReadLine.UnregisterEvent(Printer_LineRead, ref unregisterEvents);
// Release the Load WaitOne
autoResetEvent?.Set();
}
}
}

View file

@ -66,10 +66,15 @@ namespace MatterHackers.MatterControl.Library
this.Name = currentDirectory.Split('/').Last();
}
}
public Task<ILibraryContainer> GetContainer(Action<double, string> reportProgress)
{
return Task.FromResult<ILibraryContainer>(new ZipMemoryContainer(this.currentDirectory, this.Path));
return Task.FromResult<ILibraryContainer>(
new ZipMemoryContainer()
{
RelativeDirectory = this.currentDirectory,
Path = this.Path
});
}
}
}

View file

@ -32,25 +32,35 @@ 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
{
public class ZipMemoryContainer : LibraryContainer
{
public ZipMemoryContainer(string relativeDirectory, string path)
public ZipMemoryContainer()
{
}
public string RelativeDirectory { get; set; }
public string Path { get; set; }
public override void Load()
{
//string hashCode = this.Url.GetHashCode().ToString();
var items = new Dictionary<string, long>();
var directories = new HashSet<string>();
using (var file = File.OpenRead(path))
using (var file = File.OpenRead(this.Path))
using (var zip = new ZipArchive(file, ZipArchiveMode.Read))
{
foreach (var entry in zip.Entries)
{
if (entry.FullName.StartsWith(relativeDirectory))
if (entry.FullName.StartsWith(RelativeDirectory))
{
string remainingPath = entry.FullName.Substring(relativeDirectory.Length)?.Trim().TrimStart('/');
string remainingPath = entry.FullName.Substring(RelativeDirectory.Length)?.Trim().TrimStart('/');
var segments = remainingPath.Split('/');
var firstDirectory = segments.First();
@ -68,15 +78,15 @@ namespace MatterHackers.MatterControl.Library
}
}
this.Name = System.IO.Path.GetFileNameWithoutExtension(path);
this.Name = System.IO.Path.GetFileNameWithoutExtension(this.Path);
this.ChildContainers = directories.Where(d => !string.IsNullOrEmpty(d)).Select(d =>
new LocalZipContainerLink(path)
this.ChildContainers = directories.Where(d => !string.IsNullOrEmpty(d)).Select(d =>
new LocalZipContainerLink(this.Path)
{
CurrentDirectory = relativeDirectory.Length == 0 ? d : $"{relativeDirectory}/{d}"
CurrentDirectory = RelativeDirectory.Length == 0 ? d : $"{RelativeDirectory}/{d}"
}).ToList<ILibraryContainerLink>();
this.Items = items.Select(kvp => new ZipMemoryItem(path, relativeDirectory.Length == 0 ? kvp.Key : $"{relativeDirectory}/{kvp.Key}", kvp.Value)).ToList<ILibraryItem>();
this.Items = items.Select(kvp => new ZipMemoryItem(this.Path, RelativeDirectory.Length == 0 ? kvp.Key : $"{RelativeDirectory}/{kvp.Key}", kvp.Value)).ToList<ILibraryItem>();
}
public override void Dispose()

View file

@ -50,7 +50,7 @@ namespace MatterHackers.MatterControl.Library
public string RelativePath { get; set; }
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);

View file

@ -150,6 +150,8 @@ namespace MatterHackers.MatterControl.CustomWidgets
cellIndex = 0;
rowButtonContainer = null;
allIconViews.Clear();
this.CloseAllChildren();
}
}

View file

@ -32,6 +32,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Platform;
@ -46,10 +47,13 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
private EventHandler unregisterEvents;
internal GuiWidget contentView;
private ILibraryContext LibraryContext;
/// <summary>
/// The original content view before it was replaced by a container default view
/// </summary>
private GuiWidget stashedContentView = new IconListView();
// Default constructor uses IconListView
public ListView(ILibraryContext context)
: this(context, new IconListView())
@ -69,7 +73,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
this.ListContentView = libraryView;
context.ContainerChanged += ActiveContainer_Changed;
context.ContainerReloaded += ActiveContainer_Reloaded;
context.ContentChanged += ActiveContainer_ContentChanged;
}
public bool ShowItems { get; set; } = true;
@ -83,43 +87,46 @@ namespace MatterHackers.MatterControl.CustomWidgets
public RGBA_Bytes ThumbnailBackground { get; } = ActiveTheme.Instance.TertiaryBackgroundColor.AdjustLightness(1.05).GetAsRGBA_Bytes();
public RGBA_Bytes ThumbnailForeground { get; set; } = ActiveTheme.Instance.PrimaryAccentColor;
private GuiWidget stashedView = null;
private void ActiveContainer_Changed(object sender, ContainerChangedEventArgs e)
private async void ActiveContainer_Changed(object sender, ContainerChangedEventArgs e)
{
var activeContainer = e.ActiveContainer;
// Anytime the container changes,
Type targetType = activeContainer?.DefaultView;
if (targetType != null
if (targetType != null
&& targetType != this.ListContentView.GetType())
{
stashedView = this.contentView;
// If no original view is stored in stashedContentView then store a reference before the switch
if (stashedContentView == null)
{
stashedContentView = this.ListContentView;
}
// If the current view doesn't match the view requested by the container, construct and switch to the requested view
var targetView = Activator.CreateInstance(targetType) as GuiWidget;
if (targetView != null)
{
this.SetContentView(targetView);
this.ListContentView = targetView;
}
}
else if (stashedView != null)
else if (stashedContentView != null)
{
// Switch back to the original view
this.SetContentView(stashedView);
stashedView = null;
this.ListContentView = stashedContentView;
stashedContentView = null;
}
DisplayContainerContent(activeContainer);
await DisplayContainerContent(activeContainer);
}
public void Reload()
public async Task Reload()
{
DisplayContainerContent(ActiveContainer);
await DisplayContainerContent(ActiveContainer);
}
private void ActiveContainer_Reloaded(object sender, EventArgs e)
private async void ActiveContainer_ContentChanged(object sender, EventArgs e)
{
DisplayContainerContent(ActiveContainer);
await DisplayContainerContent(ActiveContainer);
}
private List<ListViewItem> items = new List<ListViewItem>();
@ -130,14 +137,13 @@ namespace MatterHackers.MatterControl.CustomWidgets
/// Empties the list children and repopulates the list with the source container content
/// </summary>
/// <param name="sourceContainer">The container to load</param>
private void DisplayContainerContent(ILibraryContainer sourceContainer)
private async Task DisplayContainerContent(ILibraryContainer sourceContainer)
{
if (this.ActiveContainer is ILibraryWritableContainer activeWritable)
{
activeWritable.ItemContentChanged -= WritableContainer_ItemContentChanged;
}
UiThread.RunOnIdle(() =>
{
if (sourceContainer == null)
{
@ -154,6 +160,12 @@ namespace MatterHackers.MatterControl.CustomWidgets
var itemsContentView = contentView as IListContentView;
itemsContentView.ClearItems();
// Wait for the container to load
await Task.Run(() =>
{
sourceContainer.Load();
});
int width = itemsContentView.ThumbWidth;
int height = itemsContentView.ThumbHeight;
@ -197,7 +209,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
}
this.Invalidate();
});
}
}
private void WritableContainer_ItemContentChanged(object sender, ItemChangedEventArgs e)
@ -216,16 +228,12 @@ namespace MatterHackers.MatterControl.CustomWidgets
List
}
private void SetContentView(GuiWidget contentView)
{
this.ScrollArea.CloseAllChildren();
this.contentView = contentView;
this.contentView.HAnchor = HAnchor.Stretch;
this.contentView.Name = "Library ListView";
this.AddChild(this.contentView);
}
// Default to IconListView
private GuiWidget contentView = new IconListView();
/// <summary>
/// The GuiWidget responsible for rendering ListViewItems
/// </summary>
public GuiWidget ListContentView
{
get { return contentView; }
@ -233,13 +241,15 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
if (value is IListContentView)
{
SetContentView(value);
// Allow some time for layout to occur and contentView to become sized before loading content
UiThread.RunOnIdle(() =>
if (contentView != null)
{
DisplayContainerContent(ActiveContainer);
});
this.ScrollArea.CloseAllChildren();
this.contentView = value;
this.contentView.HAnchor = HAnchor.Stretch;
this.contentView.Name = "Library ListView";
this.AddChild(this.contentView);
}
}
else
{
@ -364,12 +374,22 @@ namespace MatterHackers.MatterControl.CustomWidgets
public ListViewItem DragSourceRowItem { get; set; }
public override void OnLoad(EventArgs args)
{
if (this.ListContentView.Children.Count <= 0)
{
this.Reload();
}
base.OnLoad(args);
}
public override void OnClosed(ClosedEventArgs e)
{
if (this.LibraryContext != null)
{
this.LibraryContext.ContainerChanged -= this.ActiveContainer_Changed;
this.LibraryContext.ContainerReloaded -= this.ActiveContainer_Reloaded;
this.LibraryContext.ContentChanged -= this.ActiveContainer_ContentChanged;
}
unregisterEvents?.Invoke(this, null);
@ -377,4 +397,3 @@ namespace MatterHackers.MatterControl.CustomWidgets
}
}
}

View file

@ -100,7 +100,7 @@ namespace MatterHackers.MatterControl.PrintLibrary
Name = "Show Folders Toggle",
Checked = UserSettings.Instance.get("ShowContainers") == "1"
};
showFolders.CheckedStateChanged += (s, e) =>
showFolders.CheckedStateChanged += async (s, e) =>
{
UserSettings.Instance.set("ShowContainers", showFolders.Checked ? "1" : "0");
libraryView.Reload();
@ -236,12 +236,11 @@ namespace MatterHackers.MatterControl.PrintLibrary
// Release
if (e.PreviousContainer != null)
{
e.PreviousContainer.Reloaded -= UpdateStatus;
e.PreviousContainer.ContentChanged -= UpdateStatus;
}
var activeContainer = this.libraryView.ActiveContainer;
var writableContainer = activeContainer as ILibraryWritableContainer;
bool containerSupportsEdits = activeContainer is ILibraryWritableContainer;
@ -252,7 +251,7 @@ namespace MatterHackers.MatterControl.PrintLibrary
searchInput.Text = activeContainer.KeywordFilter;
breadCrumbWidget.SetBreadCrumbs(activeContainer);
activeContainer.Reloaded += UpdateStatus;
activeContainer.ContentChanged += UpdateStatus;
UpdateStatus(null, null);
}
@ -639,7 +638,7 @@ namespace MatterHackers.MatterControl.PrintLibrary
{
if (libraryView?.ActiveContainer != null)
{
libraryView.ActiveContainer.Reloaded -= UpdateStatus;
libraryView.ActiveContainer.ContentChanged -= UpdateStatus;
ApplicationController.Instance.Library.ContainerChanged -= Library_ContainerChanged;
}
@ -745,27 +744,6 @@ namespace MatterHackers.MatterControl.PrintLibrary
WizardWindow.Show(exportPage);
}
/*
public async Task<PrintItemWrapper> GetPrintItemWrapperAsync()
{
return await libraryProvider.GetPrintItemWrapperAsync(this.ItemIndex);
} */
// TODO: We've discussed not doing popup edit in a new window. That's what this did, not worth porting yet...
/*
private void editButton_Click(object sender, EventArgs e)
{
//Open export options
if (libraryDataView.SelectedItems.Count == 1)
{
OpenPartViewWindow(PartPreviewWindow.View3DWidget.OpenMode.Editing);
LibraryRowItem libraryItem = libraryDataView.SelectedItems[0];
libraryItem.Edit();
}
} */
public override void OnMouseEnterBounds(MouseEventArgs mouseEvent)
{
if (mouseEvent.DragFiles?.Count > 0)

View file

@ -150,6 +150,8 @@
<Compile Include="CustomWidgets\DisableablePanel.cs" />
<Compile Include="Library\Interfaces\LibraryExtensionMethods.cs" />
<Compile Include="Library\Providers\CreateFolderItem.cs" />
<Compile Include="Library\Providers\MatterControl\PrintHistoryContainer.cs" />
<Compile Include="Library\Providers\MatterControl\PrintHistoryItem.cs" />
<Compile Include="Library\Providers\WritableContainer.cs" />
<Compile Include="Library\Widgets\InsertionGroup.cs" />
<Compile Include="PartPreviewWindow\PopupButton.cs" />
@ -197,7 +199,6 @@
<Compile Include="Library\Interfaces\IThumbnail.cs" />
<Compile Include="Library\Interfaces\ILibraryItem.cs" />
<Compile Include="Library\Interfaces\KnownLengthStream.cs" />
<Compile Include="Library\Providers\CreatorsContainer.cs" />
<Compile Include="Library\Providers\LibraryConfig.cs" />
<Compile Include="Library\Providers\MatterControl\CalibrationPartsContainer.cs" />
<Compile Include="Library\Widgets\ListView\IconListView.cs" />
@ -206,7 +207,6 @@
<Compile Include="Library\Providers\MessageItem.cs" />
<Compile Include="Library\Providers\GeneratorItem.cs" />
<Compile Include="Library\Widgets\ListView\RowListView.cs" />
<Compile Include="Library\Providers\MatterControl\HistoryContainer.cs" />
<Compile Include="Library\Providers\MatterControl\SqliteLibraryContainer.cs" />
<Compile Include="Library\Providers\MatterControl\PrintQueueContainer.cs" />
<Compile Include="Library\Providers\SDCard\SDCardContainer.cs" />

View file

@ -378,38 +378,6 @@ namespace MatterHackers.MatterControl
return instance;
}
public static void WriteTestGCodeFile()
{
using (StreamWriter file = new StreamWriter("PerformanceTest.gcode"))
{
//int loops = 150000;
int loops = 150;
int steps = 200;
double radius = 50;
Vector2 center = new Vector2(150, 100);
file.WriteLine("G28 ; home all axes");
file.WriteLine("G90 ; use absolute coordinates");
file.WriteLine("G21 ; set units to millimeters");
file.WriteLine("G92 E0");
file.WriteLine("G1 F7800");
file.WriteLine("G1 Z" + (5).ToString());
WriteMove(file, center);
for (int loop = 0; loop < loops; loop++)
{
for (int step = 0; step < steps; step++)
{
Vector2 nextPosition = new Vector2(radius, 0);
nextPosition.Rotate(MathHelper.Tau / steps * step);
WriteMove(file, center + nextPosition);
}
}
file.WriteLine("M84 ; disable motors");
}
}
public void LaunchBrowser(string targetUri)
{
UiThread.RunOnIdle(() =>
@ -465,23 +433,23 @@ namespace MatterHackers.MatterControl
QueueData.Instance.SaveDefaultQueue();
// If we are waiting for a response and get another request, just cancel the close until we get a response.
if(closeMessageBoxIsOpen)
if(exitDialogOpen)
{
cancelClose = true;
}
if (!closeHasBeenConfirmed
&& !closeMessageBoxIsOpen
if (!ApplicationExiting
&& !exitDialogOpen
&& ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting)
{
cancelClose = true;
// Record that we are waiting for a response to the request to close
closeMessageBoxIsOpen = true;
exitDialogOpen = true;
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
{
// Needed as we can't assign to CancelClose inside of the lambda below
StyledMessageBox.ShowMessageBox(ConditionalyCloseNow,
StyledMessageBox.ShowMessageBox(ConditionalExit,
"Are you sure you want to abort the current print and close MatterControl?".Localize(),
"Abort Print".Localize(),
StyledMessageBox.MessageType.YES_NO);
@ -489,7 +457,7 @@ namespace MatterHackers.MatterControl
else
{
StyledMessageBox.ShowMessageBox(
ConditionalyCloseNow,
ConditionalExit,
"Are you sure you want exit while a print is running from SD Card?\n\nNote: If you exit, it is recommended you wait until the print is completed before running MatterControl again.".Localize(),
"Exit while printing".Localize(),
StyledMessageBox.MessageType.YES_NO);
@ -497,7 +465,17 @@ namespace MatterHackers.MatterControl
}
else if (PartsSheet.IsSaving())
{
StyledMessageBox.ShowMessageBox(onConfirmExit, savePartsSheetExitAnywayMessage, confirmExit, StyledMessageBox.MessageType.YES_NO);
StyledMessageBox.ShowMessageBox(
(exitAnyway) =>
{
if (exitAnyway)
{
base.OnClosing(out _);
}
},
savePartsSheetExitAnywayMessage,
confirmExit,
StyledMessageBox.MessageType.YES_NO);
cancelClose = true;
}
else if(!cancelClose) // only check if we have not already canceled
@ -506,26 +484,37 @@ namespace MatterHackers.MatterControl
}
}
bool closeHasBeenConfirmed = false;
bool closeMessageBoxIsOpen = false;
private void ConditionalyCloseNow(bool continueWithShutdown)
public bool ApplicationExiting { get; private set; } = false;
private bool exitDialogOpen = false;
private void ConditionalExit(bool exitConfirmed)
{
// Response received, cecord that we are not waiting anymore.
closeMessageBoxIsOpen = false;
if (continueWithShutdown)
// Record that the exitDialog has closed
exitDialogOpen = false;
// Continue with shutdown if exit confirmed by user
if (exitConfirmed)
{
closeHasBeenConfirmed = true;
bool printingFromSdCard = ApplicationController.Instance.ActivePrinter.Connection.CommunicationState == CommunicationStates.PrintingFromSd
|| (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState == CommunicationStates.Paused
&& ApplicationController.Instance.ActivePrinter.Connection.PrePauseCommunicationState == CommunicationStates.PrintingFromSd);
if (!printingFromSdCard)
this.ApplicationExiting = true;
ApplicationController.Instance.Shutdown();
// Always call PrinterConnection.Disable on exit unless PrintingFromSd
PrinterConnection printerConnection = ApplicationController.Instance.ActivePrinter.Connection;
switch(printerConnection.CommunicationState)
{
ApplicationController.Instance.ActivePrinter.Connection.Disable();
case CommunicationStates.PrintingFromSd:
case CommunicationStates.Paused when printerConnection.PrePauseCommunicationState == CommunicationStates.PrintingFromSd:
break;
default:
printerConnection.Disable();
break;
}
MatterControlApplication app = MatterControlApplication.Instance;
app.RestartOnClose = false;
app.Close();
this.RestartOnClose = false;
this.Close();
}
}
@ -590,44 +579,6 @@ namespace MatterHackers.MatterControl
base.OnLoad(args);
}
private static void HtmlWindowTest()
{
try
{
SystemWindow htmlTestWindow = new SystemWindow(640, 480);
string htmlContent = "";
if (true)
{
string releaseNotesFile = Path.Combine("C:\\Users\\lbrubaker\\Downloads", "test1.html");
htmlContent = File.ReadAllText(releaseNotesFile);
}
else
{
WebClient webClient = new WebClient();
htmlContent = webClient.DownloadString("http://www.matterhackers.com/s/store?q=pla");
}
HtmlWidget content = new HtmlWidget(htmlContent, RGBA_Bytes.Black);
content.AddChild(new GuiWidget()
{
HAnchor = HAnchor.Absolute,
VAnchor = VAnchor.Stretch
});
content.VAnchor |= VAnchor.Top;
content.BackgroundColor = RGBA_Bytes.White;
htmlTestWindow.AddChild(content);
htmlTestWindow.BackgroundColor = RGBA_Bytes.Cyan;
UiThread.RunOnIdle((state) =>
{
htmlTestWindow.ShowAsSystemWindow();
}, 1);
}
catch
{
int stop = 1;
}
}
public override void OnMouseMove(MouseEventArgs mouseEvent)
{
// run this first to make sure a child has the chance to take the drag drop event
@ -683,11 +634,6 @@ namespace MatterHackers.MatterControl
}
}
private static void WriteMove(StreamWriter file, Vector2 center)
{
file.WriteLine("G1 X" + center.x.ToString() + " Y" + center.y.ToString());
}
private void CheckOnPrinter()
{
try
@ -743,15 +689,6 @@ namespace MatterHackers.MatterControl
}
}
private void onConfirmExit(bool messageBoxResponse)
{
bool CancelClose;
if (messageBoxResponse)
{
base.OnClosing(out CancelClose);
}
}
private static void AssertDebugNotDefined()
{
#if DEBUG
@ -780,4 +717,3 @@ namespace MatterHackers.MatterControl
}
}
}

@ -1 +1 @@
Subproject commit 3b447235354fa0fb63daba924b3ec42209d7bd2f
Subproject commit 6372949c59f4b355ac3744f5b0938d42d0451183

View file

@ -0,0 +1,263 @@
/*
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 System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.Library;
using MatterHackers.MatterControl.Tests.Automation;
using NUnit.Framework;
namespace MatterControl.Tests.MatterControl
{
[TestFixture, Category("LibraryContainerTests"), RunInApplicationDomain, Apartment(ApartmentState.STA)]
public class LibraryContainerTests
{
[Test]
public Task TestExistsForEachContainerType()
{
AggContext.StaticData = new FileSystemStaticData(TestContext.CurrentContext.ResolveProjectPath(4, "StaticData"));
MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4));
// Find all test methods on this test class
var thisClassMethods = this.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
// Find and validate all ILibraryContainer types, skipping abstract classes
foreach (var containerType in PluginFinder.FindTypes<ILibraryContainer>().Where(fieldType => !fieldType.IsAbstract))
{
string expectedTestName = $"{containerType.Name}Test";
Assert.AreEqual(
1,
thisClassMethods.Where(m => m.Name == expectedTestName).Count(),
"Test for LibraryContainer missing, not yet created or typo'd - Expected: " + expectedTestName);
}
return Task.CompletedTask;
}
[Test]
public async Task NoContentChangedOnLoad()
{
AggContext.StaticData = new FileSystemStaticData(TestContext.CurrentContext.ResolveProjectPath(4, "StaticData"));
MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4));
bool onIdlePumpActive = true;
var uiPump = Task.Run(() =>
{
while (onIdlePumpActive)
{
UiThread.InvokePendingActions();
Thread.Sleep(10);
};
Console.Write("Exiting");
});
// Find and validate all ILibraryContainer types, skipping abstract classes
foreach (var containerType in PluginFinder.FindTypes<ILibraryContainer>().Where(fieldType => !fieldType.IsAbstract))
{
var args = new List<object>();
if (containerType == typeof(FileSystemContainer))
{
args.Add(TestContext.CurrentContext.ResolveProjectPath(4));
}
else if (containerType == typeof(RootLibraryContainer))
{
// TODO: Not sure how to test RootLibrary given content loads after MatterControl init is finished, skipping for now
continue;
}
if (Activator.CreateInstance(containerType, args.ToArray()) is ILibraryContainer libraryContainer)
{
if (libraryContainer is ZipMemoryContainer zipContainer)
{
zipContainer.Path = TestContext.CurrentContext.ResolveProjectPath(4, "Tests", "TestData", "TestParts", "Batman.zip");
zipContainer.RelativeDirectory = Path.GetDirectoryName(zipContainer.Path);
}
int changedCount = 0;
libraryContainer.ContentChanged += (s, e) =>
{
changedCount++;
};
await Task.Run(() =>
{
libraryContainer.Load();
});
// Allow time for invalid additional reloads
await Task.Delay(300);
// Verify Reload is called;
Assert.AreEqual(0, changedCount, "Expected reload count not hit - container should fire reload event after acquiring content");
}
}
onIdlePumpActive = false;
}
[Test]
public async Task AddFiresContentChangedEvent()
{
AggContext.StaticData = new FileSystemStaticData(TestContext.CurrentContext.ResolveProjectPath(4, "StaticData"));
MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4));
string filePath = TestContext.CurrentContext.ResolveProjectPath(4, "Tests", "TestData", "TestParts", "Batman.stl");
bool onIdlePumpActive = true;
var uiPump = Task.Run(() =>
{
while (onIdlePumpActive)
{
UiThread.InvokePendingActions();
Thread.Sleep(10);
};
Console.Write("Exiting");
});
Type writable = typeof(ILibraryWritableContainer);
// Find and validate all ILibraryContainer types, skipping abstract classes
foreach (var containerType in PluginFinder.FindTypes<ILibraryContainer>().Where(fieldType => !fieldType.IsAbstract))
{
var args = new List<object>();
if (containerType == typeof(FileSystemContainer))
{
Directory.CreateDirectory(ApplicationDataStorage.Instance.ApplicationTempDataPath);
args.Add(ApplicationDataStorage.Instance.ApplicationTempDataPath);
}
else if (containerType == typeof(RootLibraryContainer)
|| !writable.IsAssignableFrom(containerType))
{
// TODO: Not sure how to test RootLibrary given content loads after MatterControl init is finished, skipping for now
continue;
}
if (Activator.CreateInstance(containerType, args.ToArray()) is ILibraryWritableContainer libraryContainer)
{
if (libraryContainer is ZipMemoryContainer zipContainer)
{
zipContainer.Path = TestContext.CurrentContext.ResolveProjectPath(4, "Tests", "TestData", "TestParts", "Batman.zip");
zipContainer.RelativeDirectory = Path.GetDirectoryName(zipContainer.Path);
}
int changedCount = 0;
libraryContainer.ContentChanged += (s, e) =>
{
changedCount++;
};
var waitUntil = DateTime.Now.AddSeconds(15);
var result = Task.Run(() =>
{
libraryContainer.Load();
libraryContainer.Add(new[] { new FileSystemFileItem(filePath) });
});
// Wait for reload
while (DateTime.Now <= waitUntil)
{
if (changedCount > 0)
{
break;
}
await Task.Delay(200);
}
// Allow time for invalid additional reloads
await Task.Delay(300);
Console.WriteLine($"ContentChanged for {containerType.Name}");
// Verify Reload is called;
Assert.AreEqual(1, changedCount, $"Expected reload count for {containerType.Name} not hit - container should fire reload event after acquiring content");
}
}
onIdlePumpActive = false;
}
[Test, Ignore("Not implemented")]
public async Task CalibrationPartsContainerTest()
{
}
[Test, Ignore("Not implemented")]
public async Task PrintHistoryContainerTest()
{
}
[Test, Ignore("Not implemented")]
public async Task SqliteLibraryContainerTest()
{
}
[Test, Ignore("Not implemented")]
public async Task PrintQueueContainerTest()
{
}
[Test, Ignore("Not implemented")]
public async Task SDCardContainerTest()
{
}
[Test, Ignore("Not implemented")]
public async Task FileSystemContainerTest()
{
}
[Test, Ignore("Not implemented")]
public async Task RootLibraryContainerTest()
{
}
[Test, Ignore("Not implemented")]
public async Task ZipMemoryContainerTest()
{
}
}
}

View file

@ -70,6 +70,7 @@
<Compile Include="PrintQueueUncertain.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PrintingTests.cs" />
<Compile Include="LibraryContainerTests.cs" />
<Compile Include="SliceSettingsTests.cs" />
<Compile Include="SqLiteLibraryProvider.cs" />
</ItemGroup>

View file

@ -77,6 +77,7 @@
<Compile Include="MatterControl\TranslationsTests.cs" />
<Compile Include="MatterControl\UIFieldTestWindow.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RemovedFromProduct.cs" />
<Compile Include="SceneTests.cs" />
</ItemGroup>
<ItemGroup>

View file

@ -77,7 +77,6 @@ namespace MatterControl.Tests.MatterControl
// Find and validate all UIField types, skipping abstract classes
foreach (var fieldType in PluginFinder.FindTypes<UIField>().Where(fieldType => !fieldType.IsAbstract))
{
if (fieldType.Name == "UIField")
{
continue;

View file

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl;
using MatterHackers.VectorMath;
namespace MatterControl.Tests
{
class RemovedFromProduct
{
public static void WriteTestGCodeFile()
{
using (StreamWriter file = new StreamWriter("PerformanceTest.gcode"))
{
//int loops = 150000;
int loops = 150;
int steps = 200;
double radius = 50;
Vector2 center = new Vector2(150, 100);
file.WriteLine("G28 ; home all axes");
file.WriteLine("G90 ; use absolute coordinates");
file.WriteLine("G21 ; set units to millimeters");
file.WriteLine("G92 E0");
file.WriteLine("G1 F7800");
file.WriteLine("G1 Z" + (5).ToString());
WriteMove(file, center);
for (int loop = 0; loop < loops; loop++)
{
for (int step = 0; step < steps; step++)
{
Vector2 nextPosition = new Vector2(radius, 0);
nextPosition.Rotate(MathHelper.Tau / steps * step);
WriteMove(file, center + nextPosition);
}
}
file.WriteLine("M84 ; disable motors");
}
}
private static void WriteMove(StreamWriter file, Vector2 center)
{
file.WriteLine("G1 X" + center.x.ToString() + " Y" + center.y.ToString());
}
private static void HtmlWindowTest()
{
try
{
SystemWindow htmlTestWindow = new SystemWindow(640, 480);
string htmlContent = "";
if (true)
{
string releaseNotesFile = Path.Combine("C:\\Users\\lbrubaker\\Downloads", "test1.html");
htmlContent = File.ReadAllText(releaseNotesFile);
}
else
{
WebClient webClient = new WebClient();
htmlContent = webClient.DownloadString("http://www.matterhackers.com/s/store?q=pla");
}
HtmlWidget content = new HtmlWidget(htmlContent, RGBA_Bytes.Black);
content.AddChild(new GuiWidget()
{
HAnchor = HAnchor.Absolute,
VAnchor = VAnchor.Stretch
});
content.VAnchor |= VAnchor.Top;
content.BackgroundColor = RGBA_Bytes.White;
htmlTestWindow.AddChild(content);
htmlTestWindow.BackgroundColor = RGBA_Bytes.Cyan;
UiThread.RunOnIdle((state) =>
{
htmlTestWindow.ShowAsSystemWindow();
}, 1);
}
catch
{
int stop = 1;
}
}
}
}