Example #1
0
        static bool IsAttributeIgnored(UxmlAttributeDescription attribute)
        {
#if !UI_BUILDER_PACKAGE || UNITY_2021_1_OR_NEWER
            // Temporary check until we add an "obsolete" mechanism to uxml attribute description.
            return(attribute.name == "show-horizontal-scroller" || attribute.name == "show-vertical-scroller");
#else
            return(false);
#endif
        }
        static bool IsAttributeIgnored(UxmlAttributeDescription attribute)
        {
#if !UNITY_2019_4 && !UNITY_2020_1 && !UNITY_2020_2 && !UNITY_2020_3
            // Temporary check until we add an "obsolete" mechanism to uxml attribute description.
            return(attribute.name == "show-horizontal-scroller" || attribute.name == "show-vertical-scroller");
#else
            return(false);
#endif
        }
        public static void CloseEditor()
        {
            if (s_Viewport == null)
            {
                return;
            }

            s_Viewport.textEditor.Q(TextField.textInputUssName).UnregisterCallback <FocusOutEvent>(OnFocusOutEvent);
            s_Viewport.textEditor.UnregisterCallback <ChangeEvent <string> >(OnTextChanged);
            s_Viewport.editorLayer.AddToClassList(BuilderConstants.HiddenStyleClassName);
            s_EditedTextElement.UnregisterCallback <GeometryChangedEvent>(OnTextElementGeometryChanged);
            s_Viewport            = null;
            s_EditedElement       = null;
            s_EditedTextAttribute = null;
        }
