diff --git a/MatterControl.csproj b/MatterControl.csproj index 1025104c0..933784358 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -208,6 +208,7 @@ + diff --git a/PartPreviewWindow/GCodeDetails.cs b/PartPreviewWindow/GCodeDetails.cs index b29493fe6..e03630877 100644 --- a/PartPreviewWindow/GCodeDetails.cs +++ b/PartPreviewWindow/GCodeDetails.cs @@ -27,7 +27,6 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ -using MatterHackers.Agg.UI; using MatterHackers.GCodeVisualizer; using MatterHackers.MatterControl.SlicerConfiguration; diff --git a/PartPreviewWindow/GCodeDetailsView.cs b/PartPreviewWindow/GCodeDetailsView.cs new file mode 100644 index 000000000..dd33b30dc --- /dev/null +++ b/PartPreviewWindow/GCodeDetailsView.cs @@ -0,0 +1,119 @@ +/* +Copyright (c) 2017, 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 MatterHackers.Agg; +using MatterHackers.Agg.UI; +using MatterHackers.Localizations; +using MatterHackers.MatterControl.SlicerConfiguration; + +namespace MatterHackers.MatterControl.PartPreviewWindow +{ + public class GCodeDetailsView : FlowLayoutWidget + { + private TextWidget massTextWidget; + private TextWidget costTextWidget; + + // Cost info is only displayed when available - conditionalCostPanel is invisible when cost <= 0 + private GuiWidget conditionalCostPanel; + + private EventHandler unregisterEvents; + + public GCodeDetailsView(GCodeDetails gcodeDetails) + : base(FlowDirection.TopToBottom) + { + // put in the print time + this.AddChild(new TextWidget("Print Time".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); + this.AddChild(new TextWidget(gcodeDetails.EstimatedPrintTime, textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 14) + { + Margin = new BorderDouble(0, 9, 0, 3) + }); + + // show the filament used + this.AddChild(new TextWidget("Filament Length".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); + this.AddChild(new TextWidget(gcodeDetails.FilamentUsed, pointSize: 14, textColor: ActiveTheme.Instance.PrimaryTextColor) + { + Margin = new BorderDouble(0, 9, 0, 3) + }); + + this.AddChild(new TextWidget("Filament Volume".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); + this.AddChild(new TextWidget(gcodeDetails.FilamentVolume, pointSize: 14, textColor: ActiveTheme.Instance.PrimaryTextColor) + { + Margin = new BorderDouble(0, 9, 0, 3) + }); + + this.AddChild(new TextWidget("Estimated Mass".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); + + this.AddChild(massTextWidget = new TextWidget(gcodeDetails.EstimatedMass, pointSize: 14, textColor: ActiveTheme.Instance.PrimaryTextColor) + { + Margin = new BorderDouble(0, 9, 0, 3) + }); + + conditionalCostPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) + { + HAnchor = HAnchor.ParentLeftRight, + VAnchor = VAnchor.FitToChildren, + Visible = gcodeDetails.TotalCost > 0 + }; + + conditionalCostPanel.AddChild(new TextWidget("Estimated Cost".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); + conditionalCostPanel.AddChild(costTextWidget = new TextWidget(gcodeDetails.EstimatedCost, pointSize: 14, textColor: ActiveTheme.Instance.PrimaryTextColor) + { + Margin = new BorderDouble(top: 3) + }); + + this.AddChild(conditionalCostPanel); + + ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) => + { + if (e is StringEventArgs stringEvent) + { + if (stringEvent.Data == SettingsKey.filament_cost + || stringEvent.Data == SettingsKey.filament_diameter + || stringEvent.Data == SettingsKey.filament_density) + { + massTextWidget.Text = gcodeDetails.EstimatedMass; + conditionalCostPanel.Visible = gcodeDetails.TotalCost > 0; + + if (gcodeDetails.TotalCost > 0) + { + costTextWidget.Text = gcodeDetails.EstimatedCost; + } + } + } + }, ref unregisterEvents); + } + + public override void OnClosed(ClosedEventArgs e) + { + unregisterEvents?.Invoke(this, null); + base.OnClosed(e); + } + } +} diff --git a/PartPreviewWindow/ViewGcodeBasic.cs b/PartPreviewWindow/ViewGcodeBasic.cs index 79218475c..9c7b783ea 100644 --- a/PartPreviewWindow/ViewGcodeBasic.cs +++ b/PartPreviewWindow/ViewGcodeBasic.cs @@ -117,7 +117,16 @@ namespace MatterHackers.MatterControl.PartPreviewWindow CreateAndAddChildren(); - ActiveSliceSettings.SettingChanged.RegisterEvent(CheckSettingChanged, ref unregisterEvents); + ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) => + { + if (e is StringEventArgs stringEvent) + { + if (stringEvent.Data == "extruder_offset") + { + printer.BedPlate.GCodeRenderer.Clear3DGCode(); + } + } + }, ref unregisterEvents); // TODO: Why do we clear GCode on AdvancedControlsPanelReloading - assume some slice settings should invalidate. If so, code should be more specific and bound to slice settings changed ApplicationController.Instance.AdvancedControlsPanelReloading.RegisterEvent((s, e) => printer.BedPlate.GCodeRenderer?.Clear3DGCode(), ref unregisterEvents); @@ -125,33 +134,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow private GCodeFile loadedGCode => printer.BedPlate.LoadedGCode; - private void CheckSettingChanged(object sender, EventArgs e) - { - if (e is StringEventArgs stringEvent) - { - if (loadedGCode != null - && ( - stringEvent.Data == SettingsKey.filament_cost - || stringEvent.Data == SettingsKey.filament_diameter - || stringEvent.Data == SettingsKey.filament_density) - ) - { - massTextWidget.Text = gcodeDetails.EstimatedMass; - conditionalCostPanel.Visible = gcodeDetails.TotalCost > 0; - - if (gcodeDetails.TotalCost > 0) - { - costTextWidget.Text = gcodeDetails.EstimatedCost; - } - } - - if (stringEvent.Data == "extruder_offset") - { - printer.BedPlate.GCodeRenderer.Clear3DGCode(); - } - } - } - private void CreateAndAddChildren() { CloseAllChildren(); @@ -400,73 +382,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } } - TextWidget massTextWidget; - TextWidget costTextWidget; - - // Cost info is only displayed when available - conditionalCostPanel is invisible when cost <= 0 - GuiWidget conditionalCostPanel; - - GCodeDetails gcodeDetails; - - private FlowLayoutWidget CreateModelInfo(GCodeDetails gcodeDetails) - { - var modelInfoContainer = new FlowLayoutWidget(FlowDirection.TopToBottom) - { - Padding = new BorderDouble(5), - Margin = new BorderDouble(0, 0, 35, 5), - BackgroundColor = new RGBA_Bytes(0, 0, 0, ViewControlsBase.overlayAlpha), - HAnchor = HAnchor.ParentRight | HAnchor.AbsolutePosition, - VAnchor = VAnchor.ParentTop | VAnchor.FitToChildren, - Width = 150 - }; - - // put in the print time - modelInfoContainer.AddChild(new TextWidget("Print Time".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); - modelInfoContainer.AddChild(new TextWidget(gcodeDetails.EstimatedPrintTime, textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 14) - { - Margin = new BorderDouble(0, 9, 0, 3) - }); - - // show the filament used - modelInfoContainer.AddChild(new TextWidget("Filament Length".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); - modelInfoContainer.AddChild(new TextWidget(gcodeDetails.FilamentUsed, pointSize: 14, textColor: ActiveTheme.Instance.PrimaryTextColor) - { - Margin = new BorderDouble(0, 9, 0, 3) - }); - - modelInfoContainer.AddChild(new TextWidget("Filament Volume".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); - modelInfoContainer.AddChild(new TextWidget(gcodeDetails.FilamentVolume, pointSize: 14, textColor: ActiveTheme.Instance.PrimaryTextColor) - { - Margin = new BorderDouble(0, 9, 0, 3) - }); - - modelInfoContainer.AddChild(new TextWidget("Estimated Mass".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); - - modelInfoContainer.AddChild(massTextWidget = new TextWidget(gcodeDetails.EstimatedMass, pointSize: 14, textColor: ActiveTheme.Instance.PrimaryTextColor) - { - Margin = new BorderDouble(0, 9, 0, 3) - }); - - conditionalCostPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) - { - HAnchor = HAnchor.ParentLeftRight, - VAnchor = VAnchor.FitToChildren, - Visible = gcodeDetails.TotalCost > 0 - }; - - conditionalCostPanel.AddChild(new TextWidget("Estimated Cost".Localize() + ":", textColor: ActiveTheme.Instance.PrimaryTextColor, pointSize: 9)); - conditionalCostPanel.AddChild(costTextWidget = new TextWidget(gcodeDetails.EstimatedCost, pointSize: 14, textColor: ActiveTheme.Instance.PrimaryTextColor) - { - Margin = new BorderDouble(0, 9, 0, 3) - }); - - modelInfoContainer.AddChild(conditionalCostPanel); - - // TODO: Every time you click Generate we wire up a listener - only when we close do they get released. This is a terrible pattern that has a good chance of creating a high leak scenario. Since RootedEventHandlers are normally only cleared when a widget is closed, we should **only** register them in widget constructors - PrinterConnection.Instance.CommunicationStateChanged.RegisterEvent(HookUpGCodeMessagesWhenDonePrinting, ref unregisterEvents); - - return modelInfoContainer; - } + private GCodeDetails gcodeDetails; internal GuiWidget ShowOverflowMenu() { @@ -579,11 +495,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow printItem.SlicingDone -= sliceItem_Done; generateGCodeButton.Visible = false; - - // TODO: Bad pattern - figure out how to revise - // However if the print finished or is canceled we are going to want to get updates again. So, hook the status event - PrinterConnection.Instance.CommunicationStateChanged.RegisterEvent(HookUpGCodeMessagesWhenDonePrinting, ref unregisterEvents); - UiThread.RunOnIdle(SetSyncToPrintVisibility); } } @@ -771,7 +682,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow setLayerWidget.VAnchor = Agg.UI.VAnchor.ParentTop; layerSelectionButtonsPanel.AddChild(setLayerWidget); - + navigationWidget?.Close(); navigationWidget = new LayerNavigationWidget(gcode2DWidget, ApplicationController.Instance.Theme.GCodeLayerButtons); navigationWidget.Margin = new BorderDouble(0, 0, 20, 0); @@ -800,7 +711,21 @@ namespace MatterHackers.MatterControl.PartPreviewWindow BoundsChanged += new EventHandler(PartPreviewGCode_BoundsChanged); this.gcodeDetails = new GCodeDetails(this.loadedGCode); - this.AddChild(CreateModelInfo(gcodeDetails)); + + this.AddChild(new GCodeDetailsView(gcodeDetails) + { + Margin = new BorderDouble(0, 0, 35, 5), + Padding = new BorderDouble(10), + BackgroundColor = new RGBA_Bytes(0, 0, 0, ViewControlsBase.overlayAlpha), + HAnchor = HAnchor.ParentRight | HAnchor.AbsolutePosition, + VAnchor = VAnchor.ParentTop | VAnchor.FitToChildren, + Width = 150 + }); + + // TODO: Bad pattern - figure out how to revise + // However if the print finished or is canceled we are going to want to get updates again. So, hook the status event + PrinterConnection.Instance.CommunicationStateChanged.RegisterEvent(HookUpGCodeMessagesWhenDonePrinting, ref unregisterEvents); + UiThread.RunOnIdle(SetSyncToPrintVisibility); // Switch to the most recent view mode, defaulting to Layers3D SwitchViewModes();