From e95fd6f388eee3aa21e5f9a2a40976007384305d Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Fri, 25 Nov 2022 13:11:27 -0800 Subject: [PATCH] Made text work better in sheets Added WiFi login to qr code generator --- .../Primitives/ComponentObject3D.cs | 2 +- .../DesignTools/Primitives/QrCodeObject3D.cs | 63 +++++++++++++++++-- .../DesignTools/Sheets/SheetData.cs | 62 ++++++++++++++++-- .../DesignTools/Sheets/SheetObject3D.cs | 59 +++++++---------- .../View3D/Actions/SheetFieldWidget.cs | 10 +-- StaticData/Translations/Master.txt | 9 +++ .../DesignTools/SheetTests.cs | 39 +++++++----- 7 files changed, 176 insertions(+), 68 deletions(-) diff --git a/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs b/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs index 1744ea2a0..b61ff8c65 100644 --- a/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs +++ b/MatterControlLib/DesignTools/Primitives/ComponentObject3D.cs @@ -153,7 +153,7 @@ namespace MatterHackers.MatterControl.DesignTools if (firtSheet != null) { // We don't have any cache of the cell content, get the current content - double.TryParse(firtSheet.SheetData.EvaluateExpression(cellId2), out double value); + double.TryParse(firtSheet.SheetData.GetCellValue(cellId2), out double value); cellData2 = value.ToString(); } } diff --git a/MatterControlLib/DesignTools/Primitives/QrCodeObject3D.cs b/MatterControlLib/DesignTools/Primitives/QrCodeObject3D.cs index b6842a54e..fdf07f696 100644 --- a/MatterControlLib/DesignTools/Primitives/QrCodeObject3D.cs +++ b/MatterControlLib/DesignTools/Primitives/QrCodeObject3D.cs @@ -47,7 +47,7 @@ using QRCoder; namespace MatterHackers.MatterControl.DesignTools { [HideMeterialAndColor] - public class QrCodeObject3D : Object3D, IImageProvider, IObject3DControlsProvider + public class QrCodeObject3D : Object3D, IImageProvider, IObject3DControlsProvider, IPropertyGridModifier { private const double DefaultSizeMm = 60; @@ -69,6 +69,33 @@ namespace MatterHackers.MatterControl.DesignTools public override bool CanApply => false; + public enum QrCodeTypes + { + Text, + WiFi + } + + [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)] + public QrCodeTypes OutputOption { get; set; } = QrCodeTypes.Text; + + + // WIFI:S:;T:;P:;H:;; + [Description("The name of the WiFi network")] + public StringOrExpression SSID { get; set; } = ""; + + [Description("The password of the WiFi network")] + public StringOrExpression Password { get; set; } = ""; + + public enum SecurityTypes + { + WEP, + WPA, + None + } + + [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)] + public SecurityTypes Security { get; set; } = SecurityTypes.WPA; + public StringOrExpression Text { get; set; } = "https://www.matterhackers.com"; [DisplayName("")] @@ -247,8 +274,28 @@ namespace MatterHackers.MatterControl.DesignTools private ImageBuffer BuildImage() { - QRCodeGenerator qrGenerator = new QRCodeGenerator(); - QRCodeData qrCodeData = qrGenerator.CreateQrCode(Text.Value(this), QRCodeGenerator.ECCLevel.Q); + var text = Text.Value(this); + + if (OutputOption == QrCodeTypes.WiFi) + { + var ssid = SSID.Value(this).Replace(":", "\\:"); + var security = ""; + switch(Security) + { + case SecurityTypes.WPA: + security = "WPA"; + break; + case SecurityTypes.WEP: + security = "WEP"; + break; + } + var password = Password.Value(this).Replace(":", "\\:"); + + text = $"WIFI:S:{ssid};T:{security};P:{password};H:;;"; + } + + QRCodeGenerator qrGenerator = new QRCodeGenerator(); + QRCodeData qrCodeData = qrGenerator.CreateQrCode(text, QRCodeGenerator.ECCLevel.Q); QRCode qrCode = new QRCode(qrCodeData); System.Drawing.Bitmap qrCodeImage = qrCode.GetGraphic(16); @@ -471,5 +518,13 @@ namespace MatterHackers.MatterControl.DesignTools }); }); } - } + + public void UpdateControls(PublicPropertyChange change) + { + change.SetRowVisible(nameof(Text), () => OutputOption == QrCodeTypes.Text); + change.SetRowVisible(nameof(SSID), () => OutputOption == QrCodeTypes.WiFi); + change.SetRowVisible(nameof(Password), () => OutputOption == QrCodeTypes.WiFi); + change.SetRowVisible(nameof(Security), () => OutputOption == QrCodeTypes.WiFi); + } + } } \ No newline at end of file diff --git a/MatterControlLib/DesignTools/Sheets/SheetData.cs b/MatterControlLib/DesignTools/Sheets/SheetData.cs index 8c75792ef..b7d293c1a 100644 --- a/MatterControlLib/DesignTools/Sheets/SheetData.cs +++ b/MatterControlLib/DesignTools/Sheets/SheetData.cs @@ -32,6 +32,7 @@ using org.mariuszgromada.math.mxparser; using Newtonsoft.Json; using System.Linq; using System; +using g3; namespace MatterHackers.MatterControl.DesignTools { @@ -54,7 +55,37 @@ namespace MatterHackers.MatterControl.DesignTools } } - public string EvaluateExpression(string expression) + public string GetCellValue(string cellId) + { + lock (locker) + { + if (!tabelCalculated) + { + BuildTableConstants(); + } + + var cell = this[cellId]; + + var expression = cell.Expression; + + if (expression.StartsWith("=")) + { + expression = expression.Substring(1); + var evaluator = new Expression(expression.ToLower()); + AddConstants(evaluator); + var value = evaluator.calculate(); + + return value.ToString(); + } + else + { + // return the expression without evaluation + return expression; + } + } + } + + public string EvaluateExpression(string expression) { lock (locker) { @@ -65,9 +96,21 @@ namespace MatterHackers.MatterControl.DesignTools if(expression.StartsWith("=")) { - expression = expression.Substring(1); - } - var evaluator = new Expression(expression.ToLower()); + expression = expression.Substring(1).Trim(); + + // if it is a direct cell reference than return that cells value + if (expression.Length == 2) + { + var column = (uint)expression.Substring(0, 1).ToUpper()[0] - 'A'; + var row = (uint)expression.Substring(1, 1)[0] - '1'; + if (column < Width && row < Height) + { + return GetCellValue(CellId((int)column, (int)row)); + } + } + } + + var evaluator = new Expression(expression.ToLower()); AddConstants(evaluator); var value = evaluator.calculate(); @@ -83,6 +126,12 @@ namespace MatterHackers.MatterControl.DesignTools } } + /// + /// Return the cell at the given position + /// + /// The x index + /// The y index + /// The TableCell public TableCell this[int x, int y] { get @@ -102,6 +151,11 @@ namespace MatterHackers.MatterControl.DesignTools } } + /// + /// Get the Table cell for the given cellId + /// + /// + /// The table cell for the id public TableCell this[string cellId] { get diff --git a/MatterControlLib/DesignTools/Sheets/SheetObject3D.cs b/MatterControlLib/DesignTools/Sheets/SheetObject3D.cs index 255f4cd92..3d6404fc2 100644 --- a/MatterControlLib/DesignTools/Sheets/SheetObject3D.cs +++ b/MatterControlLib/DesignTools/Sheets/SheetObject3D.cs @@ -479,15 +479,34 @@ namespace MatterHackers.MatterControl.DesignTools inputExpression = ReplaceConstantsWithValues(owner, inputExpression); - // check if the expression is not an equation (does not start with "=") - if (inputExpression.Length > 0 && inputExpression[0] != '=') + // check if the expression is an equation (starts with "=") + if (inputExpression.Length > 0 && inputExpression[0] == '=') + { + // look through all the parents + var sheet = FindFirstSheet(owner); + if (sheet != null) + { + // try to manage the cell into the correct data type + string value = sheet.SheetData.EvaluateExpression(inputExpression); + return CastResult(value, inputExpression); + } + + // could not find a sheet, try to evaluate the expression directly + var evaluator = new Expression(inputExpression.ToLower()); + if (evaluator.checkSyntax()) + { + Debug.WriteLine(evaluator.getErrorMessage()); + } + + return CastResult(evaluator.calculate().ToString(), inputExpression); + } + else // not an equation so try to parse it directly { if (typeof(T) == typeof(string)) { return (T)(object)inputExpression; } - // not an equation so try to parse it directly if (double.TryParse(inputExpression, out var result)) { if (typeof(T) == typeof(double)) @@ -499,41 +518,9 @@ namespace MatterHackers.MatterControl.DesignTools return (T)(object)(int)Math.Round(result); } } - else - { - if (typeof(T) == typeof(double)) - { - return (T)(object)0.0; - } - if (typeof(T) == typeof(int)) - { - return (T)(object)0; - } - } - } - - if (inputExpression.Length > 0 && inputExpression[0] == '=') - { - inputExpression = inputExpression.Substring(1); - } - // look through all the parents - var sheet = FindFirstSheet(owner); - if (sheet != null) - { - // try to manage the cell into the correct data type - string value = sheet.SheetData.EvaluateExpression(inputExpression); - return CastResult(value, inputExpression); + return (T)(object)0; } - - // could not find a sheet, try to evaluate the expression directly - var evaluator = new Expression(inputExpression.ToLower()); - if(evaluator.checkSyntax()) - { - Debug.WriteLine(evaluator.getErrorMessage()); - } - - return CastResult(evaluator.calculate().ToString(), inputExpression); } /// diff --git a/MatterControlLib/PartPreviewWindow/View3D/Actions/SheetFieldWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/Actions/SheetFieldWidget.cs index d9f850262..b8f2bc425 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Actions/SheetFieldWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Actions/SheetFieldWidget.cs @@ -80,15 +80,7 @@ namespace MatterHackers.MatterControl.DesignTools private void UpdateContents() { - var expression = SheetData[x, y].Expression; - if (expression.StartsWith("=")) - { - content.Text = SheetData.EvaluateExpression(expression); - } - else - { - content.Text = expression; - } + content.Text = SheetData.GetCellValue(SheetData.CellId(x, y)); } public override void OnKeyPress(KeyPressEventArgs keyPressEvent) diff --git a/StaticData/Translations/Master.txt b/StaticData/Translations/Master.txt index 53088e113..1fe5c47d0 100644 --- a/StaticData/Translations/Master.txt +++ b/StaticData/Translations/Master.txt @@ -3415,6 +3415,9 @@ Translated:Output English:Output only the first layer of the print. Especially useful for outputting gcode data for applications like engraving or cutting. Translated:Output only the first layer of the print. Especially useful for outputting gcode data for applications like engraving or cutting. +English:Output Option +Translated:Output Option + English:Output Resolution Translated:Output Resolution @@ -4423,6 +4426,9 @@ Translated:seconds English:Sections Translated:Sections +English:Security +Translated:Security + English:Segments Translated:Segments @@ -4861,6 +4867,9 @@ Translated:Split English:Split Mesh Translated:Split Mesh +English:SSID +Translated:SSID + English:Stable Translated:Stable diff --git a/Tests/MatterControl.AutomationTests/DesignTools/SheetTests.cs b/Tests/MatterControl.AutomationTests/DesignTools/SheetTests.cs index c57abae88..e157361f7 100644 --- a/Tests/MatterControl.AutomationTests/DesignTools/SheetTests.cs +++ b/Tests/MatterControl.AutomationTests/DesignTools/SheetTests.cs @@ -24,25 +24,36 @@ namespace MatterHackers.MatterControl.Tests.Automation { var sheetData = new SheetData(4, 4); - sheetData[0, 0].Expression = "=4*2"; + void Test(string cell, string expression, string expected) + { + sheetData[cell].Expression = expression; + sheetData.Recalculate(); + Assert.AreEqual(expected, sheetData.GetCellValue(cell)); + } - Assert.AreEqual("8", sheetData.EvaluateExpression("A1")); - Assert.AreEqual("8", sheetData.EvaluateExpression("a1")); + // simple multiply retrived upper and lower case + Test("A1", "=4*2", "8"); + Test("a1", "=4*2", "8"); - sheetData["a2"].Expression = "=max(4, 5)"; - sheetData.Recalculate(); - Assert.AreEqual("5", sheetData.EvaluateExpression("a2")); + // make sure functions are working, max in this case + Test("a2", "=max(4, 5)", "5"); - sheetData["a3"].Expression = "=a1+a2"; - sheetData.Recalculate(); - Assert.AreEqual("13", sheetData.EvaluateExpression("a3")); + // make sure cell references are working + Test("a3", "=a1+a2", "13"); - sheetData["a4"].Expression = "=((4+5)/3+7)/5"; - sheetData.Recalculate(); - Assert.AreEqual("2", sheetData.EvaluateExpression("a4")); + // complex formulas are working + Test("a4", "=((4+5)/3+7)/5", "2"); - } - } + // complex formulas with references are working + Test("b1", "=(a4+a3)*.5", "7.5"); + + // constants work, like pi + Test("b2", "=pi", "3.141592653589793"); + + // check that we get string data back unmodified + Test("b3", "hello", "hello"); + } + } [TestFixture, Category("MatterControl.UI.Automation"), Parallelizable(ParallelScope.Children)] public class PrimitiveAndSheetsTests