Example #4
0
        BuilderStyleRow CreateAttributeRow(UxmlAttributeDescription attribute)
        {
            var attributeType = attribute.GetType();

            // Generate field label.
            var             fieldLabel = BuilderNameUtilities.ConvertDashToHuman(attribute.name);
            BindableElement fieldElement;

            if (attribute is UxmlStringAttributeDescription)
            {
                // Hard-coded
                if (attribute.name.Equals("value") && currentVisualElement is EnumField enumField)
                {
                    var uiField = new EnumField("Value");
                    if (null != enumField.value)
                    {
                        uiField.Init(enumField.value, enumField.includeObsoleteValues);
                    }
                    else
                    {
                        uiField.SetValueWithoutNotify(null);
                    }
                    uiField.RegisterValueChangedCallback(evt =>
                                                         PostAttributeValueChange(uiField, uiField.value.ToString()));
                    fieldElement = uiField;
                }
                else if (attribute.name.Equals("value") && currentVisualElement is TagField tagField)
                {
                    var uiField = new TagField("Value");
                    uiField.RegisterValueChangedCallback(evt =>
                                                         PostAttributeValueChange(uiField, uiField.value.ToString()));
                    fieldElement = uiField;
                }
                else
                {
                    var uiField = new TextField(fieldLabel);
                    if (attribute.name.Equals("name") || attribute.name.Equals("view-data-key"))
                    {
                        uiField.RegisterValueChangedCallback(e =>
                        {
                            OnValidatedAttributeValueChange(e, BuilderNameUtilities.attributeRegex,
                                                            BuilderConstants.AttributeValidationSpacialCharacters);
                        });
                    }
                    else if (attribute.name.Equals("binding-path"))
                    {
                        uiField.RegisterValueChangedCallback(e =>
                        {
                            OnValidatedAttributeValueChange(e, BuilderNameUtilities.bindingPathAttributeRegex,
                                                            BuilderConstants.BindingPathAttributeValidationSpacialCharacters);
                        });
                    }
                    else
                    {
                        uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                    }

                    if (attribute.name.Equals("text") || attribute.name.Equals("label"))
                    {
                        uiField.multiline = true;
                        uiField.AddToClassList(BuilderConstants.InspectorMultiLineTextFieldClassName);
                    }

                    fieldElement = uiField;
                }
            }
            else if (attribute is UxmlFloatAttributeDescription)
            {
                var uiField = new FloatField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlDoubleAttributeDescription)
            {
                var uiField = new DoubleField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlIntAttributeDescription)
            {
                if (attribute.name.Equals("value") && currentVisualElement is LayerField)
                {
                    var uiField = new LayerField("Value");
                    uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                    fieldElement = uiField;
                }
                else if (attribute.name.Equals("value") && currentVisualElement is LayerMaskField)
                {
                    var uiField = new LayerMaskField("Value");
                    uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                    fieldElement = uiField;
                }
                else
                {
                    var uiField = new IntegerField(fieldLabel);
                    uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                    fieldElement = uiField;
                }
            }
            else if (attribute is UxmlLongAttributeDescription)
            {
                var uiField = new LongField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlBoolAttributeDescription)
            {
                var uiField = new Toggle(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlColorAttributeDescription)
            {
                var uiField = new ColorField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attributeType.IsGenericType &&
                     !attributeType.GetGenericArguments()[0].IsEnum &&
                     attributeType.GetGenericArguments()[0] is Type)
            {
                var desiredType = attributeType.GetGenericArguments()[0];

                var uiField = new TextField(fieldLabel)
                {
                    isDelayed = true
                };

                var completer = new FieldSearchCompleter <TypeInfo>(uiField);
                uiField.RegisterCallback <AttachToPanelEvent, FieldSearchCompleter <TypeInfo> >((evt, c) =>
                {
                    // When possible, the popup should have the same width as the input field, so that the auto-complete
                    // characters will try to match said input field.
                    c.popup.anchoredControl = ((VisualElement)evt.target).Q(className: "unity-text-field__input");
                }, completer);
                completer.matcherCallback    += (str, info) => info.value.IndexOf(str, StringComparison.OrdinalIgnoreCase) >= 0;
                completer.itemHeight          = 36;
                completer.dataSourceCallback += () =>
                {
                    return(TypeCache.GetTypesDerivedFrom(desiredType)
                           .Where(t => !t.IsGenericType)
                           // Remove UIBuilder types from the list
                           .Where(t => t.Assembly != GetType().Assembly)
                           .Select(GetTypeInfo));
                };
                completer.getTextFromDataCallback += info => info.value;
                completer.makeItem    = () => s_TypeNameItemPool.Get();
                completer.destroyItem = e =>
                {
                    if (e is BuilderAttributeTypeName typeItem)
                    {
                        s_TypeNameItemPool.Release(typeItem);
                    }
                };
                completer.bindItem = (v, i) =>
                {
                    if (v is BuilderAttributeTypeName l)
                    {
                        l.SetType(completer.results[i].type, completer.textField.text);
                    }
                };

                uiField.RegisterValueChangedCallback(e => OnValidatedTypeAttributeChange(e, desiredType));

                fieldElement = uiField;
                uiField.RegisterCallback <DetachFromPanelEvent, FieldSearchCompleter <TypeInfo> >((evt, c) =>
                {
                    c.popup.RemoveFromHierarchy();
                }, completer);
                uiField.userData = completer;
            }
            else if (attributeType.IsGenericType && attributeType.GetGenericArguments()[0].IsEnum)
            {
                var propInfo         = attributeType.GetProperty("defaultValue");
                var defaultEnumValue = propInfo.GetValue(attribute, null) as Enum;

                if (defaultEnumValue.GetType().GetCustomAttribute <FlagsAttribute>() == null)
                {
                    // Create and initialize the EnumField.
                    var uiField = new EnumField(fieldLabel);
                    uiField.Init(defaultEnumValue);

                    uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                    fieldElement = uiField;
                }
                else
                {
                    // Create and initialize the EnumField.
                    var uiField = new EnumFlagsField(fieldLabel);
                    uiField.Init(defaultEnumValue);

                    uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                    fieldElement = uiField;
                }
            }
            else
            {
                var uiField = new TextField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }

            // Create row.
            var styleRow = new BuilderStyleRow();

            styleRow.Add(fieldElement);

            // Link the field.
            fieldElement.SetProperty(BuilderConstants.InspectorLinkedStyleRowVEPropertyName, styleRow);
            fieldElement.SetProperty(BuilderConstants.InspectorLinkedAttributeDescriptionVEPropertyName, attribute);

            // Set initial value.
            RefreshAttributeField(fieldElement);

            // Setup field binding path.
            fieldElement.bindingPath = attribute.name;
            fieldElement.tooltip     = attribute.name;

            // Context menu.
            fieldElement.AddManipulator(new ContextualMenuManipulator(BuildAttributeFieldContextualMenu));

            return(styleRow);
        }
Example #5
0
 static bool IsAttributeIgnored(UxmlAttributeDescription attribute)
 {
     // Temporary check until we add an "obsolete" mechanism to uxml attribute description.
     return(attribute.name == "show-horizontal-scroller" || attribute.name == "show-vertical-scroller");
 }
        BuilderStyleRow CreateAttributeRow(UxmlAttributeDescription attribute)
        {
            var attributeType = attribute.GetType();

            // Generate field label.
            var             fieldLabel = BuilderNameUtilities.ConvertDashToHuman(attribute.name);
            BindableElement fieldElement;

            if (attribute is UxmlStringAttributeDescription)
            {
                var uiField = new TextField(fieldLabel);
                if (attribute.name.Equals("name") || attribute.name.Equals("view-data-key"))
                {
                    uiField.RegisterValueChangedCallback(e =>
                    {
                        OnValidatedAttributeValueChange(e, BuilderNameUtilities.AttributeRegex, BuilderConstants.AttributeValidationSpacialCharacters);
                    });
                }
                else if (attribute.name.Equals("binding-path"))
                {
                    uiField.RegisterValueChangedCallback(e =>
                    {
                        OnValidatedAttributeValueChange(e, BuilderNameUtilities.BindingPathAttributeRegex, BuilderConstants.BindingPathAttributeValidationSpacialCharacters);
                    });
                }
                else
                {
                    uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                }

                if (attribute.name.Equals("text"))
                {
                    uiField.multiline = true;
                    uiField.AddToClassList(BuilderConstants.InspectorMultiLineTextFieldClassName);
                }

                fieldElement = uiField;
            }
            else if (attribute is UxmlFloatAttributeDescription)
            {
                var uiField = new FloatField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlDoubleAttributeDescription)
            {
                var uiField = new DoubleField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlIntAttributeDescription)
            {
                var uiField = new IntegerField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlLongAttributeDescription)
            {
                var uiField = new LongField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlBoolAttributeDescription)
            {
                var uiField = new Toggle(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlColorAttributeDescription)
            {
                var uiField = new ColorField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attributeType.IsGenericType &&
                     !attributeType.GetGenericArguments()[0].IsEnum &&
                     attributeType.GetGenericArguments()[0] is Type)
            {
                var uiField = new TextField(fieldLabel);
                uiField.isDelayed = true;
                uiField.RegisterValueChangedCallback(e =>
                {
                    OnValidatedTypeAttributeChange(e, attributeType.GetGenericArguments()[0]);
                });
                fieldElement = uiField;
            }
            else if (attributeType.IsGenericType && attributeType.GetGenericArguments()[0].IsEnum)
            {
                var propInfo  = attributeType.GetProperty("defaultValue");
                var enumValue = propInfo.GetValue(attribute, null) as Enum;

                // Create and initialize the EnumField.
                var uiField = new EnumField(fieldLabel);
                uiField.Init(enumValue);

                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else
            {
                var uiField = new TextField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }

            // Create row.
            var styleRow = new BuilderStyleRow();

            styleRow.Add(fieldElement);

            // Link the field.
            fieldElement.SetProperty(BuilderConstants.InspectorLinkedStyleRowVEPropertyName, styleRow);
            fieldElement.SetProperty(BuilderConstants.InspectorLinkedAttributeDescriptionVEPropertyName, attribute);

            // Set initial value.
            RefreshAttributeField(fieldElement);

            // Setup field binding path.
            fieldElement.bindingPath = attribute.name;

            // Tooltip.
            var label = fieldElement.Q <Label>();

            if (label != null)
            {
                label.tooltip = attribute.name;
            }
            else
            {
                fieldElement.tooltip = attribute.name;
            }

            // Context menu.
            fieldElement.AddManipulator(new ContextualMenuManipulator(BuildAttributeFieldContextualMenu));

            return(styleRow);
        }
        public static void OpenEditor(VisualElement element, Vector2 pos)
        {
            BuilderViewport viewport    = element.GetFirstAncestorOfType <BuilderViewport>();
            var             editorLayer = viewport.editorLayer;
            var             textEditor  = viewport.textEditor;

            GetAttributeToEdit(element, pos, out var textElement, out var attributeName);

            if (textElement == null || string.IsNullOrEmpty(attributeName))
            {
                return;
            }

            var attributeList = element.GetAttributeDescriptions();

            foreach (var attribute in attributeList)
            {
                if (attribute?.name != null && attribute.name.Equals(attributeName))
                {
                    s_EditedTextAttribute = attribute;
                    break;
                }
            }

            if (s_EditedTextAttribute == null)
            {
                return;
            }

            s_Viewport          = viewport;
            s_EditedElement     = element;
            s_EditedTextElement = textElement;

            var value = s_EditedElement.GetValueByReflection(s_EditedTextAttribute.name) as string;

            // To ensure the text element is visible
            if (string.IsNullOrEmpty(value))
            {
                s_EditedElement.SetValueByReflection(s_EditedTextAttribute.name, s_DummyText);
            }

            editorLayer.RemoveFromClassList(BuilderConstants.HiddenStyleClassName);

            var textInput = textEditor.Q(TextField.textInputUssName);

            textEditor.value = value;
            textInput.style.unityTextAlign          = textElement.resolvedStyle.unityTextAlign;
            textInput.style.fontSize                = textElement.resolvedStyle.fontSize;
            textInput.style.unityFontStyleAndWeight = textElement.resolvedStyle.unityFontStyleAndWeight;

            textEditor.multiline = value != null && value.Contains("\n");

            GetAlignmentFromTextAnchor(textElement.resolvedStyle.unityTextAlign, out var alignItems, out var justifyContent);

            var textEditorContainer = textEditor.parent;

            textEditorContainer.style.paddingLeft    = s_EditedTextElement.resolvedStyle.paddingLeft;
            textEditorContainer.style.paddingTop     = s_EditedTextElement.resolvedStyle.paddingTop;
            textEditorContainer.style.paddingRight   = s_EditedTextElement.resolvedStyle.paddingRight;
            textEditorContainer.style.paddingBottom  = s_EditedTextElement.resolvedStyle.paddingBottom;
            textEditorContainer.style.alignItems     = alignItems;
            textEditorContainer.style.justifyContent = justifyContent;
            UpdateTextEditorGeometry();
            textElement.RegisterCallback <GeometryChangedEvent>(OnTextElementGeometryChanged);

            textEditor.schedule.Execute(a => textInput.Focus());
            textEditor.SelectAll();

            textInput.RegisterCallback <FocusOutEvent>(OnFocusOutEvent);
            textEditor.RegisterCallback <ChangeEvent <string> >(OnTextChanged);
        }
        static void AddAttributeToXmlSchema(XmlSchemaComplexContentRestriction restriction, UxmlAttributeDescription description, XmlQualifiedName typeName)
        {
            XmlSchemaAttribute attr = new XmlSchemaAttribute();

            attr.Name           = description.name;
            attr.SchemaTypeName = typeName;

            switch (description.use)
            {
            case UxmlAttributeDescription.Use.Optional:
                attr.Use          = XmlSchemaUse.Optional;
                attr.DefaultValue = description.defaultValueAsString;
                break;

            case UxmlAttributeDescription.Use.Prohibited:
                attr.Use = XmlSchemaUse.Prohibited;
                break;

            case UxmlAttributeDescription.Use.Required:
                attr.Use = XmlSchemaUse.Required;
                break;

            default:
                attr.Use = XmlSchemaUse.None;
                break;
            }

            restriction.Attributes.Add(attr);
        }
        static XmlQualifiedName AddAttributeTypeToXmlSchema(SchemaInfo schemaInfo, UxmlAttributeDescription description, IUxmlFactory factory, FactoryProcessingHelper processingData)
        {
            if (description.name == null)
            {
                return(null);
            }

            string attrTypeName = factory.uxmlQualifiedName + "_" + description.name + "_" + k_TypeSuffix;
            string attrTypeNameInBaseElement = factory.substituteForTypeQualifiedName + "_" + description.name + "_" + k_TypeSuffix;

            FactoryProcessingHelper.AttributeRecord attrRecord;
            if (processingData.attributeTypeNames.TryGetValue(attrTypeNameInBaseElement, out attrRecord))
            {
                // If restriction != baseElement.restriction, we need to declare a new type.
                // Note: we do not support attributes having a less restrictive restriction than its base type.
                if ((description.restriction == null && attrRecord.desc.restriction == null) ||
                    (description.restriction != null && description.restriction.Equals(attrRecord.desc.restriction)))
                {
                    // Register attrTypeName -> attrRecord for potential future derived elements.
                    processingData.attributeTypeNames.Add(attrTypeName, attrRecord);
                    return(attrRecord.name);
                }
            }

            XmlQualifiedName xqn;

            FactoryProcessingHelper.AttributeRecord attributeRecord;

            if (description.restriction == null)
            {
                // Type is a built-in type.
                xqn             = new XmlQualifiedName(description.type, description.typeNamespace);
                attributeRecord = new FactoryProcessingHelper.AttributeRecord {
                    name = xqn, desc = description
                };
                processingData.attributeTypeNames.Add(attrTypeName, attributeRecord);
                return(xqn);
            }

            string attrTypeNameForSchema = factory.uxmlName + "_" + description.name + "_" + k_TypeSuffix;

            xqn = new XmlQualifiedName(attrTypeNameForSchema, schemaInfo.schema.TargetNamespace);

            XmlSchemaSimpleType simpleType = new XmlSchemaSimpleType();

            simpleType.Name = attrTypeNameForSchema;

            UxmlEnumeration enumRestriction = description.restriction as UxmlEnumeration;

            if (enumRestriction != null)
            {
                XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction();
                simpleType.Content       = restriction;
                restriction.BaseTypeName = new XmlQualifiedName(description.type, description.typeNamespace);

                foreach (var v in enumRestriction.values)
                {
                    XmlSchemaEnumerationFacet enumValue = new XmlSchemaEnumerationFacet();
                    enumValue.Value = v;
                    restriction.Facets.Add(enumValue);
                }
            }
            else
            {
                UxmlValueMatches regexRestriction = description.restriction as UxmlValueMatches;
                if (regexRestriction != null)
                {
                    XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction();
                    simpleType.Content       = restriction;
                    restriction.BaseTypeName = new XmlQualifiedName(description.type, description.typeNamespace);

                    XmlSchemaPatternFacet pattern = new XmlSchemaPatternFacet();
                    pattern.Value = regexRestriction.regex;
                    restriction.Facets.Add(pattern);
                }
                else
                {
                    UxmlValueBounds bounds = description.restriction as UxmlValueBounds;
                    if (bounds != null)
                    {
                        XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction();
                        simpleType.Content       = restriction;
                        restriction.BaseTypeName = new XmlQualifiedName(description.type, description.typeNamespace);

                        XmlSchemaFacet facet;
                        if (bounds.excludeMin)
                        {
                            facet = new XmlSchemaMinExclusiveFacet();
                        }
                        else
                        {
                            facet = new XmlSchemaMinInclusiveFacet();
                        }
                        facet.Value = bounds.min;
                        restriction.Facets.Add(facet);

                        if (bounds.excludeMax)
                        {
                            facet = new XmlSchemaMaxExclusiveFacet();
                        }
                        else
                        {
                            facet = new XmlSchemaMaxInclusiveFacet();
                        }
                        facet.Value = bounds.max;
                        restriction.Facets.Add(facet);
                    }
                    else
                    {
                        Debug.Log("Unsupported restriction type.");
                    }
                }
            }

            schemaInfo.schema.Items.Add(simpleType);
            attributeRecord = new FactoryProcessingHelper.AttributeRecord {
                name = xqn, desc = description
            };
            processingData.attributeTypeNames.Add(attrTypeName, attributeRecord);
            return(xqn);
        }
Example #10
0
        BuilderStyleRow CreateAttributeRow(UxmlAttributeDescription attribute)
        {
            var attributeType = attribute.GetType();
            var vea           = currentVisualElement.GetVisualElementAsset();

            // Generate field label.
            var fieldLabel = BuilderNameUtilities.ConvertDashToHuman(attribute.name);

            BindableElement fieldElement = null;

            if (attribute is UxmlStringAttributeDescription)
            {
                var uiField = new TextField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlFloatAttributeDescription)
            {
                var uiField = new FloatField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlDoubleAttributeDescription)
            {
                var uiField = new DoubleField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlIntAttributeDescription)
            {
                var uiField = new IntegerField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlLongAttributeDescription)
            {
                var uiField = new LongField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlBoolAttributeDescription)
            {
                var uiField = new Toggle(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attribute is UxmlColorAttributeDescription)
            {
                var uiField = new ColorField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else if (attributeType.IsGenericType && attributeType.GetGenericArguments()[0].IsEnum)
            {
                var propInfo  = attributeType.GetProperty("defaultValue");
                var enumValue = propInfo.GetValue(attribute, null) as Enum;

                // Create and initialize the EnumField.
                var uiField = new EnumField(fieldLabel);
                uiField.Init(enumValue);

                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }
            else
            {
                var uiField = new TextField(fieldLabel);
                uiField.RegisterValueChangedCallback(OnAttributeValueChange);
                fieldElement = uiField;
            }

            // Create row.
            var styleRow = new BuilderStyleRow();

            styleRow.Add(fieldElement);

            // Link the field.
            fieldElement.SetProperty(BuilderConstants.InspectorLinkedStyleRowVEPropertyName, styleRow);
            fieldElement.SetProperty(BuilderConstants.InspectorLinkedAttributeDescriptionVEPropertyName, attribute);

            // Set initial value.
            RefreshAttributeField(fieldElement);

            // Setup field binding path.
            fieldElement.bindingPath = attribute.name;

            // Tooltip.
            var label = fieldElement.Q <Label>();

            if (label != null)
            {
                label.tooltip = attribute.name;
            }
            else
            {
                fieldElement.tooltip = attribute.name;
            }

            // Context menu.
            fieldElement.AddManipulator(new ContextualMenuManipulator(BuildAttributeFieldContextualMenu));

            return(styleRow);
        }