In our table project, all three designs will show up in the UI, so each one will mix in the UIPartMixin. Simply go to the "UI" mixins of each component (TableUI, TableTopUI, and LegUI), and mix in the UIPartMixin as the right most design .
Design TableUI : TableDesigns UIPartMixin Design TableTopUI : TableTopDesigns UIPartMixin Design LegUI : LegDesigns UIPartMixin
At this point, we have done the minimum that is required to use the UI Tools. However, our UIParts will be empty since we have not yet added any UIProperties or UIMessages to them. Also, the UIName value defaults to return the DisplayName from Intent, which is sometimes not exactly what we would want to show in the UI.
Before adding any UIProperty children , we will need to set up the categories that we will want for the UIProperties. For now, we will simply have one category, "General", so we add the following to the TableUI mixin:
Child GeneralCategory As :UICategory CategoryName = "General" CategorySeq = 1 End Child
By default, UICategory and UIProperty based parts will not show up in the Intent model browser tree. This is because there can be quite a few UIProperties on a part , and showing them all in the model browser clutters up the treeview interface. There is a lookup rule that exists on all UICategory, UIProperty, and UIPartMixin designs that will toggle display of the UIProperties and UICategories in the model browser. This rule is ShowPropertiesInBrowser?:
Lookup Parameter Rule ShowPropertiesInBrowser? As Boolean = False
Simply set this rule to True and the UIProperties and UICategories below that UIPart will be displayed.
Each part that mixes in UIPartMixin contains the UIName rule, and this rule is what determines the text to display in the UI for that part . By default, the UIName is set to be the same value as the DisplayName rule ; however often times we will want to override this to provide a more meaningful description of the part . In our example, we will set the UIName on the TableUI design to be "A Simple Table":
<%%category("Ui")> Parameter Rule UIName As String = "A Simple Table"
<%%category("Ui")> Parameter Rule UIName As String = "Table Top"
<%%category("Ui")> _ Parameter Rule UIName As String = "Leg " + format("%d",index)
Now, we will add UIProperty children for the height, length, and width. For the height, we will specify a set of common choices the user can select, but also allow them to provide any value they want.
Rule Height As Number = uiHeight.value Child uiHeight As :NumberProperty BaseName = "Height" CategoryPart = GeneralCategory choiceListValues = {6,12,18,24,36} End Child
Note that we have also overridden the Height rule so that it now looks at the uiHeight.value insead of dvHeight. Also, we don't need to pass in a value to the DefaultValue parameter of uiHeight since we adhered to the "dv" shorthand system for default values as discussed earlier. Lastly, you will note that in this case, we are using a NumberProperty instead of the base UIProperty. This is a specialized UIProperty design that mixes in UIProperty and overrides the Formatter and Converter values, as well as offers some other common validation (min / max values, etc). In general, it is best to use one of the specialized UIProperty based designs instead of the base UIProperty. If the project requires a custom type of UIProperty, then it is generally best to derive a custom UIProperty for that project and use it. The following is the list of specialized UIProperties that come with the UI Tools standard:
It is important to note that each of these specialized UIProperty designs actually mix in the BasicUIProperty design , which in turn mixes in the UIProperty design . It is the BasicUIProperty design which provides the "dv" shorthand method for default values.
The width and length will simply be numbers the user can enter. As with the Height rule , we have overridden the Width and Length rules so that they now reference their respective UI properties.
Rule Width As Number = uiWidth.value Child uiWidth As :NumberProperty BaseName = "Width" CategoryPart = GeneralCategory End Child Rule Length As Number = uiLength.value Child uiLength As :NumberProperty BaseName = "Length" CategoryPart = GeneralCategory End Child
The TableTop part will have UIProperties for the width, length and thickness. However, the width and length values are passed in from the parent Table assembly, so these UIProperties will be tagged as ReadOnly. Also, we will simply reference the "General" UICategory that was added to the Table earlier. So, in the TableTopUI mixin, we add the following:
Rule Width As Number = uiWidth.value Child uiWidth As :NumberProperty BaseName = "Width" CategoryPart = GeneralCategory IsReadOnly? = True End Child Rule Length As Number = uiLength.value Child uiLength As :NumberProperty BaseName = "Length" CategoryPart = GeneralCategory IsReadOnly? = True End Child Rule Thickness As Number = uiThickness.value Child uiThickness As :NumberProperty BaseName = "Thickness" CategoryPart = GeneralCategory End Child
The Leg part will have UIProperties for the width, and height. The leg's height is passed in from the table, so it will be a ReadOnly property, whereas the width will allow the user to edit its value. We will add the following to the LegUI mixin:
Rule Width As Number = uiWidth.value Child uiWidth As :NumberProperty BaseName = "Width" CategoryPart = GeneralCategory End Child Rule Height As Number = uiHeight.value Child uiHeight As :NumberProperty BaseName = "Height" CategoryPart = GeneralCategory IsReadOnly? = True End Child
It is often the case that the developer will want to display messages in the UI based on the current state of the model. This is accomplished by adding UIMessage children to a design which mixes in UIPartMixin. In our simple table project, we will have a warning message on the Table that informs the user that they are using a nonstandard Height if they choose a value for the height that is not in the list of choices. Also, if the value of the Height they have chosen is below our minimum allowed Height, this warning will change to an error message telling the user that they must choose a height above the minimum. This UIMessage child will be added to the TableUI design as the following:
Child HeightMessage As :UIMessage severity = (If Height < MinimumHeight Then :Error Else :Warning) message = (If Height < MinimumHeight Then _ "Below minimum height of " + format("%d",MinimumHeight) _ Else _ "The user has entered a nonstandard table height") End Child