Improving open library behavior

This commit is contained in:
LarsBrubaker 2021-03-21 19:32:30 -07:00
parent ec145a4d8f
commit 1f1fed2e2e
15 changed files with 295 additions and 202 deletions

View file

@ -53,6 +53,11 @@ namespace MatterHackers.MatterControl.Library
Task<IObject3D> GetObject3D(Action<double, string> reportProgress);
}
public interface IAssetPath
{
string AssetPath { get; }
}
public interface ILibraryAssetStream : ILibraryAsset
{
/// <summary>

View file

@ -254,18 +254,18 @@ namespace MatterHackers.MatterControl.Library
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
if (AggContext.OperatingSystem == OSType.Windows)
{
if (items.Count() == 1
&& items.FirstOrDefault() is FileSystemFileItem fileItem)
foreach (var item in items)
{
Process.Start("explorer.exe", $"/select, \"{fileItem.Path}\"");
}
else
{
Process.Start(this.FullPath);
if (item is FileSystemItem fileItem
&& File.Exists(fileItem.Path))
{
File.Delete(fileItem.Path);
}
}
this.ReloadContent();
}
}
@ -354,7 +354,7 @@ namespace MatterHackers.MatterControl.Library
public class DirectoryContainerLink : FileSystemItem, ILibraryContainerLink
{
public DirectoryContainerLink(string path)
: base(path)
: base(path, null)
{
}

View file

@ -35,8 +35,8 @@ namespace MatterHackers.MatterControl.Library
{
public class FileSystemFileItem : FileSystemItem, ILibraryAssetStream
{
public FileSystemFileItem(string path)
: base(path)
public FileSystemFileItem(string path, Func<FileSystemItem, string> getFirstSaveName = null)
: base(path, getFirstSaveName)
{
var fileInfo = new FileInfo(path);
if (fileInfo.Exists)

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,9 +40,12 @@ namespace MatterHackers.MatterControl.Library
{
private string fileName;
public FileSystemItem(string path)
private Func<FileSystemItem, string> getFirstSaveName;
public FileSystemItem(string path, Func<FileSystemItem, string> getFirstSaveName = null)
{
this.Path = path;
this.getFirstSaveName = getFirstSaveName;
var type = GetType();
@ -102,6 +105,25 @@ namespace MatterHackers.MatterControl.Library
}
}
public string Path { get; set; }
private string _path;
public string Path
{
get
{
if (getFirstSaveName != null)
{
var newPath = getFirstSaveName(this);
if (!string.IsNullOrEmpty(newPath))
{
getFirstSaveName = null;
_path = newPath;
}
}
return _path;
}
set => _path = value;
}
}
}

View file

@ -62,10 +62,6 @@ namespace MatterHackers.MatterControl.Library
};
}
public int PageSize { get; set; } = 25;
public event EventHandler<ItemChangedEventArgs> ItemContentChanged;
public override bool AllowAction(ContainerActions containerActions)
{
switch(containerActions)
@ -82,44 +78,50 @@ namespace MatterHackers.MatterControl.Library
}
}
// PrintItems projected onto FileSystemFileItem
public override void Load()
{
// Select the 25 most recent files and project onto FileSystemItems
if (Directory.Exists(this.FullPath))
{
var recentFiles = new DirectoryInfo(this.FullPath).GetFiles("*.mcx").OrderByDescending(f => f.LastWriteTime);
Items = recentFiles.Where(f => f.Length > 215).Select(f => new FileSystemFileItem(f.FullName)).ToList<ILibraryItem>();
}
}
internal ILibraryItem NewPlatingItem()
internal ILibraryItem NewPlatingItem(InteractiveScene scene)
{
string now = "Workspace " + DateTime.Now.ToString("yyyy-MM-dd HH_mm_ss");
string mcxPath = Path.Combine(this.FullPath, now + ".mcx");
File.WriteAllText(mcxPath, new Object3D().ToJson());
return new FileSystemFileItem(mcxPath);
}
public ILibraryItem GetLastPlateOrNew()
{
// Find the last used bed plate mcx
var directoryInfo = new DirectoryInfo(ApplicationDataStorage.Instance.PlatingDirectory);
var firstFile = directoryInfo.GetFileSystemInfos("*.mcx").OrderByDescending(fl => fl.LastWriteTime).FirstOrDefault();
// Set as the current item - should be restored as the Active scene in the MeshViewer
if (firstFile != null)
return new FileSystemFileItem(mcxPath, (fileItem) =>
{
return new FileSystemFileItem(firstFile.FullName);
}
// Otherwise generate a new plating item
return this.NewPlatingItem();
// Find the names of stuff in the scene
if (scene.Children.Any())
{
// Create a reasonable name
var baseName = scene.Children.First().Name;
var newName = baseName;
// Make sure the name is unique on disk
var count = 1;
while (File.Exists(Path.Combine(this.FullPath, newName + ".mcx")))
{
newName = baseName + $" ({count++})";
}
// return the new name
var filename = Path.Combine(this.FullPath, newName + ".mcx");
if (File.Exists(filename))
{
File.Move(mcxPath, filename);
}
// change the path in the workspaces
// w.SceneContext.EditContext?.SourceFilePath
var workspace = ApplicationController.Instance.Workspaces.Where(w => w.SceneContext.EditContext?.SourceFilePath == mcxPath).FirstOrDefault();
if (workspace != null)
{
workspace.SceneContext.EditContext.SourceFilePath = filename;
}
fileItem.Name = newName;
fileItem.Path = filename;
return filename;
}
return null;
});
}
public void SetThumbnail(ILibraryItem item, int width, int height, ImageBuffer imageBuffer)
public override void SetThumbnail(ILibraryItem item, int width, int height, ImageBuffer imageBuffer)
{
}
}

