Revise tab ordering and persistence logic

- Issue MatterHackers/MCCentral#4555
This commit is contained in:
John Lewin 2018-12-07 18:41:32 -08:00
parent 980b9e6236
commit aae2ffdf76
11 changed files with 347 additions and 99 deletions

View file

@ -29,9 +29,11 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
@ -40,10 +42,7 @@ using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.MatterControl.DesignTools.Operations;
using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("MatterControl.Tests")]
[assembly: InternalsVisibleTo("MatterControl.AutomationTests")]
@ -73,17 +72,13 @@ namespace MatterHackers.MatterControl
using MatterHackers.MatterControl.Library;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.MatterControl.PartPreviewWindow.View3D;
using MatterHackers.MatterControl.PluginSystem;
using MatterHackers.MatterControl.PrinterControls.PrinterConnections;
using MatterHackers.MatterControl.SetupWizard;
using MatterHackers.PolygonMesh;
using MatterHackers.PolygonMesh.Processors;
using MatterHackers.RenderOpenGl;
using MatterHackers.SerialPortCommunication;
using MatterHackers.VectorMath;
using MatterHackers.VectorMath.TrackBall;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
using SettingsManagement;
[JsonConverter(typeof(StringEnumConverter))]
@ -109,16 +104,16 @@ namespace MatterHackers.MatterControl
Titillium,
};
public class OpenPrintersChangedEventArgs : EventArgs
public class WorkspacesChangedEventArgs : EventArgs
{
public OpenPrintersChangedEventArgs(PrinterConfig printer, OperationType operation)
public WorkspacesChangedEventArgs(PartWorkspace workspace, OperationType operation)
{
this.Printer = printer;
this.Operation = operation;
this.Workspace = workspace;
}
public PrinterConfig Printer { get; }
public OperationType Operation { get; }
public PartWorkspace Workspace { get; }
public enum OperationType { Add, Remove }
}
@ -269,10 +264,10 @@ namespace MatterHackers.MatterControl
public RunningTasksConfig Tasks { get; set; } = new RunningTasksConfig();
public IReadOnlyList<PrinterConfig> ActivePrinters => _activePrinters;
public IEnumerable<PrinterConfig> ActivePrinters => this.Workspaces.Where(w => w.Printer != null).Select(w => w.Printer);
// A list of printers which are open (i.e. displaying a tab) on this instance of MatterControl
private List<PrinterConfig> _activePrinters = new List<PrinterConfig>();
//// A list of printers which are open (i.e. displaying a tab) on this instance of MatterControl
//private List<PrinterConfig> _activePrinters = new List<PrinterConfig>();
private Dictionary<Type, HashSet<IObject3DEditor>> objectEditorsByType;
@ -395,7 +390,7 @@ namespace MatterHackers.MatterControl
public RootedObjectEventHandler DoneReloadingAll = new RootedObjectEventHandler();
public RootedObjectEventHandler ActiveProfileModified = new RootedObjectEventHandler();
public event EventHandler<OpenPrintersChangedEventArgs> OpenPrintersChanged;
public event EventHandler<WorkspacesChangedEventArgs> WorkspacesChanged;
public static Action WebRequestFailed;
public static Action WebRequestSucceeded;
@ -412,9 +407,9 @@ namespace MatterHackers.MatterControl
public static Func<string, Task<Dictionary<string, string>>> GetProfileHistory;
public void OnOpenPrintersChanged(OpenPrintersChangedEventArgs e)
public void OnWorkspacesChanged(WorkspacesChangedEventArgs e)
{
this.OpenPrintersChanged?.Invoke(this, e);
this.WorkspacesChanged?.Invoke(this, e);
}
public string GetFavIconUrl(string oemName)
@ -428,11 +423,15 @@ namespace MatterHackers.MatterControl
// Actually clear printer
ProfileManager.Instance.ClosePrinter(printer.Settings.ID);
_activePrinters.Remove(printer);
if (allowChangedEvent)
{
this.OnOpenPrintersChanged(new OpenPrintersChangedEventArgs(printer, OpenPrintersChangedEventArgs.OperationType.Remove));
if (ApplicationController.Instance.Workspaces.FirstOrDefault(w => w.Printer.Settings.ID == printer.Settings.ID) is PartWorkspace workspace)
{
this.OnWorkspacesChanged(
new WorkspacesChangedEventArgs(
workspace,
WorkspacesChangedEventArgs.OperationType.Remove));
}
}
printer.Dispose();
@ -935,7 +934,7 @@ namespace MatterHackers.MatterControl
{
UiThread.RunOnIdle(() =>
{
if (printer != null || this.ActivePrinters.Count == 1)
if (printer != null || this.ActivePrinters.Count() == 1)
{
// If unspecified but count is one, select the one active printer
if (printer == null)
@ -1032,7 +1031,7 @@ namespace MatterHackers.MatterControl
ProfileManager.UserChanged += (s, e) =>
{
_activePrinters = new List<PrinterConfig>();
//_activePrinters = new List<PrinterConfig>();
};
this.RebuildSceneOperations(this.Theme);
@ -1811,39 +1810,48 @@ namespace MatterHackers.MatterControl
public async Task<PrinterConfig> OpenPrinter(string printerID, bool loadPlateFromHistory = true)
{
if (!_activePrinters.Any(p => p.Settings.ID == printerID))
var printer = this.ActivePrinters.FirstOrDefault(p => p.Settings.ID == printerID);
if (printer == null)
{
ProfileManager.Instance.OpenPrinter(printerID);
var printer = new PrinterConfig(await ProfileManager.LoadSettingsAsync(printerID));
_activePrinters.Add(printer);
if (!string.IsNullOrEmpty(printerID)
&& ProfileManager.Instance[printerID] != null)
{
printer = new PrinterConfig(await ProfileManager.LoadSettingsAsync(printerID));
}
if (loadPlateFromHistory)
{
await printer.Bed.LoadPlateFromHistory();
}
this.OnOpenPrintersChanged(new OpenPrintersChangedEventArgs(printer, OpenPrintersChangedEventArgs.OperationType.Add));
if (printer.Settings.PrinterSelected
&& printer.Settings.GetValue<bool>(SettingsKey.auto_connect))
{
printer.Connection.Connect();
}
return printer;
}
return PrinterConfig.EmptyPrinter;
if (printer != null
&& printer.Settings.PrinterSelected
&& printer.Settings.GetValue<bool>(SettingsKey.auto_connect))
{
printer.Connection.Connect();
}
return printer;
}
public void OpenWorkspace(PartWorkspace workspace)
{
this.OnWorkspacesChanged(
new WorkspacesChangedEventArgs(
workspace,
WorkspacesChangedEventArgs.OperationType.Add));
ApplicationController.Instance.Workspaces.Add(workspace);
}
public async Task OpenAllPrinters()
{
foreach (var printerID in ProfileManager.Instance.OpenPrinterIDs)
{
await this.OpenPrinter(printerID);
}
//foreach (var printerID in ProfileManager.Instance.OpenPrinterIDs)
//{
// await this.OpenPrinter(printerID);
//}
}
/// <summary>
@ -3206,6 +3214,99 @@ If you experience adhesion problems, please re-run leveling."
return Task.CompletedTask;
});
// Instead of opening printers, we should load open tabs........................
// Persist part workspaces
var history = applicationController.Library.PlatingHistory;
if (File.Exists(ProfileManager.Instance.OpenTabsPath))
{
try
{
string openTabsText = File.ReadAllText(ProfileManager.Instance.OpenTabsPath);
var persistedWorkspaces = JsonConvert.DeserializeObject<List<PartWorkspace>>(
openTabsText,
new ContentStoreConverter(),
new LibraryItemConverter());
foreach (var persistedWorkspace in persistedWorkspaces)
{
// Load the actual workspace if content file exists
if (File.Exists(persistedWorkspace.ContentPath))
{
// Spin up the printer if specified
// Push item to loaded workspaces
string printerID = persistedWorkspace.PrinterID;
PartWorkspace workspace = null;
if (!string.IsNullOrEmpty(printerID)
&& ProfileManager.Instance[printerID] != null)
{
//var workspace = this.OpenWorkspace(printerID, ));
var itemPrinter = await applicationController.OpenPrinter(persistedWorkspace.PrinterID, false);
// Add workspace for printer plate
workspace = new PartWorkspace(itemPrinter);
}
else
{
workspace = new PartWorkspace(new BedConfig(history));
}
// Load it up
await workspace.SceneContext.LoadContent(new EditContext() {
ContentStore = history,
SourceItem = new FileSystemFileItem(persistedWorkspace.ContentPath)
});
if (workspace.Printer != null)
{
workspace.Name = workspace.Printer.Settings.GetValue(SettingsKey.printer_name);
}
else
{
workspace.Name = workspace?.SceneContext.EditContext?.SourceItem?.Name ?? "Unknown";
}
applicationController.OpenWorkspace(workspace);
}
}
}
catch
{
// Create new part tab on failure?
}
}
else
{
// Create new part tab if no existing?
}
if (applicationController.Workspaces.Count == 0)
{
var workspace = new PartWorkspace(new BedConfig(history))
{
Name = "New Design".Localize()
};
// Load it up
workspace.SceneContext.LoadEmptyContent(
new EditContext()
{
ContentStore = history,
SourceItem = history.NewPlatingItem()
});
applicationController.OpenWorkspace(workspace);
}
await applicationController.Tasks.Execute(
"Restoring Printers".Localize(),
null,
@ -3257,4 +3358,20 @@ If you experience adhesion problems, please re-run leveling."
});
}
}
public class ContentStoreConverter : JsonConverter<IContentStore>
{
public override bool CanWrite => false;
public override IContentStore ReadJson(JsonReader reader, Type objectType, IContentStore existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
return null;
}
public override void WriteJson(JsonWriter writer, IContentStore value, JsonSerializer serializer)
{
}
}
}

