diff --git a/MatterControlLib/ApplicationView/ApplicationController.cs b/MatterControlLib/ApplicationView/ApplicationController.cs index a60b2da6a..045f5a99e 100644 --- a/MatterControlLib/ApplicationView/ApplicationController.cs +++ b/MatterControlLib/ApplicationView/ApplicationController.cs @@ -180,22 +180,9 @@ namespace MatterHackers.MatterControl { DialogWindow.Show( new SaveAsPage( - (newName, destinationContainer) => + (newName, container) => { - // Save to the destination provider - if (destinationContainer is ILibraryWritableContainer writableContainer) - { - // Wrap stream with ReadOnlyStream library item and add to container - writableContainer.Add(new[] - { - new InMemoryLibraryItem(selectedItem) - { - Name = newName - } - }); - - destinationContainer.Dispose(); - } + sceneContext.Rename(newName); })); }), IsEnabled = () => sceneContext.EditableScene @@ -679,22 +666,9 @@ namespace MatterHackers.MatterControl { DialogWindow.Show( new SaveAsPage( - async (newName, destinationContainer) => + async (newName, container) => { - // Save to the destination provider - if (destinationContainer is ILibraryWritableContainer writableContainer) - { - // Wrap stream with ReadOnlyStream library item and add to container - writableContainer.Add(new[] - { - new InMemoryLibraryItem(sceneContext.Scene) - { - Name = newName - } - }); - - destinationContainer.Dispose(); - } + sceneContext.Rename(newName); })); }), IsEnabled = () => sceneContext.EditableScene diff --git a/MatterControlLib/ApplicationView/EditContext.cs b/MatterControlLib/ApplicationView/EditContext.cs index 47f7ec0b4..981330862 100644 --- a/MatterControlLib/ApplicationView/EditContext.cs +++ b/MatterControlLib/ApplicationView/EditContext.cs @@ -38,6 +38,7 @@ using Newtonsoft.Json; using System.Linq; using System.Threading; using System.Threading.Tasks; +using System; namespace MatterHackers.MatterControl { @@ -63,10 +64,25 @@ namespace MatterHackers.MatterControl public bool FreezeGCode { get; set; } + public event EventHandler SourceItemChanged; + + private ILibraryItem _sourceItem; /// /// The library item to load and persist /// - public ILibraryItem SourceItem { get; set; } + public ILibraryItem SourceItem + { + get => _sourceItem; + + set + { + if (value != _sourceItem) + { + _sourceItem = value; + SourceItemChanged?.Invoke(this, EventArgs.Empty); + } + } + } public bool IsGGCodeSource => (this.SourceItem as ILibraryAsset)?.ContentType == "gcode"; diff --git a/MatterControlLib/Library/DynamicContentStore.cs b/MatterControlLib/Library/DynamicContentStore.cs index 7cc4609ef..c8e216e2e 100644 --- a/MatterControlLib/Library/DynamicContentStore.cs +++ b/MatterControlLib/Library/DynamicContentStore.cs @@ -41,7 +41,11 @@ namespace MatterHackers.MatterControl.Library this.saveAction = saveAction; } - public void Save(ILibraryItem item, IObject3D content) + public void Dispose() + { + } + + public void Save(ILibraryItem item, IObject3D content) { saveAction.Invoke(item, content); } diff --git a/MatterControlLib/Library/Interfaces/IContentStore.cs b/MatterControlLib/Library/Interfaces/IContentStore.cs index a1c61b02e..ab484186b 100644 --- a/MatterControlLib/Library/Interfaces/IContentStore.cs +++ b/MatterControlLib/Library/Interfaces/IContentStore.cs @@ -1,5 +1,5 @@ /* -Copyright (c) 2017, John Lewin +Copyright (c) 2022, John Lewin, Lars Brubaker All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,10 +28,11 @@ either expressed or implied, of the FreeBSD Project. */ using MatterHackers.DataConverters3D; +using System; namespace MatterHackers.MatterControl.Library { - public interface IContentStore + public interface IContentStore : IDisposable { void Save(ILibraryItem item, IObject3D content); } diff --git a/MatterControlLib/Library/Interfaces/LibraryExtensionMethods.cs b/MatterControlLib/Library/Interfaces/LibraryExtensionMethods.cs index 95224dbc0..a21ca948c 100644 --- a/MatterControlLib/Library/Interfaces/LibraryExtensionMethods.cs +++ b/MatterControlLib/Library/Interfaces/LibraryExtensionMethods.cs @@ -29,6 +29,7 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Collections.Generic; +using System.IO; using System.Threading.Tasks; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; @@ -77,6 +78,30 @@ namespace MatterHackers.MatterControl.Library } } + public static void Rename(this ISceneContext sceneContext, string newName) + { + var contentStore = sceneContext.EditContext.ContentStore; + // Save to the destination provider + if (contentStore is FileSystemContainer fileSystemContainer) + { + sceneContext.EditContext.SourceItem = new FileSystemFileItem(Path.ChangeExtension(Path.Combine(fileSystemContainer.FullPath, newName), ".mcx")); + fileSystemContainer.Save(sceneContext.EditContext.SourceItem, sceneContext.Scene); + } + else if (contentStore is ILibraryWritableContainer writableContainer) + { + // Wrap stream with ReadOnlyStream library item and add to container + writableContainer.Add(new[] + { + new InMemoryLibraryItem(sceneContext.Scene) + { + Name = newName + } + }); + + contentStore.Dispose(); + } + } + public static IEnumerable AncestorsAndSelf(this ILibraryContainer item) { var container = item; diff --git a/MatterControlLib/Library/Widgets/LibraryWidget.cs b/MatterControlLib/Library/Widgets/LibraryWidget.cs index 57d28511e..9fa8cd234 100644 --- a/MatterControlLib/Library/Widgets/LibraryWidget.cs +++ b/MatterControlLib/Library/Widgets/LibraryWidget.cs @@ -799,7 +799,7 @@ namespace MatterHackers.MatterControl.PrintLibrary } ApplicationController.Instance.BlinkTab( - ApplicationController.Instance.MainView.TabControl.AllTabs.FirstOrDefault(t => t.TabContent is PartTabPage)); + ApplicationController.Instance.MainView.TabControl.AllTabs.FirstOrDefault(t => t.TabContent is DesignTabPage)); }, IsEnabled = (selectedListItems, listView) => { @@ -810,7 +810,7 @@ namespace MatterHackers.MatterControl.PrintLibrary && listView.SelectedItems.Any() && listView.SelectedItems.All(i => !(i.Model is ILibraryContainerLink)) && !isFolder - && ApplicationController.Instance.MainView.TabControl.AllTabs.Any(t => t.TabContent is PartTabPage); + && ApplicationController.Instance.MainView.TabControl.AllTabs.Any(t => t.TabContent is DesignTabPage); } }); diff --git a/MatterControlLib/Library/Widgets/ListView/LibraryListView.cs b/MatterControlLib/Library/Widgets/ListView/LibraryListView.cs index c4a89b673..5c22bb452 100644 --- a/MatterControlLib/Library/Widgets/ListView/LibraryListView.cs +++ b/MatterControlLib/Library/Widgets/ListView/LibraryListView.cs @@ -519,7 +519,7 @@ namespace MatterHackers.MatterControl.CustomWidgets { foreach (var tab in mainViewWidget.TabControl.AllTabs) { - if (tab.TabContent is PartTabPage tabContent + if (tab.TabContent is DesignTabPage tabContent && (tabContent.sceneContext.EditContext.SourceFilePath == asset.AssetPath || (tabContent.sceneContext.EditContext.SourceItem is IAssetPath cloudItem2 && cloudItem2.AssetPath == asset.AssetPath))) @@ -535,7 +535,7 @@ namespace MatterHackers.MatterControl.CustomWidgets ApplicationController.Instance.Workspaces.Add(workspace); - var partTab = mainViewWidget.CreatePartTab(workspace, true); + var partTab = mainViewWidget.CreateDesignTab(workspace, true); mainViewWidget.TabControl.ActiveTab = partTab; // Load content after UI widgets to support progress notification during acquire/load @@ -545,8 +545,6 @@ namespace MatterHackers.MatterControl.CustomWidgets ContentStore = writableContainer, SourceItem = firstItem }); - - mainViewWidget.HookupNameChangeCallback(partTab, workspace); } else { diff --git a/MatterControlLib/PartPreviewWindow/PartTabPage.cs b/MatterControlLib/PartPreviewWindow/DesignTabPage.cs similarity index 98% rename from MatterControlLib/PartPreviewWindow/PartTabPage.cs rename to MatterControlLib/PartPreviewWindow/DesignTabPage.cs index b3b5dad58..a681620b1 100644 --- a/MatterControlLib/PartPreviewWindow/PartTabPage.cs +++ b/MatterControlLib/PartPreviewWindow/DesignTabPage.cs @@ -39,7 +39,7 @@ using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.PartPreviewWindow { - public class PartTabPage : TabPage + public class DesignTabPage : TabPage { // TODO: Don't change casing... almost certainly none of these should be exposed internal View3DWidget view3DWidget; @@ -53,7 +53,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public PrinterConfig Printer => Workspace.Printer; - public PartTabPage(PartWorkspace workspace, ThemeConfig theme, string tabTitle) + public DesignTabPage(PartWorkspace workspace, ThemeConfig theme, string tabTitle) : base(tabTitle) { this.sceneContext = workspace.SceneContext; diff --git a/MatterControlLib/PartPreviewWindow/MainViewWidget.cs b/MatterControlLib/PartPreviewWindow/MainViewWidget.cs index 4ec2e1358..062dd05ce 100644 --- a/MatterControlLib/PartPreviewWindow/MainViewWidget.cs +++ b/MatterControlLib/PartPreviewWindow/MainViewWidget.cs @@ -352,7 +352,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } else { - newTab = this.CreatePartTab(workspace, false); + newTab = this.CreateDesignTab(workspace, false); } if (newTab.Key == ApplicationController.Instance.MainTabKey) @@ -404,6 +404,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow BorderColor = theme.SlightShade, Width = 200 * GuiWidget.DeviceScale }; + statusBar.AddChild(stretchStatusPanel); var panelBackgroundColor = theme.MinimalShade.WithAlpha(10); @@ -454,13 +455,13 @@ namespace MatterHackers.MatterControl.PartPreviewWindow ApplicationController.Instance.Workspaces.Add(workspace); - var newTab = CreatePartTab(workspace, true); + var newTab = CreateDesignTab(workspace, true); tabControl.ActiveTab = newTab; } private void TabControl_ActiveTabChanged(object sender, EventArgs e) { - if (this.tabControl.ActiveTab?.TabContent is PartTabPage tabPage) + if (this.tabControl.ActiveTab?.TabContent is DesignTabPage tabPage) { var dragDropData = ApplicationController.Instance.DragDropData; @@ -553,7 +554,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { // Create printer or part tab bool isPrinter = activePrinter?.Settings.PrinterSelected == true; - ChromeTab newTab = isPrinter ? CreatePrinterTab(workspace, theme) : CreatePartTab(workspace, false); + ChromeTab newTab = isPrinter ? CreatePrinterTab(workspace, theme) : CreateDesignTab(workspace, false); if (e.Operation == WorkspacesChangedEventArgs.OperationType.Add) { @@ -578,26 +579,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } - public void HookupNameChangeCallback(ChromeTab partTab, PartWorkspace workspace) - { - var sourceItem = workspace.SceneContext?.EditContext?.SourceItem; - - if (sourceItem != null) - { - void UpdateTabName(object s, EventArgs e) - { - partTab.Title = sourceItem.Name; - ApplicationController.Instance.PersistOpenTabsLayout(); - } - - sourceItem.NameChanged += UpdateTabName; - - partTab.Closed += (s, e) => sourceItem.NameChanged -= UpdateTabName; - - partTab.Title = sourceItem.Name; - } - } - private GuiWidget CreateNetworkStatusPanel(ThemeConfig theme) { var networkStatus = new GuiWidget() @@ -851,7 +832,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow ApplicationController.Instance.Workspaces.Add(workspace); - var newTab = CreatePartTab(workspace, true); + var newTab = CreateDesignTab(workspace, true); tabControl.ActiveTab = newTab; if (addPhilToBed) @@ -868,13 +849,54 @@ namespace MatterHackers.MatterControl.PartPreviewWindow ApplicationController.Instance.MainTabKey = workspace.Name; } - public ChromeTab CreatePartTab(PartWorkspace workspace, bool saveLayout) + private static void HookupNameChangeCallback(ChromeTab partTab, PartWorkspace workspace) + { + var sourceItem = workspace.SceneContext?.EditContext?.SourceItem; + + if (sourceItem != null) + { + void UpdateTabName(object s, EventArgs e) + { + partTab.Text = sourceItem.Name; + if (workspace.SceneContext.EditContext.SourceItem is FileSystemFileItem fileSystemFileItem) + { + partTab.ToolTipText = fileSystemFileItem.FilePath; + } + + ApplicationController.Instance.PersistOpenTabsLayout(); + } + + var lastSourceItem = sourceItem; + void SourceItemChanged(object s, EventArgs e) + { + lastSourceItem.NameChanged -= UpdateTabName; + lastSourceItem = workspace.SceneContext.EditContext.SourceItem; + lastSourceItem.NameChanged += UpdateTabName; + UpdateTabName(s, e); + } + + workspace.SceneContext.EditContext.SourceItemChanged += SourceItemChanged; + sourceItem.NameChanged += UpdateTabName; + workspace.SceneContext.SceneLoaded += UpdateTabName; + + partTab.Closed += (s, e) => + { + workspace.SceneContext.EditContext.SourceItemChanged -= SourceItemChanged; + sourceItem.NameChanged -= UpdateTabName; + workspace.SceneContext.SceneLoaded -= UpdateTabName; + }; + + UpdateTabName(null, null); + } + } + + public ChromeTab CreateDesignTab(PartWorkspace workspace, bool saveLayout) { var partTab = new ChromeTab( workspace.Name, workspace.Name, tabControl, - new PartTabPage(workspace, theme, ""), + new DesignTabPage(workspace, theme, ""), theme, StaticData.Instance.LoadIcon("cube.png", 16, 16).SetToColor(theme.TextColor)) { @@ -951,19 +973,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow partTab.MaximumSize = new Vector2(width, partTab.MaximumSize.Y); partTab.Width -= 1; - - // wait for this size change to take effect and update the tool tip - partTab.BoundsChanged += (s, e) => - { - if (partTab.Width < partTab.MaximumSize.X) - { - partTab.ToolTipText = textWidget.Text; - } - else - { - partTab.ToolTipText = ""; - } - }; } partTab.HAnchor = HAnchor.Stretch; @@ -1003,8 +1012,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var printerTab = tabControl.AllTabs.FirstOrDefault(t => t.TabContent is PrinterTabPage printerPage && printerPage.Printer.Settings.ID == printerSettings.ID) as ChromeTab; if (printerTab != null) { - printerTab.Title = printerSettings.GetValue(SettingsKey.printer_name); - printerTab.ToolTipText = printerTab.Title; + printerTab.Text = printerSettings.GetValue(SettingsKey.printer_name); + // printerTab.ToolTipText = printerTab.Text; } } } diff --git a/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs b/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs index abd76d521..024af4f9f 100644 --- a/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs +++ b/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs @@ -44,7 +44,7 @@ using static MatterHackers.MatterControl.StyledMessageBox; namespace MatterHackers.MatterControl.PartPreviewWindow { - public class PrinterTabPage : PartTabPage + public class PrinterTabPage : DesignTabPage { private GCode2DWidget gcode2DWidget; diff --git a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs index 6759857f4..96b06f077 100644 --- a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs +++ b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs @@ -483,5 +483,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow primaryActionsPanel.RemoveChildren(); } } - } + + public void Dispose() + { + } + } } \ No newline at end of file diff --git a/MatterControlLib/PartPreviewWindow/Tabs.cs b/MatterControlLib/PartPreviewWindow/Tabs.cs index 4c1af2a1c..36f53da37 100644 --- a/MatterControlLib/PartPreviewWindow/Tabs.cs +++ b/MatterControlLib/PartPreviewWindow/Tabs.cs @@ -462,7 +462,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow "Cancel Print".Localize(), "Continue Printing".Localize()); } - else if (this.TabContent is PartTabPage partTab + else if (this.TabContent is DesignTabPage partTab && partTab?.Workspace?.SceneContext?.Scene is InteractiveScene sceneContext && sceneContext.HasUnsavedChanges) { @@ -744,7 +744,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow base.OnClosed(e); } - public string Title + public override string Text { get => tabPill?.Text; set @@ -756,6 +756,18 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } + public override string ToolTipText + { + get => tabPill?.ToolTipText; + set + { + if (tabPill != null) + { + tabPill.ToolTipText = value; + } + } + } + public static void DrawTabLowerRight(Graphics2D graphics2D, RectangleDouble rect, Color color) { // Tab - right nub diff --git a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs index 03168d8f4..e3abbf204 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs @@ -98,7 +98,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow private RadioIconButton zoomButton; private RadioIconButton partSelectButton; - public View3DWidget(PrinterConfig printer, ISceneContext sceneContext, ViewToolBarControls viewControls3D, ThemeConfig theme, PartTabPage printerTabBase, Object3DControlsLayer.EditorType editorType = Object3DControlsLayer.EditorType.Part) + public View3DWidget(PrinterConfig printer, ISceneContext sceneContext, ViewToolBarControls viewControls3D, ThemeConfig theme, DesignTabPage printerTabBase, Object3DControlsLayer.EditorType editorType = Object3DControlsLayer.EditorType.Part) { this.sceneContext = sceneContext; this.printerTabPage = printerTabBase as PrinterTabPage; diff --git a/MatterControlLib/PartPreviewWindow/ViewToolBarControls.cs b/MatterControlLib/PartPreviewWindow/ViewToolBarControls.cs index e5380d6a3..82fd6a079 100644 --- a/MatterControlLib/PartPreviewWindow/ViewToolBarControls.cs +++ b/MatterControlLib/PartPreviewWindow/ViewToolBarControls.cs @@ -1,5 +1,5 @@ /* -Copyright (c) 2018, Lars Brubaker, John Lewin +Copyright (c) 2022, Lars Brubaker, John Lewin All rights reserved. Redistribution and use in source and binary forms, with or without @@ -276,7 +276,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow button.Click += (s, e) => UiThread.RunOnIdle(() => { namedAction.Action.Invoke(sceneContext); - var partTab = button.Parents().FirstOrDefault(); + var partTab = button.Parents().FirstOrDefault(); var view3D = partTab.Descendants().FirstOrDefault(); view3D.Object3DControlLayer.Focus(); }); @@ -868,27 +868,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { DialogWindow.Show( new SaveAsPage( - (newName, destinationContainer) => + (newName, container) => { - // Save to the destination provider - if (destinationContainer is FileSystemContainer fileSystemContainer) - { - sceneContext.EditContext.SourceItem = new FileSystemFileItem(Path.ChangeExtension(Path.Combine(fileSystemContainer.FullPath, newName), ".mcx")); - fileSystemContainer.Save(sceneContext.EditContext.SourceItem, sceneContext.Scene); - } - else if (destinationContainer is ILibraryWritableContainer writableContainer) - { - // Wrap stream with ReadOnlyStream library item and add to container - writableContainer.Add(new[] - { - new InMemoryLibraryItem(sceneContext.Scene) - { - Name = newName - } - }); - - destinationContainer.Dispose(); - } + sceneContext.Rename(newName); })); }); var export = popupMenu.CreateMenuItem("Export".Localize(), StaticData.Instance.LoadIcon("cube_export.png", 16, 16).SetToColor(theme.TextColor)); diff --git a/Tests/MatterControl.AutomationTests/PrinterDropDownTests.cs b/Tests/MatterControl.AutomationTests/PrinterDropDownTests.cs index d478bdff2..04a25ac94 100644 --- a/Tests/MatterControl.AutomationTests/PrinterDropDownTests.cs +++ b/Tests/MatterControl.AutomationTests/PrinterDropDownTests.cs @@ -36,16 +36,16 @@ namespace MatterHackers.MatterControl.Tests.Automation .SwitchToPrinterSettings() .InlineTitleEdit("Printer Name", newName0); - Assert.AreEqual(newName0, printerTab0.Title); - Assert.AreEqual("BCN3D Sigma", printerTab1.Title); + Assert.AreEqual(newName0, printerTab0.Text); + Assert.AreEqual("BCN3D Sigma", printerTab1.Text); // switch back to BCN tab testRunner.ClickByName("3D View Tab 1") .SwitchToPrinterSettings() .InlineTitleEdit("Printer Name", newName1); - Assert.AreEqual(newName1, printerTab1.Title); - Assert.AreEqual(newName0, printerTab0.Title, "Name did not change"); + Assert.AreEqual(newName1, printerTab1.Text); + Assert.AreEqual(newName0, printerTab0.Text, "Name did not change"); return Task.CompletedTask; }, maxTimeToRun: 120); @@ -84,7 +84,7 @@ namespace MatterHackers.MatterControl.Tests.Automation // Validate that the tab reflects the new name var printerTab = testRunner.GetWidgetByName("3D View Tab 0", out _) as ChromeTab; - Assert.AreEqual(newName, printerTab.Title); + Assert.AreEqual(newName, printerTab.Text); // Validate that the settings layer reflects the new name Assert.AreEqual(newName, printer.PrinterName);