View file

@ -29,6 +29,7 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
@ -777,27 +778,54 @@ namespace MatterHackers.MatterControl.PrintLibrary
});
}
// Open menu item
menuActions.Add(new MenuSeparator("Open"));
// open menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Open".Localize(),
Icon = StaticData.Instance.LoadIcon("cube.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
if (listView.SelectedItems.All(i => !(i.Model is ILibraryContainerLink)))
{
ApplicationController.Instance.OpenIntoNewTab(selectedLibraryItems);
}
else
{
// open the folder
listView.SelectedItems.First().OnDoubleClick();
}
listView.SelectedItems.FirstOrDefault()?.OnDoubleClick();
},
IsEnabled = (selectedListItems, listView) =>
{
// Singleselect
return listView.SelectedItems.Count == 1;
// Single select
var only1 = listView.SelectedItems.Count == 1;
// mcx only - disallow containers and protected items
var isAsset = selectedListItems.FirstOrDefault()?.Model is ILibraryItem libraryItem
&& !(libraryItem is ILibraryContainer) // containers are also items
&& !libraryItem.IsProtected
// and we can only edit it if it is an mcx (can't edit stls)
&& libraryItem is ILibraryAsset asset && asset.ContentType == "mcx";
// Check if it is writeable
var writableContainer = !libraryContext.ActiveContainer.IsProtected
&& libraryContext.ActiveContainer is ILibraryWritableContainer;
var isFolder = listView.SelectedItems.FirstOrDefault()?.Model is DynamicContainerLink;
return only1 && ((isAsset && writableContainer) || isFolder);
}
});
// Open a copy menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Open a copy".Localize(),
Icon = StaticData.Instance.LoadIcon("cube_add.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
ApplicationController.Instance.OpenIntoNewTab(selectedLibraryItems);
},
IsEnabled = (selectedListItems, listView) =>
{
var isFolder = listView.SelectedItems.FirstOrDefault()?.Model is DynamicContainerLink;
return listView.SelectedItems.Count == 1
&& (listView.SelectedItems.FirstOrDefault().Container is ILibraryContainerLink
|| listView.SelectedItems.FirstOrDefault().Container is ILibraryContainer)
&& !isFolder;
}
});
@ -837,54 +865,59 @@ namespace MatterHackers.MatterControl.PrintLibrary
// Multiselect - disallow containers, require View3DWidget context
return ApplicationController.Instance.DragDropData.View3DWidget != null
&& listView.SelectedItems.Any()
&& listView.SelectedItems.All(i => !(i.Model is ILibraryContainerLink));
&& listView.SelectedItems.All(i => !(i.Model is ILibraryContainerLink))
&& ApplicationController.Instance.ActivePrinters.Any();
}
});
// edit menu item
menuActions.Add(new MenuSeparator("Export"));
// export menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Edit".Localize(),
Action = async (selectedLibraryItems, listView) =>
Title = "Export".Localize(),
Icon = StaticData.Instance.LoadIcon("cube_export.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
if (selectedLibraryItems.FirstOrDefault() is ILibraryItem firstItem
&& libraryContext.ActiveContainer is ILibraryWritableContainer writableContainer)
{
var workspace = new PartWorkspace(new BedConfig(ApplicationController.Instance.Library.PlatingHistory))
{
Name = firstItem.Name,
};
ApplicationController.Instance.Workspaces.Add(workspace);
var tab = mainViewWidget.CreatePartTab(workspace);
mainViewWidget.TabControl.ActiveTab = tab;
// Load content after UI widgets to support progress notification during acquire/load
await workspace.SceneContext.LoadContent(
new EditContext()
{
ContentStore = writableContainer,
SourceItem = firstItem
});
}
ApplicationController.Instance.ExportLibraryItems(libraryView.SelectedItems.Select(item => item.Model));
},
IsEnabled = (selectedListItems, listView) =>
{
// Singleselect, WritableContainer, mcx only - disallow containers and protected items
// Multiselect - disallow containers
return listView.SelectedItems.Any()
&& listView.SelectedItems.All(i => !(i.Model is ILibraryContainerLink));
},
});
// share menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Share".Localize() + "...",
Icon = StaticData.Instance.LoadIcon("share.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
// Previously - shareFromLibraryButton_Click
// TODO: Should be rewritten to Register from cloudlibrary, include logic to add to library as needed
ApplicationController.Instance.ShareLibraryItem(libraryView.SelectedItems.Select(i => i.Model).FirstOrDefault());
},
IsEnabled = (selectedListItems, listView) =>
{
// Singleselect - disallow containers and protected items
return listView.SelectedItems.Count == 1
&& selectedListItems.FirstOrDefault()?.Model is ILibraryItem firstItem
&& listView.ActiveContainer.GetType().Name.IndexOf("Cloud", StringComparison.OrdinalIgnoreCase) >= 0
&& !(firstItem is ILibraryContainer)
&& !firstItem.IsProtected
&& firstItem is ILibraryAsset asset && asset.ContentType == "mcx"
&& libraryContext.ActiveContainer is ILibraryWritableContainer;
&& !firstItem.IsProtected;
}
});
menuActions.Add(new MenuSeparator("Rename"));
// rename menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Rename".Localize(),
Icon = StaticData.Instance.LoadIcon("icon_edit.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
if (libraryView.SelectedItems.Count == 1)
@ -961,10 +994,51 @@ namespace MatterHackers.MatterControl.PrintLibrary
}
});
// show on disk menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Show in Explorer".Localize(),
// Icon = StaticData.Instance.LoadIcon("remove.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
if (AggContext.OperatingSystem == OSType.Windows)
{
if (AggContext.OperatingSystem == OSType.Windows
&& listView.SelectedItems.Count() == 1)
{
if (listView.SelectedItems.FirstOrDefault().Model is FileSystemFileItem fileItem)
{
Process.Start("explorer.exe", $"/select, \"{fileItem.Path}\"");
}
else if (listView.SelectedItems.FirstOrDefault().Model is FileSystemContainer.DirectoryContainerLink container)
{
Process.Start("explorer.exe", $"/select, \"{container.Path}\"");
}
else if (listView.SelectedItems.FirstOrDefault().Model is LocalZipContainerLink zipContainer)
{
Process.Start("explorer.exe", $"/select, \"{zipContainer.Path}\"");
}
}
}
},
IsEnabled = (selectedListItems, listView) =>
{
if (AggContext.OperatingSystem == OSType.Windows
&& listView.SelectedItems.Count() == 1
&& listView.SelectedItems.FirstOrDefault().Model is FileSystemItem)
{
return true;
}
return false;
}
});
// remove menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Remove".Localize(),
Icon = StaticData.Instance.LoadIcon("remove.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
// Previously - deleteFromLibraryButton_Click
@ -975,27 +1049,19 @@ namespace MatterHackers.MatterControl.PrintLibrary
{
if (libraryView.ActiveContainer is ILibraryWritableContainer container)
{
if (container is FileSystemContainer)
{
container.Remove(libraryItems);
libraryView.SelectedItems.Clear();
}
else
{
StyledMessageBox.ShowMessageBox(
(doDelete) =>
StyledMessageBox.ShowMessageBox(
(doDelete) =>
{
if (doDelete)
{
if (doDelete)
{
container.Remove(libraryItems);
libraryView.SelectedItems.Clear();
}
},
"Are you sure you want to remove the currently selected items?".Localize(),
"Remove Items?".Localize(),
StyledMessageBox.MessageType.YES_NO,
"Remove".Localize());
}
container.Remove(libraryItems);
libraryView.SelectedItems.Clear();
}
},
"Are you sure you want to remove the currently selected items?".Localize(),
"Remove Items?".Localize(),
StyledMessageBox.MessageType.YES_NO,
"Remove".Localize());
}
}
},
@ -1008,47 +1074,6 @@ namespace MatterHackers.MatterControl.PrintLibrary
}
});
menuActions.Add(new MenuSeparator("Export"));
// export menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Export".Localize(),
Icon = StaticData.Instance.LoadIcon("cube_export.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
ApplicationController.Instance.ExportLibraryItems(libraryView.SelectedItems.Select(item => item.Model));
},
IsEnabled = (selectedListItems, listView) =>
{
// Multiselect - disallow containers
return listView.SelectedItems.Any()
&& listView.SelectedItems.All(i => !(i.Model is ILibraryContainerLink));
},
});
// share menu item
menuActions.Add(new LibraryAction(ActionScope.ListItem)
{
Title = "Share".Localize() + "...",
Icon = StaticData.Instance.LoadIcon("share.png", 16, 16, theme.InvertIcons),
Action = (selectedLibraryItems, listView) =>
{
// Previously - shareFromLibraryButton_Click
// TODO: Should be rewritten to Register from cloudlibrary, include logic to add to library as needed
ApplicationController.Instance.ShareLibraryItem(libraryView.SelectedItems.Select(i => i.Model).FirstOrDefault());
},
IsEnabled = (selectedListItems, listView) =>
{
// Singleselect - disallow containers and protected items
return listView.SelectedItems.Count == 1
&& selectedListItems.FirstOrDefault()?.Model is ILibraryItem firstItem
&& listView.ActiveContainer.GetType().Name.IndexOf("Cloud", StringComparison.OrdinalIgnoreCase) >= 0
&& !(firstItem is ILibraryContainer)
&& !firstItem.IsProtected;
}
});
// Extension point - RegisteredLibraryActions not defined in this file/assembly can insert here via this named token
menuActions.AddRange(ApplicationController.Instance.RegisteredLibraryActions("StandardLibraryOperations"));

