diff --git a/MatterControl.csproj b/MatterControl.csproj index 35b4c2ac9..4c1db2df7 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -146,6 +146,7 @@ + @@ -249,7 +250,7 @@ - + diff --git a/PrintLibrary/LibraryDataView.cs b/PrintLibrary/LibraryDataView.cs index 16ddd6075..424320d7d 100644 --- a/PrintLibrary/LibraryDataView.cs +++ b/PrintLibrary/LibraryDataView.cs @@ -43,29 +43,7 @@ using MatterHackers.MatterControl.PrintQueue; namespace MatterHackers.MatterControl.PrintLibrary { - public class SelectedPrintItems : List - { - public event EventHandler OnAdd; - public event EventHandler OnRemove; - - new public void Add(T item) - { - base.Add(item); - if (null != OnAdd) - { - OnAdd(this, null); - } - } - - new public void Remove(T item) - { - base.Remove(item); - if (null != OnRemove) - { - OnRemove(this, null); - } - } - } + public class LibraryDataView : ScrollableWidget { @@ -142,7 +120,7 @@ namespace MatterHackers.MatterControl.PrintLibrary RGBA_Bytes selectedColor = new RGBA_Bytes(180, 180, 180, 255); RGBA_Bytes baseColor = new RGBA_Bytes(255, 255, 255); - public SelectedPrintItems SelectedItems = new SelectedPrintItems(); + public SelectedListItems SelectedItems = new SelectedListItems(); int selectedIndex = -1; int hoverIndex = -1; int dragIndex = -1; diff --git a/PrintLibrary/LibraryRowItem.cs b/PrintLibrary/LibraryRowItem.cs index 5573fb817..9b0ae8d91 100644 --- a/PrintLibrary/LibraryRowItem.cs +++ b/PrintLibrary/LibraryRowItem.cs @@ -165,7 +165,6 @@ namespace MatterHackers.MatterControl.PrintLibrary primaryClickContainer.HAnchor = HAnchor.ParentLeftRight; primaryClickContainer.VAnchor = VAnchor.ParentBottomTop; - primaryContainer.AddChild(primaryClickContainer); rightButtonOverlay = getItemActionButtons(); diff --git a/PrintLibrary/PrintLibraryWidget.cs b/PrintLibrary/PrintLibraryWidget.cs index 77259546c..6988672a4 100644 --- a/PrintLibrary/PrintLibraryWidget.cs +++ b/PrintLibrary/PrintLibraryWidget.cs @@ -87,7 +87,7 @@ namespace MatterHackers.MatterControl.PrintLibrary FlowLayoutWidget allControls = new FlowLayoutWidget(FlowDirection.TopToBottom); { - enterEditModeButton = editButtonFactory.Generate("Edit".Localize(), centerText:true); + enterEditModeButton = editButtonFactory.Generate("Edit".Localize(), centerText: true); leaveEditModeButton = editButtonFactory.Generate("Done".Localize(), centerText: true); leaveEditModeButton.Visible = false; diff --git a/PrintLibrary/SelectedListItems.cs b/PrintLibrary/SelectedListItems.cs new file mode 100644 index 000000000..b1c01cc9f --- /dev/null +++ b/PrintLibrary/SelectedListItems.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MatterHackers.MatterControl +{ + public class SelectedListItems : List + { + public event EventHandler OnAdd; + public event EventHandler OnRemove; + + new public void Add(T item) + { + base.Add(item); + if (null != OnAdd) + { + OnAdd(this, null); + } + } + + new public void Remove(T item) + { + base.Remove(item); + if (null != OnRemove) + { + OnRemove(this, null); + } + } + + // Also fire OnRemove on Clear + new public void Clear() + { + base.Clear(); + if(null != OnRemove) + { + OnRemove(this, null); + } + } + } +} diff --git a/PrintQueue/QueueDataView.cs b/PrintQueue/QueueDataView.cs index f0435b886..530002c00 100644 --- a/PrintQueue/QueueDataView.cs +++ b/PrintQueue/QueueDataView.cs @@ -67,13 +67,22 @@ namespace MatterHackers.MatterControl.PrintQueue this.editMode = value; if (this.editMode == false) { - //Clear selected items + this.ClearSelectedItems(); } - } } } + public void ClearSelectedItems() + { + foreach (var item in SelectedItems) + { + item.isSelectedItem = false; + item.selectionCheckBox.Checked = false; + } + this.SelectedItems.Clear(); + } + private void AddWatermark() { string imagePathAndFile = Path.Combine(ApplicationDataStorage.Instance.ApplicationStaticDataPath, "OEMSettings", "watermark.png"); @@ -142,6 +151,9 @@ namespace MatterHackers.MatterControl.PrintQueue } } + public SelectedListItems SelectedItems = new SelectedListItems(); + + public PrintItemWrapper SelectedPrintItem { get @@ -267,12 +279,12 @@ namespace MatterHackers.MatterControl.PrintQueue { hoverIndex = value; OnHoverIndexChanged(); - + for (int index = 0; index < topToBottomItemList.Children.Count; index++) - { + { GuiWidget child = topToBottomItemList.Children[index]; if (index == HoverIndex) - { + { ((QueueRowItem)child.Children[0]).IsHoverItem = true; } else if (((QueueRowItem)child.Children[0]).IsHoverItem == true) @@ -335,35 +347,54 @@ namespace MatterHackers.MatterControl.PrintQueue void SelectedIndexChanged(object sender, EventArgs e) { + // Skip this processing while in EditMode + if (this.editMode) return; + OnSelectedIndexChanged(); for (int index = 0; index < topToBottomItemList.Children.Count; index++) { GuiWidget child = topToBottomItemList.Children[index]; + var queueRowItem = (QueueRowItem) child.Children[0]; + if (index == SelectedIndex) { - ((QueueRowItem)child.Children[0]).isSelectedItem = true; + // When not in editmode, keep updating the SelectedItems list to contain the current object. This insures + // that when toggle to editmode occurs, the active selection appears checked. + this.SelectedItems.Clear(); + this.SelectedItems.Add(queueRowItem); + + queueRowItem.selectionCheckBox.Checked = true; + queueRowItem.isSelectedItem = true; + + + + if (!PrinterConnectionAndCommunication.Instance.PrinterIsPrinting && !PrinterConnectionAndCommunication.Instance.PrinterIsPaused) { - ((QueueRowItem)child.Children[0]).isActivePrint = true; - PrinterConnectionAndCommunication.Instance.ActivePrintItem = ((QueueRowItem)child.Children[0]).PrintItemWrapper; + queueRowItem.isActivePrint = true; + PrinterConnectionAndCommunication.Instance.ActivePrintItem = queueRowItem.PrintItemWrapper; } - else if (((QueueRowItem)child.Children[0]).PrintItemWrapper == PrinterConnectionAndCommunication.Instance.ActivePrintItem) + else if (queueRowItem.PrintItemWrapper == PrinterConnectionAndCommunication.Instance.ActivePrintItem) { // the selection must be the active print item - ((QueueRowItem)child.Children[0]).isActivePrint = true; + queueRowItem.isActivePrint = true; } } else { - if (((QueueRowItem)child.Children[0]).isSelectedItem) + // Don't test for .Checked as the property already performs validation + queueRowItem.selectionCheckBox.Checked = false; + + if (queueRowItem.isSelectedItem) { - ((QueueRowItem)child.Children[0]).isSelectedItem = false; + queueRowItem.isSelectedItem = false; } + if (!PrinterConnectionAndCommunication.Instance.PrinterIsPrinting && !PrinterConnectionAndCommunication.Instance.PrinterIsPaused) { - if (((QueueRowItem)child.Children[0]).isActivePrint) + if (queueRowItem.isActivePrint) { - ((QueueRowItem)child.Children[0]).isActivePrint = false; + queueRowItem.isActivePrint = false; } } } diff --git a/PrintQueue/QueueBottomToolbar.cs b/PrintQueue/QueueDataWidget.cs similarity index 69% rename from PrintQueue/QueueBottomToolbar.cs rename to PrintQueue/QueueDataWidget.cs index 37304be6e..7257b9237 100644 --- a/PrintQueue/QueueBottomToolbar.cs +++ b/PrintQueue/QueueDataWidget.cs @@ -29,24 +29,30 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Collections.Generic; +using System.Linq; + using System.IO; using MatterHackers.Agg; using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.DataStorage; using MatterHackers.Localizations; using MatterHackers.MatterControl.CreatorPlugins; -using MatterHackers.MatterControl.DataStorage; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.MatterControl.SettingsManagement; +using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.PrintQueue { public class QueueDataWidget : GuiWidget { - TextImageButtonFactory editButtonFactory = new TextImageButtonFactory(); TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory(); + TextImageButtonFactory editButtonFactory = new TextImageButtonFactory(); PluginChooserWindow pluginChooserWindow; QueueDataView queueDataView; + Button exportItemButton; + Button copyItemButton; + Button removeItemButton; Button enterEditModeButton; Button leaveEditModeButton; QueueRowItem queueRowItem; @@ -79,11 +85,10 @@ namespace MatterHackers.MatterControl.PrintQueue FlowLayoutWidget allControls = new FlowLayoutWidget(FlowDirection.TopToBottom); { - enterEditModeButton = editButtonFactory.Generate("Edit".Localize(), centerText: true); leaveEditModeButton = editButtonFactory.Generate("Done".Localize(), centerText: true); leaveEditModeButton.Visible = false; - + FlowLayoutWidget searchPanel = new FlowLayoutWidget(); searchPanel.BackgroundColor = ActiveTheme.Instance.TransparentDarkOverlay; searchPanel.HAnchor = HAnchor.ParentLeftRight; @@ -106,7 +111,7 @@ namespace MatterHackers.MatterControl.PrintQueue FlowLayoutWidget buttonPanel1 = new FlowLayoutWidget(); buttonPanel1.HAnchor = HAnchor.ParentLeftRight; buttonPanel1.Padding = new BorderDouble(0, 3); - + buttonPanel1.MinimumSize = new Vector2(0, 46); { addToQueueButton = textImageButtonFactory.Generate(LocalizedString.Get("Add"), "icon_circle_plus.png"); buttonPanel1.AddChild(addToQueueButton); @@ -124,6 +129,24 @@ namespace MatterHackers.MatterControl.PrintQueue }; } + exportItemButton = textImageButtonFactory.Generate("Export".Localize()); + exportItemButton.Margin = new BorderDouble(3, 0); + exportItemButton.Click += new EventHandler(exportButton_Click); + exportItemButton.Visible = false; + buttonPanel1.AddChild(exportItemButton); + + copyItemButton = textImageButtonFactory.Generate("Copy".Localize()); + copyItemButton.Margin = new BorderDouble(3, 0); + copyItemButton.Click += new EventHandler(copy_Button_Click); + copyItemButton.Visible = false; + buttonPanel1.AddChild(copyItemButton); + + removeItemButton = textImageButtonFactory.Generate("Remove".Localize()); + removeItemButton.Margin = new BorderDouble(3, 0); + removeItemButton.Click += new EventHandler(removeButton_Click); + removeItemButton.Visible = false; + buttonPanel1.AddChild(removeItemButton); + if(OemSettings.Instance.ShowShopButton) { shopButton = textImageButtonFactory.Generate(LocalizedString.Get("Buy Materials"), "icon_shopping_cart_32x32.png"); @@ -188,6 +211,9 @@ namespace MatterHackers.MatterControl.PrintQueue void AddHandlers() { + queueDataView.SelectedItems.OnAdd += onLibraryItemsSelectChanged; + queueDataView.SelectedItems.OnRemove += onLibraryItemsSelectChanged; + enterEditModeButton.Click += enterEditModeButtonClick; leaveEditModeButton.Click += leaveEditModeButtonClick; } @@ -212,13 +238,8 @@ namespace MatterHackers.MatterControl.PrintQueue createButton.Visible = true; queueMenuContainer.Visible = true; SetVisibleButtons(); - } - void SetVisibleButtons() - { - - } private void SetDisplayAttributes() { @@ -227,6 +248,132 @@ namespace MatterHackers.MatterControl.PrintQueue this.AnchorAll(); } + void exportButton_Click(object sender, EventArgs mouseEvent) + { + //Open export options + if (queueDataView.SelectedItems.Count == 1) + { + QueueRowItem libraryItem = queueDataView.SelectedItems[0]; + OpenExportWindow(libraryItem.PrintItemWrapper); + } + } + + void removeButton_Click(object sender, EventArgs mouseEvent) + { + // Sort by index in the QueueData list to prevent positions shifting due to removes + var sortedByIndexPos = this.queueDataView.SelectedItems.OrderByDescending(rowItem => QueueData.Instance.GetIndex(rowItem.PrintItemWrapper)); + + // Once sorted, remove each selected item + foreach (var item in sortedByIndexPos) + { + item.DeletePartFromQueue(null); + } + + this.queueDataView.SelectedItems.Clear(); + } + + void copy_Button_Click(object sender, EventArgs mouseEvent) + { + CreateCopyInQueue(); + } + + public void CreateCopyInQueue() + { + // Guard for single item selection + if (this.queueDataView.SelectedItems.Count != 1) return; + + var queueRowItem = this.queueDataView.SelectedItems[0]; + + var printItem = queueRowItem.PrintItemWrapper; + + int thisIndexInQueue = QueueData.Instance.GetIndex(printItem); + if (thisIndexInQueue != -1 && File.Exists(printItem.FileLocation)) + { + string applicationDataPath = ApplicationDataStorage.Instance.ApplicationUserDataPath; + string stagingFolder = Path.Combine(applicationDataPath, "data", "temp", "stl"); + if (!Directory.Exists(stagingFolder)) + { + Directory.CreateDirectory(stagingFolder); + } + + string newCopyFilename; + int infiniteBlocker = 0; + do + { + newCopyFilename = Path.Combine(stagingFolder, Path.ChangeExtension(Path.GetRandomFileName(), "stl")); + newCopyFilename = Path.GetFullPath(newCopyFilename); + infiniteBlocker++; + } while (File.Exists(newCopyFilename) && infiniteBlocker < 100); + + File.Copy(printItem.FileLocation, newCopyFilename); + + string newName = printItem.Name; + + if (!newName.Contains(" - copy")) + { + newName += " - copy"; + } + else + { + int index = newName.LastIndexOf(" - copy"); + newName = newName.Substring(0, index) + " - copy"; + } + + int copyNumber = 2; + string testName = newName; + string[] itemNames = QueueData.Instance.GetItemNames(); + // figure out if we have a copy already and increment the number if we do + while (true) + { + if (itemNames.Contains(testName)) + { + testName = "{0} {1}".FormatWith(newName, copyNumber); + copyNumber++; + } + else + { + break; + } + } + newName = testName; + + UiThread.RunOnIdle(AddPartCopyToQueue, new PartToAddToQueue() + { + Name = newName, + FileLocation = newCopyFilename, + InsertAfterIndex = thisIndexInQueue + 1 + }); + } + } + + class PartToAddToQueue + { + internal string Name { get; set; } + internal string FileLocation { get; set; } + internal int InsertAfterIndex { get; set; } + } + + ExportPrintItemWindow exportingWindow; + bool exportingWindowIsOpen = false; + private void OpenExportWindow(PrintItemWrapper printItem) + { + if (exportingWindowIsOpen == false) + { + exportingWindow = new ExportPrintItemWindow(printItem); + this.exportingWindowIsOpen = true; + exportingWindow.Closed += (source, e) => this.exportingWindowIsOpen = false; + exportingWindow.ShowAsSystemWindow(); + } + else + { + if (exportingWindow != null) + { + exportingWindow.BringToFront(); + } + } + } + + private void OpenPluginChooserWindow() { if (pluginChooserWindow == null) @@ -265,6 +412,43 @@ namespace MatterHackers.MatterControl.PrintQueue } } + private void onLibraryItemsSelectChanged(object sender, EventArgs e) + { + SetVisibleButtons(); + } + + private void SetVisibleButtons() + { + int selectedCount = queueDataView.SelectedItems.Count; + if (selectedCount > 0 && queueDataView.EditMode) + { + if (selectedCount == 1) + { + exportItemButton.Visible = true; + copyItemButton.Visible = true; + removeItemButton.Visible = true; + } + else + { + exportItemButton.Visible = false; + copyItemButton.Visible = false; + removeItemButton.Visible = true; + } + + //addToQueueButton.Visible = false; + //createButton.Visible = false; + } + else + { + //addToQueueButton.Visible = true; + //createButton.Visible = true; + exportItemButton.Visible = false; + copyItemButton.Visible = false; + removeItemButton.Visible = false; + } + } + + void exportToSDProcess_UpdateRemainingItems(object sender, EventArgs e) { ExportToFolderProcess exportToSDProcess = (ExportToFolderProcess)sender; @@ -363,6 +547,12 @@ namespace MatterHackers.MatterControl.PrintQueue UiThread.RunOnIdle(AddItemsToQueue); } + void AddPartCopyToQueue(object state) + { + var partInfo = state as PartToAddToQueue; + QueueData.Instance.AddItem(new PrintItemWrapper(new PrintItem(partInfo.Name, partInfo.FileLocation)), partInfo.InsertAfterIndex); + } + void AddItemsToQueue(object state) { string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); diff --git a/PrintQueue/QueueRowItem.cs b/PrintQueue/QueueRowItem.cs index 5bfbdf65b..7081cd270 100644 --- a/PrintQueue/QueueRowItem.cs +++ b/PrintQueue/QueueRowItem.cs @@ -52,6 +52,20 @@ namespace MatterHackers.MatterControl.PrintQueue { public class QueueRowItem : GuiWidget { + private class PartToAddToQueue + { + internal string Name; + internal string FileLocation; + internal int insertAfterIndex; + + internal PartToAddToQueue(string name, string fileLocation, int insertAfterIndex) + { + this.Name = name; + this.FileLocation = fileLocation; + this.insertAfterIndex = insertAfterIndex; + } + } + public PrintItemWrapper PrintItemWrapper { get; set; } //public PrintItemWrapper printItemWrapper; public RGBA_Bytes WidgetTextColor; @@ -73,19 +87,6 @@ namespace MatterHackers.MatterControl.PrintQueue GuiWidget selectionCheckBoxContainer; public CheckBox selectionCheckBox; ClickWidget primaryClickContainer; - bool editMode = false; - public bool EditMode - { - get { return editMode; } - set - { - if (this.editMode != value) - { - this.editMode = value; - } - } - } - public bool IsHoverItem { @@ -147,16 +148,11 @@ namespace MatterHackers.MatterControl.PrintQueue selectionCheckBoxContainer.AddChild(selectionCheckBox); PartThumbnailWidget thumbnailWidget = new PartThumbnailWidget(PrintItemWrapper, "part_icon_transparent_40x40.png", "building_thumbnail_40x40.png", PartThumbnailWidget.ImageSizes.Size50x50); - if (this.editMode) - { - leftColumn.AddChild(selectionCheckBoxContainer); - } + leftColumn.AddChild(selectionCheckBoxContainer); leftColumn.AddChild(thumbnailWidget); } - - FlowLayoutWidget middleColumn = new FlowLayoutWidget(FlowDirection.TopToBottom); middleColumn.VAnchor = VAnchor.ParentTop | Agg.UI.VAnchor.FitToChildren; middleColumn.HAnchor = HAnchor.ParentLeftRight;// | Agg.UI.HAnchor.FitToChildren; @@ -177,7 +173,7 @@ namespace MatterHackers.MatterControl.PrintQueue partStatus.AutoExpandBoundsToText = true; partStatus.TextColor = WidgetTextColor; partStatus.MinimumSize = new Vector2(50, 12); - middleColumn.DebugShowBounds = true; + middleColumn.AddChild(partLabel); middleColumn.AddChild(partStatus); } @@ -193,7 +189,8 @@ namespace MatterHackers.MatterControl.PrintQueue primaryClickContainer = new ClickWidget(); primaryClickContainer.HAnchor = HAnchor.ParentLeftRight; - primaryClickContainer.VAnchor = VAnchor.ParentBottomTop; + primaryClickContainer.VAnchor = VAnchor.ParentBottomTop; + primaryClickContainer.Click += onLibraryItemClick; topToBottomLayout.AddChild(topContentsFlowLayout); this.AddChild(topToBottomLayout); @@ -202,6 +199,7 @@ namespace MatterHackers.MatterControl.PrintQueue actionButtonContainer.Visible = false; this.AddChild(actionButtonContainer); + this.AddChild(primaryClickContainer); AddHandlers(); @@ -263,6 +261,7 @@ namespace MatterHackers.MatterControl.PrintQueue }); } + private void OpenExportWindow() @@ -461,19 +460,7 @@ namespace MatterHackers.MatterControl.PrintQueue this.Margin = new BorderDouble(6,0,6,6); } - class PartToAddToQueue - { - internal string Name; - internal string FileLocation; - internal int insertAfterIndex; - - internal PartToAddToQueue(string name, string fileLocation, int insertAfterIndex) - { - this.Name = name; - this.FileLocation = fileLocation; - this.insertAfterIndex = insertAfterIndex; - } - } + void AddPartToQueue(object state) { @@ -483,7 +470,7 @@ namespace MatterHackers.MatterControl.PrintQueue string alsoRemoveFromSdCardMessage = "Would you also like to remove this file from the Printer's SD Card?".Localize(); string alsoRemoveFromSdCardTitle = "Remove From Printer's SD Card?"; - void DeletePartFromQueue(object state) + internal void DeletePartFromQueue(object state) { if (PrintItemWrapper.PrintItem.FileLocation == QueueData.SdCardFileName) { @@ -495,6 +482,25 @@ namespace MatterHackers.MatterControl.PrintQueue } + private void onLibraryItemClick(object sender, EventArgs e) + { + if (queueDataView.EditMode) + { + if (this.isSelectedItem) + { + this.isSelectedItem = false; + this.selectionCheckBox.Checked = false; + queueDataView.SelectedItems.Remove(this); + } + else + { + this.isSelectedItem = true; + this.selectionCheckBox.Checked = true; + queueDataView.SelectedItems.Add(this); + } + } + } + void onDeleteFileConfirm(bool messageBoxResponse) { if (messageBoxResponse) @@ -558,9 +564,19 @@ namespace MatterHackers.MatterControl.PrintQueue public override void OnDraw(Graphics2D graphics2D) { + if (this.queueDataView.EditMode) + { + selectionCheckBoxContainer.Visible = true; + actionButtonContainer.Visible = false; + } + else + { + selectionCheckBoxContainer.Visible = false; + } + base.OnDraw(graphics2D); - if (this.isActivePrint) + if (this.isActivePrint && !this.queueDataView.EditMode) { //RectangleDouble Bounds = LocalBounds; //RoundedRect rectBorder = new RoundedRect(Bounds, 0); @@ -569,24 +585,30 @@ namespace MatterHackers.MatterControl.PrintQueue SetTextColors(RGBA_Bytes.White); //graphics2D.Render(new Stroke(rectBorder, 4), ActiveTheme.Instance.SecondaryAccentColor); - } + } + else if (this.isSelectedItem) + { + this.BackgroundColor = ActiveTheme.Instance.PrimaryAccentColor; + this.partLabel.TextColor = RGBA_Bytes.White; + this.selectionCheckBox.TextColor = RGBA_Bytes.White; + } else if (this.IsHoverItem) { RectangleDouble Bounds = LocalBounds; RoundedRect rectBorder = new RoundedRect(Bounds, 0); this.BackgroundColor = RGBA_Bytes.White; - SetTextColors(RGBA_Bytes.Black); + this.partLabel.TextColor = RGBA_Bytes.Black; + this.selectionCheckBox.TextColor = RGBA_Bytes.Black; graphics2D.Render(new Stroke(rectBorder, 3), ActiveTheme.Instance.SecondaryAccentColor); } else { - this.BackgroundColor = RGBA_Bytes.White; - SetTextColors(RGBA_Bytes.Black); + this.BackgroundColor = new RGBA_Bytes(255, 255, 255, 255); + SetTextColors(RGBA_Bytes.Black); + this.selectionCheckBox.TextColor = RGBA_Bytes.Black; } - } - } }