View file

@ -60,10 +60,12 @@ namespace MatterHackers.MatterControl
public View3DConfig RendererOptions { get; } = new View3DConfig();
[JsonIgnore]
public PrinterConfig Printer { get; set; }
public EditContext EditContext { get; private set; }
public EditContext EditContext { get; set; }
[JsonIgnore]
public Mesh PrinterShape { get; private set; }
public SceneContextViewState ViewState { get; }
@ -346,11 +348,14 @@ namespace MatterHackers.MatterControl
}
}
[JsonIgnore]
public InteractiveScene Scene { get; } = new InteractiveScene();
public GCodeRenderInfo RenderInfo { get; set; }
private Mesh _bedMesh;
[JsonIgnore]
public Mesh Mesh
{
get
@ -414,6 +419,7 @@ namespace MatterHackers.MatterControl
private Mesh _buildVolumeMesh;
[JsonIgnore]
public Mesh BuildVolumeMesh => _buildVolumeMesh;
public bool EditableScene => this.EditContext?.FreezeGCode != true;

View file

@ -0,0 +1,77 @@
/*
Copyright (c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using Newtonsoft.Json;
namespace MatterHackers.MatterControl
{
using MatterHackers.MatterControl.Library;
using Newtonsoft.Json.Linq;
public class LibraryItemConverter : JsonConverter<ILibraryItem>
{
public override bool CanWrite => false;
public override ILibraryItem ReadJson(JsonReader reader, Type objectType, ILibraryItem existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jsonObject = JObject.Load(reader);
var item = new DummyItem();
serializer.Populate(jsonObject.CreateReader(), item);
return item;
}
public override void WriteJson(JsonWriter writer, ILibraryItem value, JsonSerializer serializer)
{
}
}
public class DummyItem : ILibraryItem
{
public string ID { get; set; }
public string Name { get; set; }
public bool IsProtected { get; set; }
public bool IsVisible { get; set; }
public DateTime DateModified { get; set; }
public DateTime DateCreated { get; set; }
public string Path { get; set; }
public string AssetPath { get; set; }
}
}

View file

@ -27,11 +27,43 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using Newtonsoft.Json;
namespace MatterHackers.MatterControl
{
public class PartWorkspace
{
private BedConfig _sceneContext { get; }
public PartWorkspace()
{
}
public PartWorkspace(PrinterConfig printer)
: this (printer.Bed)
{
this.Printer = printer;
this.PrinterID = printer.Settings.ID;
}
public PartWorkspace(BedConfig bedConfig)
{
_sceneContext = bedConfig;
Name = _sceneContext.EditContext?.SourceItem?.Name ?? "Unknown";
}
public string Name { get; set; }
public BedConfig SceneContext { get; set; }
[JsonIgnore]
public BedConfig SceneContext => _sceneContext;
public EditContext EditContext { get; set; }
public string PrinterID { get; set; }
[JsonIgnore]
public PrinterConfig Printer { get; }
public string ContentPath { get; set; }
}
}

View file

@ -34,16 +34,13 @@ using MatterHackers.MatterControl.SlicerConfiguration;
namespace MatterHackers.MatterControl
{
using System.IO;
using System.Threading;
using MatterHackers.Agg;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.SlicerConfiguration.MappingClasses;
using MatterHackers.MeshVisualizer;
using MatterHackers.VectorMath;
using Newtonsoft.Json;
public class PrinterConfig : IDisposable
{
@ -55,6 +52,7 @@ namespace MatterHackers.MatterControl
public static PrinterConfig EmptyPrinter { get; } = new PrinterConfig();
[JsonIgnore]
public EngineMappingsMatterSlice EngineMappingsMatterSlice { get; }
// heating status
@ -173,6 +171,7 @@ namespace MatterHackers.MatterControl
}
}
[JsonIgnore]
public PrinterConnection Connection { get; }
public string PrinterConnectionStatus