mattercontrol/ActionBar/PrintStatusRow.cs

537 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Diagnostics;
using System.Threading;
using System.IO;
using MatterHackers.Agg.Image;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.VectorMath;
using MatterHackers.Agg.VertexSource;
using MatterHackers.MatterControl;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.PolygonMesh;
using MatterHackers.Localizations;
namespace MatterHackers.MatterControl.ActionBar
{
class PrintStatusRow : ActionRowBase
{
Stopwatch timeSinceLastDrawTime = new Stopwatch();
event EventHandler unregisterEvents;
TextWidget activePrintName;
TextWidget activePrintLabel;
TextWidget activePrintInfo;
TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
TextWidget activePrintStatus;
string ActivePrintStatusText
{
set
{
if (activePrintStatus.Text != value)
{
activePrintStatus.Text = value;
}
}
}
protected override void Initialize()
{
UiThread.RunOnIdle(OnIdle);
this.Margin = new BorderDouble(6, 3, 6, 6);
}
PartThumbnailWidget activePrintPreviewImage;
void onActivePrintItemChanged(object sender, EventArgs e)
{
// first we have to remove any link to an old part (the part currently in the view)
if (activePrintPreviewImage.PrintItem != null)
{
activePrintPreviewImage.PrintItem.SlicingOutputMessage -= PrintItem_SlicingOutputMessage;
}
activePrintPreviewImage.PrintItem = PrinterCommunication.Instance.ActivePrintItem;
// then hook up our new part
if (activePrintPreviewImage.PrintItem != null)
{
activePrintPreviewImage.PrintItem.SlicingOutputMessage += PrintItem_SlicingOutputMessage;
}
activePrintPreviewImage.Invalidate();
}
void PrintItem_SlicingOutputMessage(object sender, EventArgs e)
{
StringEventArgs message = e as StringEventArgs;
ActivePrintStatusText = message.Data;
}
override protected void AddChildElements()
{
activePrintPreviewImage = new PartThumbnailWidget(null, "part_icon_transparent_100x100.png", "building_thumbnail_100x100.png", new Vector2(115, 115));
activePrintPreviewImage.VAnchor = VAnchor.ParentTop;
activePrintPreviewImage.Padding = new BorderDouble(0);
activePrintPreviewImage.HoverBackgroundColor = new RGBA_Bytes();
activePrintPreviewImage.BorderWidth = 3;
FlowLayoutWidget temperatureWidgets = new FlowLayoutWidget(FlowDirection.TopToBottom);
{
IndicatorWidget extruderTemperatureWidget = new ExtruderTemperatureWidget();
IndicatorWidget bedTemperatureWidget = new BedTemperatureWidget();
temperatureWidgets.AddChild(extruderTemperatureWidget);
temperatureWidgets.AddChild(bedTemperatureWidget);
}
temperatureWidgets.VAnchor |= VAnchor.ParentTop;
temperatureWidgets.Margin = new BorderDouble(left: 6);
FlowLayoutWidget printStatusContainer = getActivePrinterInfo();
printStatusContainer.VAnchor |= VAnchor.ParentTop;
FlowLayoutWidget iconContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
iconContainer.Name = "PrintStatusRow.IconContainer";
iconContainer.VAnchor |= VAnchor.ParentTop;
iconContainer.Margin = new BorderDouble(top: 3);
iconContainer.AddChild(GetAutoLevelIndicator());
this.AddChild(activePrintPreviewImage);
this.AddChild(printStatusContainer);
this.AddChild(iconContainer);
this.AddChild(temperatureWidgets);
UpdatePrintStatus();
UpdatePrintItemName();
}
private Button GetAutoLevelIndicator()
{
ImageButtonFactory imageButtonFactory = new ImageButtonFactory();
string notifyIconPath = Path.Combine("Icons", "PrintStatusControls", "leveling-16x16.png");
string notifyHoverIconPath = Path.Combine("Icons", "PrintStatusControls", "leveling-16x16.png");
Button notifyButton = imageButtonFactory.Generate(notifyIconPath, notifyHoverIconPath);
notifyButton.Cursor = Cursors.Hand;
notifyButton.Margin = new Agg.BorderDouble(top: 3);
notifyButton.MouseEnterBounds += (sender, mouseEvent) => { HelpTextWidget.Instance.ShowHoverText("Print leveling is enabled."); };
notifyButton.MouseLeaveBounds += (sender, mouseEvent) => { HelpTextWidget.Instance.HideHoverText(); };
notifyButton.Visible = ActivePrinterProfile.Instance.DoPrintLeveling;
ActivePrinterProfile.Instance.ActivePrinterChanged.RegisterEvent((sender, e) =>
{
notifyButton.Visible = ActivePrinterProfile.Instance.DoPrintLeveling;
}, ref unregisterEvents);
ActivePrinterProfile.Instance.DoPrintLevelingChanged.RegisterEvent((sender, e) =>
{
notifyButton.Visible = ActivePrinterProfile.Instance.DoPrintLeveling;
}, ref unregisterEvents);
return notifyButton;
}
private FlowLayoutWidget getActivePrinterInfo()
{
FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom);
container.Margin = new BorderDouble(6, 0,6,3);
container.HAnchor = HAnchor.ParentLeftRight;
container.VAnchor |= VAnchor.ParentTop;
FlowLayoutWidget topRow = new FlowLayoutWidget();
topRow.Name = "PrintStatusRow.ActivePrinterInfo.TopRow";
topRow.HAnchor = HAnchor.ParentLeftRight;
string nextPrintLbl = new LocalizedString("Next Print").Translated;
string nextPrintLblFull = string.Format("{0}:", nextPrintLbl);
activePrintLabel = getPrintStatusLabel(nextPrintLblFull, pointSize: 11);
activePrintLabel.VAnchor = VAnchor.ParentTop;
topRow.AddChild(activePrintLabel);
activePrintName = getPrintStatusLabel("this is the biggest name we will allow", pointSize: 14);
activePrintName.AutoExpandBoundsToText = false;
activePrintStatus = getPrintStatusLabel("this is the biggest label we will allow - bigger", pointSize: 11);
activePrintStatus.AutoExpandBoundsToText = false;
activePrintStatus.Text = "";
activePrintStatus.Margin = new BorderDouble(top: 3);
activePrintInfo = getPrintStatusLabel("", pointSize: 11);
activePrintInfo.AutoExpandBoundsToText = true;
PrintActionRow printActionRow = new PrintActionRow();
container.AddChild(topRow);
container.AddChild(activePrintName);
container.AddChild(activePrintStatus);
//container.AddChild(activePrintInfo);
container.AddChild(printActionRow);
container.AddChild(new MessageActionRow());
return container;
}
protected override void AddHandlers()
{
PrinterCommunication.Instance.ActivePrintItemChanged.RegisterEvent(onPrintItemChanged, ref unregisterEvents);
PrinterCommunication.Instance.ConnectionStateChanged.RegisterEvent(onStateChanged, ref unregisterEvents);
PrinterCommunication.Instance.WroteLine.RegisterEvent(Instance_WroteLine, ref unregisterEvents);
PrinterCommunication.Instance.ActivePrintItemChanged.RegisterEvent(onActivePrintItemChanged, ref unregisterEvents);
}
public override void OnClosed(EventArgs e)
{
if (unregisterEvents != null)
{
unregisterEvents(this, null);
}
base.OnClosed(e);
}
public override void OnDraw(Graphics2D graphics2D)
{
timeSinceLastDrawTime.Restart();
base.OnDraw(graphics2D);
}
void OnIdle(object state)
{
if (PrinterCommunication.Instance.PrinterIsPrinting)
{
if (!timeSinceLastDrawTime.IsRunning)
{
timeSinceLastDrawTime.Start();
}
else if (timeSinceLastDrawTime.ElapsedMilliseconds > 999)
{
UpdatePrintStatus();
timeSinceLastDrawTime.Restart();
}
}
if (!WidgetHasBeenClosed)
{
UiThread.RunOnIdle(OnIdle);
}
}
void Instance_WroteLine(object sender, EventArgs e)
{
UpdatePrintStatus();
}
private void onStateChanged(object sender, EventArgs e)
{
UpdatePrintStatus();
}
private void UpdatePrintStatus()
{
if (PrinterCommunication.Instance.ActivePrintItem != null)
{
int totalSecondsInPrint = PrinterCommunication.Instance.TotalSecondsInPrint;
int totalHoursInPrint = (int)(totalSecondsInPrint / (60 * 60));
int totalMinutesInPrint = (int)(totalSecondsInPrint / 60 - totalHoursInPrint * 60);
totalSecondsInPrint = totalSecondsInPrint % 60;
string totalTimeLabel = new LocalizedString("Est. Print Time").Translated;
string calculatingLabel = new LocalizedString("Calculating...").Translated;
string totalPrintTimeText;
if (totalSecondsInPrint > 0)
{
if (totalHoursInPrint > 0)
{
totalPrintTimeText = string.Format("{3} {0}h {1:00}m {2:00}s",
totalHoursInPrint,
totalMinutesInPrint,
totalSecondsInPrint,
totalTimeLabel);
}
else
{
totalPrintTimeText = string.Format("{2} {0}m {1:00}s",
totalMinutesInPrint,
totalSecondsInPrint,
totalTimeLabel);
}
}
else
{
totalPrintTimeText = string.Format("{0}: {1}", totalTimeLabel, calculatingLabel);
}
//GC.WaitForFullGCComplete();
string printPercentRemainingText;
string printPercentCompleteTxt = new LocalizedString("complete").Translated;
printPercentRemainingText = string.Format("{0:0.0}% {1}", PrinterCommunication.Instance.PercentComplete,printPercentCompleteTxt);
switch (PrinterCommunication.Instance.CommunicationState)
{
case PrinterCommunication.CommunicationStates.PreparingToPrint:
string preparingPrintLbl = new LocalizedString("Preparing To Print").Translated;
string preparingPrintLblFull = string.Format("{0}:", preparingPrintLbl);
activePrintLabel.Text = preparingPrintLblFull;
//ActivePrintStatusText = ""; // set by slicer
activePrintInfo.Text = "";
break;
case PrinterCommunication.CommunicationStates.Printing:
{
activePrintLabel.Text = PrinterCommunication.Instance.PrintingStateString;
ActivePrintStatusText = totalPrintTimeText;
}
break;
case PrinterCommunication.CommunicationStates.Paused:
{
string activePrintLblTxt = new LocalizedString ("Printing Paused").Translated;
string activePrintLblTxtFull = string.Format("{0}:", activePrintLblTxt);
activePrintLabel.Text = activePrintLblTxtFull;
ActivePrintStatusText = totalPrintTimeText;
}
break;
case PrinterCommunication.CommunicationStates.FinishedPrint:
string donePrintingTxt = new LocalizedString ("Done Printing").Translated;
string donePrintingTxtFull = string.Format ("{0}:", donePrintingTxt);
activePrintLabel.Text = donePrintingTxtFull;
ActivePrintStatusText = totalPrintTimeText;
break;
default:
string nextPrintLblActive = new LocalizedString ("Next Print").Translated;
string nextPrintLblActiveFull = string.Format("{0}: ", nextPrintLblActive);
activePrintLabel.Text = nextPrintLblActiveFull;
ActivePrintStatusText = "";
activePrintInfo.Text = "";
break;
}
}
else
{
string nextPrintLabel = new LocalizedString ("Next Print").Translated;
string nextPrintLabelFull = string.Format ("{0}:", nextPrintLabel);
activePrintLabel.Text = nextPrintLabelFull;
ActivePrintStatusText = string.Format(new LocalizedString("Press 'Add' to choose an item to print").Translated);
activePrintInfo.Text = "";
}
}
protected void onPrintItemChanged(object sender, EventArgs e)
{
UpdatePrintItemName();
UpdatePrintStatus();
}
void UpdatePrintItemName()
{
if (PrinterCommunication.Instance.ActivePrintItem != null)
{
string labelName = textInfo.ToTitleCase(PrinterCommunication.Instance.ActivePrintItem.Name);
labelName = labelName.Replace('_', ' ');
this.activePrintName.Text = labelName;
}
else
{
this.activePrintName.Text = new LocalizedString("No items in the print queue").Translated;
}
}
private TextWidget getPrintStatusLabel(string text, int pointSize)
{
TextWidget widget = new TextWidget(text, pointSize: pointSize);
widget.TextColor = RGBA_Bytes.White;
widget.AutoExpandBoundsToText = true;
widget.MinimumSize = new Vector2(widget.Width, widget.Height);
return widget;
}
}
class ExtruderTemperatureWidget : IndicatorWidget
{
public ExtruderTemperatureWidget()
: base("150.3°")
{
AddHandlers();
setToCurrentTemperature();
}
event EventHandler unregisterEvents;
void AddHandlers()
{
PrinterCommunication.Instance.ExtruderTemperatureRead.RegisterEvent(onTemperatureRead, ref unregisterEvents);
this.MouseEnterBounds += onMouseEnterBounds;
this.MouseLeaveBounds += onMouseLeaveBounds;
}
public override void OnClosed(EventArgs e)
{
if (unregisterEvents != null)
{
unregisterEvents(this, null);
}
base.OnClosed(e);
}
void onMouseEnterBounds(Object sender, EventArgs e)
{
HelpTextWidget.Instance.ShowHoverText(new LocalizedString("Extruder Temperature").Translated);
}
void onMouseLeaveBounds(Object sender, EventArgs e)
{
HelpTextWidget.Instance.HideHoverText();
}
void setToCurrentTemperature()
{
string tempDirectionIndicator = "";
if (PrinterCommunication.Instance.TargetExtruderTemperature > 0)
{
if ((int)(PrinterCommunication.Instance.TargetExtruderTemperature + 0.5) < (int)(PrinterCommunication.Instance.ActualExtruderTemperature + 0.5))
{
tempDirectionIndicator = "↓";
}
else if ((int)(PrinterCommunication.Instance.TargetExtruderTemperature + 0.5) > (int)(PrinterCommunication.Instance.ActualExtruderTemperature + 0.5))
{
tempDirectionIndicator = "↑";
}
}
this.IndicatorValue = string.Format("{0:0.#}°{1}", PrinterCommunication.Instance.ActualExtruderTemperature, tempDirectionIndicator);
}
void onTemperatureRead(Object sender, EventArgs e)
{
setToCurrentTemperature();
}
}
class BedTemperatureWidget : IndicatorWidget
{
//Not currently hooked up to anything
public BedTemperatureWidget()
: base("150.3°")
{
AddHandlers();
setToCurrentTemperature();
}
event EventHandler unregisterEvents;
void AddHandlers()
{
PrinterCommunication.Instance.BedTemperatureRead.RegisterEvent(onTemperatureRead, ref unregisterEvents);
this.MouseEnterBounds += onMouseEnterBounds;
this.MouseLeaveBounds += onMouseLeaveBounds;
}
public override void OnClosed(EventArgs e)
{
if (unregisterEvents != null)
{
unregisterEvents(this, null);
}
base.OnClosed(e);
}
void onMouseEnterBounds(Object sender, EventArgs e)
{
HelpTextWidget.Instance.ShowHoverText(new LocalizedString("Bed Temperature").Translated);
}
void onMouseLeaveBounds(Object sender, EventArgs e)
{
HelpTextWidget.Instance.HideHoverText();
}
void setToCurrentTemperature()
{
this.IndicatorValue = string.Format("{0:0.#}°", PrinterCommunication.Instance.ActualBedTemperature);
}
void onTemperatureRead(Object sender, EventArgs e)
{
setToCurrentTemperature();
}
}
class IndicatorWidget : GuiWidget
{
TextWidget indicatorTextWidget;
RGBA_Bytes borderColor = new RGBA_Bytes(255, 255, 255);
int borderWidth = 2;
public string IndicatorValue
{
get
{
return indicatorTextWidget.Text;
}
set
{
if (indicatorTextWidget.Text != value)
{
indicatorTextWidget.Text = value;
}
}
}
event EventHandler unregisterEvents;
public IndicatorWidget(string textValue)
: base(52, 52)
{
this.BackgroundColor = new RGBA_Bytes(255, 255, 255, 200);
indicatorTextWidget = new TextWidget(textValue, pointSize: 11);
indicatorTextWidget.TextColor = ActiveTheme.Instance.PrimaryAccentColor;
indicatorTextWidget.HAnchor = HAnchor.ParentCenter;
indicatorTextWidget.VAnchor = VAnchor.ParentCenter;
indicatorTextWidget.AutoExpandBoundsToText = true;
this.Margin = new BorderDouble(0, 2);
this.AddChild(indicatorTextWidget);
ActiveTheme.Instance.ThemeChanged.RegisterEvent(onThemeChanged, ref unregisterEvents);
}
public override void OnClosed(EventArgs e)
{
if (unregisterEvents != null)
{
unregisterEvents(this, null);
}
base.OnClosed(e);
}
private void onThemeChanged(object sender, EventArgs e)
{
this.indicatorTextWidget.TextColor = ActiveTheme.Instance.PrimaryAccentColor;
this.Invalidate();
}
public override void OnDraw(Graphics2D graphics2D)
{
base.OnDraw(graphics2D);
RectangleDouble Bounds = LocalBounds;
RoundedRect borderRect = new RoundedRect(this.LocalBounds, 0);
Stroke strokeRect = new Stroke(borderRect, borderWidth);
graphics2D.Render(strokeRect, borderColor);
}
}
}