View file

@ -30,6 +30,7 @@ either expressed or implied, of the FreeBSD Project.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using MatterHackers.Agg;
@ -475,7 +476,55 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
if (this.DoubleClickAction == DoubleClickActions.PreviewItem)
{
ApplicationController.Instance.OpenIntoNewTab(new[] { itemModel });
if (itemModel is ILibraryAsset asset && asset.ContentType == "mcx"
&& itemModel is ILibraryItem firstItem
&& this.ActiveContainer is ILibraryWritableContainer writableContainer)
{
var mainViewWidget = ApplicationController.Instance.MainView;
// check if it is already open
foreach (var openWorkspace in ApplicationController.Instance.Workspaces)
{
if (openWorkspace.SceneContext.EditContext.SourceFilePath == asset.AssetPath
|| (openWorkspace.SceneContext.EditContext.SourceItem is IAssetPath cloudItem
&& cloudItem.AssetPath == asset.AssetPath))
{
foreach (var tab in mainViewWidget.TabControl.AllTabs)
{
if (tab.TabContent is PartTabPage tabContent
&& (tabContent.sceneContext.EditContext.SourceFilePath == asset.AssetPath
|| (tabContent.sceneContext.EditContext.SourceItem is IAssetPath cloudItem2
&& cloudItem2.AssetPath == asset.AssetPath)))
{
mainViewWidget.TabControl.ActiveTab = tab;
return;
}
}
}
}
var workspace = new PartWorkspace(new BedConfig(ApplicationController.Instance.Library.PlatingHistory))
{
Name = firstItem.Name,
};
ApplicationController.Instance.Workspaces.Add(workspace);
var partTab = mainViewWidget.CreatePartTab(workspace);
mainViewWidget.TabControl.ActiveTab = partTab;
// Load content after UI widgets to support progress notification during acquire/load
await workspace.SceneContext.LoadContent(
new EditContext()
{
ContentStore = writableContainer,
SourceItem = firstItem
});
}
else
{
ApplicationController.Instance.OpenIntoNewTab(new[] { itemModel });
}
}
else
{