Add DragDrop support for image content

This commit is contained in:
John Lewin 2017-04-05 19:03:04 -07:00
parent 022c91910c
commit d647cf8a86
3 changed files with 136 additions and 29 deletions

View file

@ -56,11 +56,44 @@ namespace MatterHackers.MatterControl
using Agg.Image;
using System.Net;
using CustomWidgets;
using MatterHackers.DataConverters3D;
public class OemProfileDictionary : Dictionary<string, Dictionary<string, PublicDevice>>
{
}
public class ContentResult
{
public IObject3D Object3D { get; set; }
public Task MeshLoaded { get; set; }
}
public interface IContentProvider
{
ContentResult CreateItem(string filePath);
}
public class SimpleContentProvider : IContentProvider
{
public Func<string, ContentResult> Generator { get; set; }
public ContentResult CreateItem(string filePath)
{
return this.Generator(filePath);
}
}
public static class ExtensionMethods
{
public static void Add(this Dictionary<string, IContentProvider> list, IEnumerable<string> extensions, IContentProvider provider)
{
foreach(var extension in extensions)
{
list.Add(extension, provider);
}
}
}
public class PublicDevice
{
public string DeviceToken { get; set; }
@ -224,6 +257,8 @@ namespace MatterHackers.MatterControl
public SlicePresetsWindow EditQualityPresetsWindow { get; set; }
public Dictionary<string, IContentProvider> SceneContentProviders = new Dictionary<string, IContentProvider>();
public ApplicationView MainView;
public event EventHandler ApplicationClosed;

View file

@ -186,6 +186,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
public partial class View3DWidget : PartPreview3DWidget
{
private bool DoBooleanTest = false;
private bool deferEditorTillMouseUp = false;
public FlowLayoutWidget doEdittingButtonsContainer;
public UndoBuffer UndoBuffer { get; private set; } = new UndoBuffer();
public readonly int EditButtonHeight = 44;
@ -872,22 +874,27 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
{
if (AllowDragDrop())
{
foreach (string file in mouseEvent.DragFiles)
{
string extension = Path.GetExtension(file).ToLower();
if (extension != "" && ApplicationSettings.OpenDesignFileParams.Contains(extension))
{
mouseEvent.AcceptDrop = true;
}
}
mouseEvent.AcceptDrop = mouseEvent.DragFiles.TrueForAll(filePath => AllowFileDrop(filePath));
if (mouseEvent.AcceptDrop)
{
DragDropSource = new Object3D
string filePath = mouseEvent.DragFiles.FirstOrDefault();
string extensionWithoutPeriod = Path.GetExtension(filePath).Trim('.');
IContentProvider contentProvider;
if (!string.IsNullOrEmpty(filePath)
&& ApplicationController.Instance.SceneContentProviders.TryGetValue(extensionWithoutPeriod, out contentProvider))
{
ItemType = Object3DTypes.Model,
Mesh = PlatonicSolids.CreateCube(10, 10, 10)
};
DragDropSource = contentProvider.CreateItem(filePath).Object3D;
}
else
{
DragDropSource = new Object3D
{
ItemType = Object3DTypes.Model,
Mesh = PlatonicSolids.CreateCube(10, 10, 10)
};
}
}
}
}
@ -903,7 +910,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
/// Provides a View3DWidget specific drag implementation
/// </summary>
/// <param name="screenSpaceMousePosition">The screen space mouse position.</param>
/// <returns>A value indicating in the DragDropSource was added to the scene</returns>
/// <returns>A value indicating if a new item was generated for the DragDropSource and added to the scene</returns>
public bool AltDragOver(Vector2 screenSpaceMousePosition)
{
if (this.HasBeenClosed)
@ -942,6 +949,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
CurrentSelectInfo.PlaneDownHitPos = intersectInfo.hitPosition;
CurrentSelectInfo.LastMoveDelta = Vector3.Zero;
this.deferEditorTillMouseUp = true;
// Add item to scene and select it
Scene.ModifyChildren(children =>
{
@ -987,14 +996,19 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
IObject3D loadedItem = await Task.Run(() =>
{
return Object3D.Load(dragSource.MeshPath, progress: new DragDropLoadProgress(this, dragSource).UpdateLoadProgress);
string extensionWithoutPeriod = Path.GetExtension(dragSource.MeshPath).Trim('.');
if (ApplicationController.Instance.SceneContentProviders.ContainsKey(extensionWithoutPeriod))
{
return null;
}
else
{
return Object3D.Load(dragSource.MeshPath, progress: new DragDropLoadProgress(this, dragSource).UpdateLoadProgress);
}
});
if (loadedItem != null)
{
// TODO: Changing an item in the scene has a risk of collection modified during enumeration errors. This approach works as
// a proof of concept but needs to take the more difficult route of managing state and swapping the dragging instance with
// the new loaded item data
Vector3 meshGroupCenter = loadedItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity).Center;
dragSource.Mesh = loadedItem.Mesh;
dragSource.Children.AddRange(loadedItem.Children);
@ -1247,7 +1261,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
// the "loading" mesh with the actual file contents
if (AltDragOver(screenSpaceMousePosition))
{
DragDropSource.MeshPath = mouseEvent.DragFiles.First();
DragDropSource.MeshPath = mouseEvent.DragFiles.FirstOrDefault();
// Run the rest of the OnDragOver pipeline since we're starting a new thread and won't finish for an unknown time
base.OnMouseMove(mouseEvent);
@ -1291,10 +1305,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
else if (AllowDragDrop())
{
// Items need to be added to the scene
var partsToAdd = (from droppedFileName in mouseEvent.DragFiles
let extension = Path.GetExtension(droppedFileName).ToLower()
where !string.IsNullOrEmpty(extension) && ApplicationSettings.OpenDesignFileParams.Contains(extension)
select droppedFileName).ToArray();
var partsToAdd = mouseEvent.DragFiles.Where(filePath => AllowFileDrop(filePath)).ToArray();
if (partsToAdd.Length > 0)
{
@ -1307,6 +1318,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
loadAndAddPartsToPlate(partsToAdd);
}
}
if (deferEditorTillMouseUp)
{
this.deferEditorTillMouseUp = false;
Scene_SelectionChanged(null, null);
}
}
if (meshViewerWidget.TrackballTumbleWidget.TransformState == TrackBallController.MouseDownType.None
@ -1520,6 +1537,17 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
flowToAddTo.AddChild(saveButtons);
}
// Indicates if DragDrop operations should be allowed for the given file type
private bool AllowFileDrop(string filePath)
{
string extension = Path.GetExtension(filePath).ToLower();
string extensionWithoutPeriod = extension.Trim('.');
return !string.IsNullOrEmpty(extension)
&& (ApplicationSettings.OpenDesignFileParams.Contains(extension) || ApplicationController.Instance.SceneContentProviders.Keys.Contains(extensionWithoutPeriod));
}
// Indicates if MatterControl is in a mode that allows DragDrop
private bool AllowDragDrop()
{
if ((!enterEditButtonsContainer.Visible
@ -1753,6 +1781,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
return;
}
if (deferEditorTillMouseUp)
{
return;
}
var selectedItem = Scene.SelectedItem;
HashSet<IObject3DEditor> mappedEditors;
@ -1952,13 +1985,24 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
foreach (string loadedFileName in filesToLoad)
{
IObject3D newItem = Object3D.Load(loadedFileName, itemCache, (double progress0To1, string processingState, out bool continueProcessing) =>
IObject3D newItem;
string extension = Path.GetExtension(loadedFileName).ToLower();
IContentProvider contentProvider;
if (ApplicationController.Instance.SceneContentProviders.TryGetValue(extension.Trim('.'), out contentProvider))
{
continueProcessing = !this.HasBeenClosed;
double ratioAvailable = (ratioPerFile * .5);
double currentRatio = currentRatioDone + progress0To1 * ratioAvailable;
ReportProgressChanged(currentRatio, progressMessage, out continueProcessing);
});
newItem = contentProvider.CreateItem(loadedFileName).Object3D;
}
else
{
newItem = Object3D.Load(loadedFileName, itemCache, (double progress0To1, string processingState, out bool continueProcessing) =>
{
continueProcessing = !this.HasBeenClosed;
double ratioAvailable = (ratioPerFile * .5);
double currentRatio = currentRatioDone + progress0To1 * ratioAvailable;
ReportProgressChanged(currentRatio, progressMessage, out continueProcessing);
});
}
if (HasBeenClosed)
{

View file

@ -50,6 +50,7 @@ using MatterHackers.Agg.VertexSource;
using MatterHackers.DataConverters3D;
using MatterHackers.MatterControl.PartPreviewWindow;
using System.Threading.Tasks;
using MatterHackers.MeshVisualizer;
namespace MatterHackers.MatterControl.PrintQueue
{
@ -426,15 +427,19 @@ namespace MatterHackers.MatterControl.PrintQueue
ActionButtonLabel = "Add to Queue",
Title = "MatterControl: Select A File"
},
(openParams) =>
async (openParams) =>
{
if (openParams.FileNames != null)
{
int preAddCount = QueueData.Instance.ItemCount;
IContentProvider contentProvider;
foreach (string fileNameToLoad in openParams.FileNames)
{
string extension = Path.GetExtension(fileNameToLoad).ToUpper();
string extensionWithoutPeriod = extension.ToLower().Trim('.');
if (extension == ".ZIP")
{
List<PrintItem> partFiles = ProjectFileHandler.ImportFromProjectArchive(fileNameToLoad);
@ -446,6 +451,29 @@ namespace MatterHackers.MatterControl.PrintQueue
}
}
}
else if (extension != "" && ApplicationController.Instance.SceneContentProviders.TryGetValue(extensionWithoutPeriod, out contentProvider))
{
// Generate the object
var result = contentProvider.CreateItem(fileNameToLoad);
await result.MeshLoaded;
// Save to the library
string fileName = Path.ChangeExtension(Path.GetRandomFileName(), ".mcx");
string libraryPath = Path.Combine(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, fileName);
var tempScene = new InteractiveScene();
tempScene.Children.Add(result.Object3D);
tempScene.Save(libraryPath, ApplicationDataStorage.Instance.ApplicationLibraryDataPath);
// Add the generated .mcx file to the queue
QueueData.Instance.AddItem(
new PrintItemWrapper(
new PrintItem(
Path.GetFileNameWithoutExtension(fileNameToLoad),
libraryPath)));
}
else if (extension != "" && ApplicationSettings.OpenDesignFileParams.Contains(extension.ToLower()))
{
// Only add files if they have an extension and if it's in the OpenDesignFileParams list