JimYuan's Blog

Sharing the things I learned

0%

CustomUI_for_GH_component

Preface

Happy new year, it’s 2022 now. It’s been a while since the last time I updated my blog. Though I didn’t write something in a quite long period of time, I still check some interesting fellows’ work. There’s an open source project from Arup was released on github, so I decided to give it a look.

Reference

https://github.com/arup-group/Custom-Grasshopper-UI-Components

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
using Grasshopper.Kernel;
using Rhino.Geometry;
using System;
using System.Collections.Generic;

// In order to load the result of this wizard, you will also need to
// add the output bin/ folder of this project to the list of loaded
// folder in Grasshopper.
// You can use the _GrasshopperDeveloperSettings Rhino command for that.

namespace CustomGhComponents
{
public class ComponentWithDropDown : GH_Component
{
/// <summary>
/// Each implementation of GH_Component must provide a public
/// constructor without any arguments.
/// Category represents the Tab in which the component will appear,
/// Subcategory the panel. If you use non-existing tab or panel names,
/// new tabs/panels will automatically be created.
/// </summary>
public ComponentWithDropDown()
: base("DropDownComponent", "DropDown",
"A component with dropdown menus",
"Category", "Subcategory")
{
}

//This region overrides the typical component layout
public override void CreateAttributes()
{
if (first)
{
FunctionToSetSelectedContent(0, 0);
first = false;
}
m_attributes = new CustomUI.DropDownUIAttributes(this, FunctionToSetSelectedContent, dropdowncontents, selections, spacerDescriptionText);
}

public void FunctionToSetSelectedContent(int dropdownListId, int selectedItemId)
{
// on first run we create the combined dropdown content
if (dropdowncontents == null)
{
// create list to populate dropdown content with
dropdowncontents = new List<List<string>>(); //clear all previous content
selections = new List<string>();

dropdowncontents.Add(dropdownTopLevelContent); //add Top Level content as first list
selections.Add(dropdownTopLevelContent[0]);

dropdowncontents.Add(dropdownLevel2_A_Content); //add level 2 first list as default on first run
selections.Add(dropdownLevel2_A_Content[0]);

// add the lists corrosponding to top level content order
dropdownLevel2_Content.Add(dropdownLevel2_A_Content);
dropdownLevel2_Content.Add(dropdownLevel2_B_Content);
dropdownLevel2_Content.Add(dropdownLevel2_C_Content);
dropdownLevel2_Content.Add(dropdownLevel2_D_Content);
}

if (dropdownListId == 0) // if change is made to first list
{
// change the content of level 2 based on selection
dropdowncontents[1] = dropdownLevel2_Content[selectedItemId];

// update the shown selected to first item in list
selections[1] = dropdowncontents[1][0];
}

if (dropdownListId == 1) // if change is made to second list
{
selections[1] = dropdowncontents[1][selectedItemId];

// do something with the selected item
System.Windows.Forms.MessageBox.Show("You selected: " + dropdowncontents[1][selectedItemId]);
}

// for Grasshopper to redraw the component to get changes to dropdown menu displayed on canvas:
Params.OnParametersChanged();
ExpireSolution(true);
}

#region dropdownmenu content
// this region is where (static) lists are created that will be displayed
// in the dropdown menus dependent on user selection.

List<List<string>> dropdowncontents; // list that holds all dropdown contents
List<List<string>> dropdownLevel2_Content = new List<List<string>>(); // list to hold level2 content

List<string> selections; // list of the selected items
bool first = true; // bool to create menu first time the component runs

readonly List<string> spacerDescriptionText = new List<string>(new string[]
{
"TopLevel List",
"Level2 Items"
});
readonly List<string> dropdownTopLevelContent = new List<string>(new string[]
{
"ListA",
"ListB",
"ListC",
"ListD"
});
// lists longer than 10 will automatically get a vertical scroll bar
readonly List<string> dropdownLevel2_A_Content = new List<string>(new string[]
{
"Item A1",
"Item A2",
"Item A3",
"Item A4",
"Item A5",
"Item A6",
"Item A7",
"Item A8",
"Item A9",
"Item A10",
"Item A11",
"Item A12",
"Item A13",
});

readonly List<string> dropdownLevel2_B_Content = new List<string>(new string[]
{
"Item B1",
"Item B2",
"Item B3",
"Item B4",
"Item B5",
"Item B6",
"Item B7",
"Item B8",
"Item B9",
});

readonly List<string> dropdownLevel2_C_Content = new List<string>(new string[]
{
"Item C1",
"Item C2",
"Item C3",
"Item C4",
"Item C5",
"Item C6",
"Item C7",
"Item C8",
"Item C9",
"Item C10",
"Item C11",
"Item C12",
"Item C13",
"Item C14",
"Item C15",
"Item C16",
});

readonly List<string> dropdownLevel2_D_Content = new List<string>(new string[]
{
"Item D1",
"Item D2",
"Item D3",
"Item D4",
"Item D5",
"Item D6",
});
#endregion

/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.AddGenericParameter("Input1", "I1", "First Input", GH_ParamAccess.item);
pManager[0].Optional = true;
}

/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("Output1", "O1", "First Output", GH_ParamAccess.item);
}

/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="DA">The DA object can be used to retrieve data from input parameters and
/// to store data in output parameters.</param>
protected override void SolveInstance(IGH_DataAccess DA)
{
// set output to selected
DA.SetData(0, selections[1]);
}

/// <summary>
/// Provides an Icon for every component that will be visible in the User Interface.
/// Icons need to be 24x24 pixels.
/// </summary>
protected override System.Drawing.Bitmap Icon
{
get
{
// You can add image files to your project resources and access them like this:
//return Resources.IconForThisComponent;
return null;
}
}

/// <summary>
/// Each component must have a unique Guid to identify it.
/// It is vital this Guid doesn't change otherwise old ghx files
/// that use the old ID will partially fail during loading.
/// </summary>
public override Guid ComponentGuid
{
get { return new Guid("020959db-8b03-4a62-9a25-5b34e4e44812"); }
}
}
}

Skills

THIS PAGE IS NOT YET FINISHED