diff --git a/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObject.cs b/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObject.cs index b137c5dcfb..d5416f1b54 100644 --- a/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObject.cs +++ b/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObject.cs @@ -25,7 +25,6 @@ namespace ConnectorGrasshopper; public class CreateSchemaObject : SelectKitComponentBase, IGH_VariableParameterComponent { - private GH_Document _document; private DebounceDispatcher nicknameChangeDebounce = new(); private bool readFailed; @@ -179,8 +178,6 @@ public override void AddedToDocument(GH_Document document) return; } - _document = document; - var dialog = new CreateSchemaObjectDialog(); dialog.Owner = Instances.EtoDocumentEditor; var mouse = Control.MousePosition; @@ -231,6 +228,8 @@ public void SwitchConstructor(ConstructorInfo constructor) foreach (var p in props) RegisterPropertyAsInputParameter(p, k++); + UserInterfaceUtils.CreateCanvasDropdownForAllEnumInputs(this, props); + Name = constructor.GetCustomAttribute().Name; Description = constructor.GetCustomAttribute().Description; @@ -288,23 +287,9 @@ private void RegisterPropertyAsInputParameter(ParameterInfo param, int index) newInputParam.Access = GH_ParamAccess.item; Params.RegisterInputParam(newInputParam, index); - - //add dropdown - if (propType.IsEnum) - { - //expire solution so that node gets proper size - ExpireSolution(true); - - var instance = Activator.CreateInstance(propType); - - var vals = Enum.GetValues(propType).Cast().Select(x => x.ToString()).ToList(); - var options = CreateDropDown(propName, vals, Attributes.Bounds.X, Params.Input[index].Attributes.Bounds.Y); - _document.AddObject(options, false); - Params.Input[index].AddSource(options); - } } - public static GH_ValueList CreateDropDown(string name, List values, float x, float y) + public static GH_ValueList CreateDropDown(string name, List<(string name, int value)> values, float x, float y) { var valueList = new GH_ValueList(); valueList.CreateAttributes(); @@ -314,13 +299,12 @@ public static GH_ValueList CreateDropDown(string name, List values, floa valueList.ListMode = GH_ValueListMode.DropDown; valueList.ListItems.Clear(); - values = values.OrderBy(x=>x).ToList(); - for (int i = 0; i < values.Count; i++) - valueList.ListItems.Add(new GH_ValueListItem(values[i], i.ToString())); - + valueList.ListItems.Add(new GH_ValueListItem(values[i].name, values[i].value.ToString())); + valueList.Attributes.Pivot = new PointF(x - 200, y - 10); + valueList.ListItems.Sort((item, listItem) => string.Compare(item.Name, listItem.Name)); return valueList; } diff --git a/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObjectBase.cs b/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObjectBase.cs index e063c7e366..4d5827df9c 100644 --- a/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObjectBase.cs +++ b/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObjectBase.cs @@ -275,6 +275,8 @@ public void SetupComponent(ConstructorInfo constructor) foreach (var p in props) RegisterPropertyAsInputParameter(p, k++); + UserInterfaceUtils.CreateCanvasDropdownForAllEnumInputs(this, props); + Name = constructor.GetCustomAttribute().Name; Description = constructor.GetCustomAttribute().Description; @@ -330,38 +332,6 @@ private void RegisterPropertyAsInputParameter(ParameterInfo param, int index) newInputParam.Access = GH_ParamAccess.item; Params.RegisterInputParam(newInputParam, index); - - //add dropdown - if (propType.IsEnum) - { - //expire solution so that node gets proper size - ExpireSolution(true); - - var instance = Activator.CreateInstance(propType); - - var vals = Enum.GetValues(propType).Cast().Select(x => x.ToString()).ToList(); - var options = CreateDropDown(propName, vals, Attributes.Bounds.X, Params.Input[index].Attributes.Bounds.Y); - OnPingDocument().AddObject(options, false); - Params.Input[index].AddSource(options); - } - } - - public static GH_ValueList CreateDropDown(string name, List values, float x, float y) - { - var valueList = new GH_ValueList(); - valueList.CreateAttributes(); - valueList.Name = name; - valueList.NickName = name + ":"; - valueList.Description = "Select an option..."; - valueList.ListMode = GH_ValueListMode.DropDown; - valueList.ListItems.Clear(); - - for (int i = 0; i < values.Count; i++) - valueList.ListItems.Add(new GH_ValueListItem(values[i], i.ToString())); - - valueList.Attributes.Pivot = new PointF(x - 200, y - 10); - - return valueList; } public override void SolveInstanceWithLogContext(IGH_DataAccess DA) diff --git a/ConnectorGrasshopper/ConnectorGrasshopperUtils/UserInterfaceUtils.cs b/ConnectorGrasshopper/ConnectorGrasshopperUtils/UserInterfaceUtils.cs new file mode 100644 index 0000000000..0b36ef3b55 --- /dev/null +++ b/ConnectorGrasshopper/ConnectorGrasshopperUtils/UserInterfaceUtils.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Reflection; +using Grasshopper.Kernel; +using Grasshopper.Kernel.Special; + +namespace ConnectorGrasshopperUtils; + +public static class UserInterfaceUtils +{ + /// + /// Used to Create + /// + /// + /// + /// + /// + /// + public static GH_ValueList CreateEnumDropDown(Type enumType, string name, float xPos, float yPos, bool sorted = true) + { + if (!enumType.IsEnum) + { + throw new ArgumentException($"Input type must be {typeof(Enum)} but got {enumType.Name} ", nameof(enumType)); + } + + // Convert all values of an enum into a GH_ValueListItem and add them to the value list. + // This preserves both the name of the Enum value, as well as it's declared integer value (saved as a string). + var items = Enum.GetValues(enumType) + .Cast() + .Select(x => new GH_ValueListItem(name: x.ToString(), expression: Convert.ToInt32(x).ToString())) + .ToList(); + + var valueList = new GH_ValueList(); + valueList.CreateAttributes(); + valueList.Name = name; + valueList.NickName = name + ":"; + valueList.Description = "Select an option..."; + valueList.ListMode = GH_ValueListMode.DropDown; + valueList.Attributes.Pivot = new PointF(xPos, yPos); + + valueList.ListItems.Clear(); + valueList.ListItems.AddRange(items); + + if (sorted) + { + valueList.ListItems.Sort((itemA, itemB) => string.Compare(itemA.Name, itemB.Name)); + } + + return valueList; + } + + /// + /// Creates a dropdown component on the canvas for every type input of the component. + /// This assumes the inputs have already been created, and that there is a 1 to 1 relationship between + /// the number of inputs of the component and the number of properties. + /// + /// The component to connect the dropdowns to + /// The list of the class being created as a component. + public static void CreateCanvasDropdownForAllEnumInputs(IGH_Component component, ParameterInfo[] props) + { + //Expiring solution ensures the size and position of the parent are updated before placing any input connections + component.ExpireSolution(true); + + for (int index = 0; index < props.Length; index++) + { + ParameterInfo p = props[index]; + if (!p.ParameterType.IsEnum) + { + continue; + } + + var options = CreateEnumDropDown( + p.ParameterType, + p.Name, + component.Attributes.Bounds.X - 200, + component.Params.Input[index].Attributes.Bounds.Y - 1 + ); + component.OnPingDocument().AddObject(options, false); + component.Params.Input[index].AddSource(options); + } + } +}