diff --git a/src/Libraries/CoreNodeModels/DefineData.cs b/src/Libraries/CoreNodeModels/DefineData.cs index 9e9e6ae6d8e..1703a43f901 100644 --- a/src/Libraries/CoreNodeModels/DefineData.cs +++ b/src/Libraries/CoreNodeModels/DefineData.cs @@ -27,7 +27,6 @@ namespace CoreNodeModels [AlsoKnownAs("Data.DefineData")] public class DefineData : DSDropDownBase { - private List serializedItems; private bool isAutoMode = true; // default start with auto-detect 'on' private bool isList; private string displayValue = Properties.Resources.DefineDataDisplayValueMessage; @@ -48,7 +47,7 @@ public class DefineData : DSDropDownBase [JsonProperty] public bool IsAutoMode { - get { return isAutoMode; } + get => isAutoMode; set { isAutoMode = value; @@ -64,7 +63,7 @@ public bool IsAutoMode [JsonProperty] public bool IsList { - get { return isList; } + get => isList; set { isList = value; @@ -79,8 +78,8 @@ public bool IsList /// [JsonProperty] public string DisplayValue - { - get { return displayValue; } + { + get => displayValue; set { if (displayValue != value) @@ -93,10 +92,7 @@ public string DisplayValue [JsonIgnore] - public override bool IsInputNode - { - get { return true; } - } + public override bool IsInputNode => true; private string value = ""; @@ -146,7 +142,6 @@ private DefineData(IEnumerable inPorts, IEnumerable outPor private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { - } protected override void OnBuilt() @@ -170,7 +165,7 @@ public override IEnumerable BuildOutputAst(List>(DSCore.Data.IsSupportedDataNodeType); + var function = new Func>(EvaluateDefineDataNode); var functionInputs = new List { inputAstNodes[0], AstFactory.BuildStringNode((Items[SelectedIndex].Item as Data.DataNodeDynamoType).Type.ToString()), @@ -196,8 +191,8 @@ public override IEnumerable BuildOutputAst(List BuildOutputAst(List)data; + (bool IsValid, bool UpdateList, DataNodeDynamoType InputType) = (ValueTuple)data; if (IsAutoMode) { - if (resultData.UpdateList) + if (UpdateList) { IsList = !IsList; } - if (resultData.InputType != null) + if (InputType != null) { - if (!resultData.IsValid) + if (!IsValid) { // Assign to the correct value, if the object was of supported type - var index = Items.IndexOf(Items.First(i => i.Name.Equals(resultData.InputType.Name))); + var index = Items.IndexOf(Items.First(i => i.Name.Equals(InputType.Name))); SelectedIndex = index; } - if (!DisplayValue.Equals(resultData.InputType.Name)) + if (!DisplayValue.Equals(InputType.Name)) { - DisplayValue = resultData.InputType.Name; + DisplayValue = InputType.Name; } } } @@ -273,12 +267,6 @@ protected override SelectionState PopulateItemsCore(string currentSelection) return SelectionState.Restore; } - [OnSerializing] - private void OnSerializing(StreamingContext context) - { - serializedItems = Items.ToList(); - } - protected override bool UpdateValueCore(UpdateValueParams updateValueParams) { string name = updateValueParams.PropertyName; diff --git a/src/Libraries/CoreNodeModelsWpf/NodeViewCustomizations/DefineData.cs b/src/Libraries/CoreNodeModelsWpf/NodeViewCustomizations/DefineData.cs index 101a28e6d9b..09e9e62de32 100644 --- a/src/Libraries/CoreNodeModelsWpf/NodeViewCustomizations/DefineData.cs +++ b/src/Libraries/CoreNodeModelsWpf/NodeViewCustomizations/DefineData.cs @@ -16,7 +16,7 @@ namespace CoreNodeModelsWpf.Nodes /// /// View customizer for DefineData node model. /// - public class DefineDataNodeViewCustomization : DropDownNodeViewCustomization, INodeViewCustomization + internal class DefineDataNodeViewCustomization : DropDownNodeViewCustomization, INodeViewCustomization { private ComboBox dropdown; private ToggleButton modeToggleButton; diff --git a/src/Libraries/CoreNodes/Data.cs b/src/Libraries/CoreNodes/Data.cs index 0064f77b1b1..959586acacc 100644 --- a/src/Libraries/CoreNodes/Data.cs +++ b/src/Libraries/CoreNodes/Data.cs @@ -194,8 +194,8 @@ public static string StringifyJSON([ArbitraryDimensionArrayImport] object values { var settings = new JsonSerializerSettings() { - Converters = new JsonConverter[] - { + Converters = + [ new DictConverter(), new DesignScriptGeometryConverter(), new ColorConveter(), @@ -203,18 +203,15 @@ public static string StringifyJSON([ArbitraryDimensionArrayImport] object values #if _WINDOWS new PNGImageConverter(), #endif - } + ] }; - StringBuilder sb = new StringBuilder(256); - using (var writer = new StringWriter(sb, CultureInfo.InvariantCulture)) - { - using (var jsonWriter = new MaxDepthJsonTextWriter(writer)) - { - JsonSerializer.Create(settings).Serialize(jsonWriter, values); - } - return writer.ToString(); - } + StringBuilder sb = new(256); + using StringWriter writer = new(sb, CultureInfo.InvariantCulture); + using MaxDepthJsonTextWriter jsonWriter = new(writer); + JsonSerializer.Create(settings).Serialize(jsonWriter, values); + + return writer.ToString(); } /// @@ -537,37 +534,29 @@ public static Dictionary Remember([ArbitraryDimensionArrayImport /// /// A class representing a DataType supported by Dynamo /// - public class DataNodeDynamoType + internal class DataNodeDynamoType(Type type, string name = null) { /// /// The underlying Type /// - public Type Type { get; private set; } + public Type Type { get; private set; } = type; /// /// An optional Name to override the Type name (`Number` instead of `long`) /// - public string Name { get; private set; } + public string Name { get; private set; } = name ?? type.Name; /// /// The hierarchical level to be displayed in the UI /// - public int Level { get; private set; } + public int Level { get; private set; } = 0; /// /// If the type is a last child of a hierarchy (for UI purposes) /// - public bool IsLastChild { get; private set; } + public bool IsLastChild { get; private set; } = false; /// /// The parent of the Type, if any /// public DataNodeDynamoType Parent { get; private set; } - public DataNodeDynamoType(Type type, string name = null) - { - Type = type; - Name = name ?? type.Name; - Level = 0; - IsLastChild = false; - } - public DataNodeDynamoType(Type type, int level, bool isLastChild = false, string name = null, DataNodeDynamoType parent = null) : this(type, name) { @@ -588,62 +577,54 @@ public DataNodeDynamoType(Type type, int level, bool isLastChild = false, string /// static Data() { - var typeList = new List(); - typeList.Add(new DataNodeDynamoType(typeof(bool))); - typeList.Add(new DataNodeDynamoType(typeof(BoundingBox))); - typeList.Add(new DataNodeDynamoType(typeof(CoordinateSystem))); - - // Subtypes of Curve - var crv = new DataNodeDynamoType(typeof(Curve), 0, false, null, null); - typeList.Add(crv); - typeList.Add(new DataNodeDynamoType(typeof(Arc), 1, false, null, crv)); - typeList.Add(new DataNodeDynamoType(typeof(Circle), 1, false, null, crv)); - typeList.Add(new DataNodeDynamoType(typeof(Ellipse), 1, false, null, crv)); - typeList.Add(new DataNodeDynamoType(typeof(EllipseArc), 1, false, null, crv)); - typeList.Add(new DataNodeDynamoType(typeof(Helix), 1, false, null, crv)); - typeList.Add(new DataNodeDynamoType(typeof(Line), 1, false, null, crv)); - typeList.Add(new DataNodeDynamoType(typeof(NurbsCurve), 1, false, null, crv)); - - var polyCurve = new DataNodeDynamoType(typeof(PolyCurve), 1, false, null, crv); + var curve = new DataNodeDynamoType(typeof(Curve), 0, false, null, null); + var polyCurve = new DataNodeDynamoType(typeof(PolyCurve), 1, false, null, curve); var polygon = new DataNodeDynamoType(typeof(Polygon), 2, false, null, polyCurve); // polygon is subtype of polyCurve var rectangle = new DataNodeDynamoType(typeof(Autodesk.DesignScript.Geometry.Rectangle), 3, true, null, polyCurve); // rectangle is subtype of polygon - - typeList.Add(polyCurve); - typeList.Add(polygon); - typeList.Add(rectangle); - typeList.Add(new DataNodeDynamoType(typeof(System.DateTime))); - typeList.Add(new DataNodeDynamoType(typeof(double), "Number")); - typeList.Add(new DataNodeDynamoType(typeof(long), "Integer")); - typeList.Add(new DataNodeDynamoType(typeof(Location))); - typeList.Add(new DataNodeDynamoType(typeof(Mesh))); - typeList.Add(new DataNodeDynamoType(typeof(Plane))); - typeList.Add(new DataNodeDynamoType(typeof(Autodesk.DesignScript.Geometry.Point))); - - // Subtypes of Solid var solid = new DataNodeDynamoType(typeof(Solid), 0, false, null, null); var cone = new DataNodeDynamoType(typeof(Cone), 1, false, null, solid); // cone is subtype of solid var cylinder = new DataNodeDynamoType(typeof(Cylinder), 2, false, null, cone); // cylinder is subtype of cone var cuboid = new DataNodeDynamoType(typeof(Cuboid), 1, false, null, solid); // cuboid is subtype of solid var sphere = new DataNodeDynamoType(typeof(Sphere), 1, true, null, solid); // sphere is subtype of solid - typeList.Add(solid); - typeList.Add(cone); - typeList.Add(cylinder); - typeList.Add(cuboid); - typeList.Add(sphere); - typeList.Add(new DataNodeDynamoType(typeof(string))); - - // Subtypes of Surface var surface = new DataNodeDynamoType(typeof(Surface), 0, false, null, null); - var nurbsSrf = new DataNodeDynamoType(typeof(NurbsSurface), 1, false, null, surface); // nurbsSrf is subtype of surface - var polySrf = new DataNodeDynamoType(typeof(PolySurface), 1, true, null, surface); // polySrf is subtype of surface - typeList.Add(surface); - typeList.Add(nurbsSrf); - typeList.Add(polySrf); - typeList.Add(new DataNodeDynamoType(typeof(System.TimeSpan))); - typeList.Add(new DataNodeDynamoType(typeof(UV))); - typeList.Add(new DataNodeDynamoType(typeof(Vector))); + var typeList = new List + { + new(typeof(bool)), + new(typeof(BoundingBox)), + new(typeof(CoordinateSystem)), + curve, + new(typeof(Arc), 1, false, null, curve), + new(typeof(Circle), 1, false, null, curve), + new(typeof(Ellipse), 1, false, null, curve), + new(typeof(EllipseArc), 1, false, null, curve), + new(typeof(Helix), 1, false, null, curve), + new(typeof(Line), 1, false, null, curve), + new(typeof(NurbsCurve), 1, false, null, curve), + polyCurve, + polygon, + rectangle, + new(typeof(System.DateTime)), + new(typeof(double), "Number"), + new(typeof(long), "Integer"), + new(typeof(Location)), + new(typeof(Mesh)), + new(typeof(Plane)), + new(typeof(Autodesk.DesignScript.Geometry.Point)), + solid, + cone, + cylinder, + cuboid, + sphere, + new(typeof(string)), + surface, + new(typeof(NurbsSurface), 1, false, null, surface), + new(typeof(PolySurface), 1, true, null, surface), + new(typeof(System.TimeSpan)), + new(typeof(UV)), + new(typeof(Vector)) + }; DataNodeDynamoTypeList = new ReadOnlyCollection(typeList); } @@ -653,7 +634,6 @@ static Data() /// /// The dictionary to extract the value from /// The key of the key/value pair - /// [IsVisibleInDynamoLibrary(false)] public static object SafeExtractDictionaryValue(Dictionary dict, string key) { @@ -666,17 +646,17 @@ public static object SafeExtractDictionaryValue(Dictionary dict, } /// - /// This is the function used by AST + /// This is the function used by AST to evaluate the Define Data node. /// Handles some of the the node logic while performing the validation /// /// Upstream input value - /// The Type as string (it would be better to pass an object of type 'Type' for direct type comparison) + /// The Type as string (Todo: it would be better to pass an object of type 'Type' for direct type comparison) /// If the input is of type `ArrayList` /// If the node is in Auto mode - /// The value coming from Dynamo Player - /// + /// The value injected into the node by Dynamo Player, if any. [IsVisibleInDynamoLibrary(false)] - public static Dictionary IsSupportedDataNodeType([ArbitraryDimensionArrayImport] object inputValue, + [Obsolete("This method must be public for the Define Data node to function but is not intended as external API. The method's signature may change in the future.")] + public static Dictionary EvaluateDefineDataNode([ArbitraryDimensionArrayImport] object inputValue, string typeString, bool isList, bool isAutoMode, string playerValue) { @@ -719,18 +699,15 @@ public static Dictionary IsSupportedDataNodeType([ArbitraryDimen if (isAutoMode) { // If running in AutoMode, then we would propagate the actual Type and List value and validate against them - bool updateList = false; - - var assertList = inputValue is ArrayList; - if (assertList != isList) - { - updateList = true; - } + // List logic + var arrayList = inputValue as ArrayList; + bool assertList = arrayList is not null; + bool updateList = assertList != isList; // Type logic - we try to 'guess' the type of the object if (type == null || !IsSupportedDataNodeDynamoType(inputValue, type.Type, assertList)) { - var valueType = assertList ? FindCommonAncestor(inputValue) : inputValue.GetType(); + var valueType = assertList ? FindCommonAncestor(arrayList) : inputValue.GetType(); if (valueType == null) { // We couldn't find a common ancestor - list containing unsupported or incompatible data types @@ -826,13 +803,10 @@ private static string ConcatenateUniqueDataTypes(object inputValue) /// /// A function to help find the type in case an ArrayList of objects was passed in AutoMode /// - /// The input value, expected to be of type ArrayList + /// The input value, expected to be of type ArrayList /// - private static Type FindCommonAncestor(object inputValue) + private static Type FindCommonAncestor(ArrayList list) { - if (inputValue is not ArrayList) return null; // this should not happen - var list = inputValue as ArrayList; - if (list.Count == 1) return list[0].GetType(); // Only one node, so it's the "common" ancestor @@ -927,7 +901,7 @@ private static DataNodeDynamoType FindCommonAncestorBetweenTwoNodes(DataNodeDyna /// private static List GetListFromTypes(ArrayList list) { - List typeList = new List(); + List typeList = []; foreach (var item in list) { var matchingType = DataNodeDynamoTypeList.FirstOrDefault(x => x.Type == item.GetType()); @@ -940,22 +914,17 @@ private static List GetListFromTypes(ArrayList list) } /// - /// Check if the input object is a single value or an ArrayList + /// Check if the input object is a single value or a single-level ArrayList. /// /// The input object to evaluate /// private static bool IsSingleValueOrSingleLevelArrayList(object obj) { - if (obj == null) return true; - - // Check if the object is a string, since strings are IEnumerable but usually considered single values - if (obj is string) return true; - if (obj is ArrayList arrayList) { foreach (var item in arrayList) { - if (item is IEnumerable && !(item is string)) + if (item is IEnumerable && item is not string) { return false; } @@ -963,7 +932,8 @@ private static bool IsSingleValueOrSingleLevelArrayList(object obj) return true; } - if (obj is IEnumerable) return false; + // Check if the object is a string, since strings are IEnumerable but usually considered single values + if (obj is IEnumerable && obj is not string) return false; return true; } @@ -991,7 +961,7 @@ internal static bool IsSupportedDataNodeDynamoType([ArbitraryDimensionArrayImpor } else { - if (!(inputValue is ArrayList arrayList)) return false; + if (inputValue is not ArrayList arrayList) return false; foreach (var item in arrayList) { diff --git a/src/Libraries/CoreNodes/Properties/AssemblyInfo.cs b/src/Libraries/CoreNodes/Properties/AssemblyInfo.cs index a7f530fff25..59de657a4e9 100644 --- a/src/Libraries/CoreNodes/Properties/AssemblyInfo.cs +++ b/src/Libraries/CoreNodes/Properties/AssemblyInfo.cs @@ -13,5 +13,3 @@ [assembly: InternalsVisibleTo("DynamoCoreTests")] [assembly: InternalsVisibleTo("DynamoCoreWpfTests")] [assembly: InternalsVisibleTo("DSCoreNodesTests")] -[assembly: InternalsVisibleTo("CoreNodeModels")] -[assembly: InternalsVisibleTo("DynamoCoreTests")] diff --git a/src/LibraryViewExtensionWebView2/Packages/LibrarieJS/layoutSpecs.json b/src/LibraryViewExtensionWebView2/Packages/LibrarieJS/layoutSpecs.json index f1946b47962..a184f4b81e6 100644 --- a/src/LibraryViewExtensionWebView2/Packages/LibrarieJS/layoutSpecs.json +++ b/src/LibraryViewExtensionWebView2/Packages/LibrarieJS/layoutSpecs.json @@ -519,6 +519,9 @@ }, { "path": "DSCoreNodes.DSCore.Object.Type" + }, + { + "path": "Core.Data.DefineData" } ], "childElements": [] @@ -1190,9 +1193,6 @@ }, { "path": "Core.Data.Remember" - }, - { - "path": "Core.Data.DefineData" } ], "childElements": [] diff --git a/test/DynamoCoreTests/DSCoreDataTests.cs b/test/DynamoCoreTests/DSCoreDataTests.cs index 82f6cacddbf..876204ec66a 100644 --- a/test/DynamoCoreTests/DSCoreDataTests.cs +++ b/test/DynamoCoreTests/DSCoreDataTests.cs @@ -913,7 +913,7 @@ public void ThrowsCorrectErrorTypes() 10, false }; - var ex = Assert.Throws(() => DSCore.Data.IsSupportedDataNodeType(listInput, booleanString, true, true, "")); + var ex = Assert.Throws(() => DSCore.Data.EvaluateDefineDataNode(listInput, booleanString, true, true, "")); Assert.That(ex.Message.Equals(DSCore.Properties.Resources.DefineDataSupportedInputValueExceptionMessage)); @@ -924,26 +924,26 @@ public void ThrowsCorrectErrorTypes() 10, false }; - ex = Assert.Throws(() => DSCore.Data.IsSupportedDataNodeType(arrayListInput, booleanString, true, true, "")); + ex = Assert.Throws(() => DSCore.Data.EvaluateDefineDataNode(arrayListInput, booleanString, true, true, "")); Assert.That(ex.Message.Split("{")[0].StartsWith(DSCore.Properties.Resources.DefineDataUnsupportedCombinationOfDataTypesExceptionMessage.Split("{")[0])); // Wrong DynamoPlayer input var input = "Test"; var dynamoPlayerInput = Color.Red.ToString(); - ex = Assert.Throws(() => DSCore.Data.IsSupportedDataNodeType(input, booleanString, true, true, dynamoPlayerInput)); + ex = Assert.Throws(() => DSCore.Data.EvaluateDefineDataNode(input, booleanString, true, true, dynamoPlayerInput)); Assert.That(ex.Message.Equals(DSCore.Properties.Resources.Exception_Deserialize_Unsupported_Cache)); // Invalid input var invalidTypeInput = Color.Red; - ex = Assert.Throws(() => DSCore.Data.IsSupportedDataNodeType(invalidTypeInput, booleanString, true, true, "")); + ex = Assert.Throws(() => DSCore.Data.EvaluateDefineDataNode(invalidTypeInput, booleanString, true, true, "")); Assert.That(ex.Message.Split("{")[0].StartsWith(DSCore.Properties.Resources.DefineDataUnsupportedDataTypeExceptionMessage.Split("{")[0])); // Detect type - unexpected input var detectTypeInput = 1; - ex = Assert.Throws(() => DSCore.Data.IsSupportedDataNodeType(detectTypeInput, booleanString, false, false, "")); + ex = Assert.Throws(() => DSCore.Data.EvaluateDefineDataNode(detectTypeInput, booleanString, false, false, "")); Assert.That(ex.Message.Split("{")[0].StartsWith(DSCore.Properties.Resources.DefineDataUnexpectedInputExceptionMessage.Split("{")[0])); } } diff --git a/test/Tools/docGeneratorTestFiles/sampledictionarycontent/Dynamo_Nodes_Documentation.json b/test/Tools/docGeneratorTestFiles/sampledictionarycontent/Dynamo_Nodes_Documentation.json index cef5a1e29ea..bc748da91db 100644 --- a/test/Tools/docGeneratorTestFiles/sampledictionarycontent/Dynamo_Nodes_Documentation.json +++ b/test/Tools/docGeneratorTestFiles/sampledictionarycontent/Dynamo_Nodes_Documentation.json @@ -4358,7 +4358,7 @@ "Name": "DefineData", "imageFile": ["DefineData"], "dynFile": ["DefineData"], - "folderPath": "ImportExport/Data/Action", + "folderPath": "Input/Object/Action", "inDepth": "Validates and returns data from a currently or previously connected node." } ]