// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using System.Linq; using FlaxEditor.CustomEditors.Editors; using FlaxEditor.GUI; using FlaxEditor.GUI.Input; using FlaxEditor.Scripting; using FlaxEngine; using FlaxEngine.GUI; namespace FlaxEditor.Surface.Elements { /// /// The handler for the input box default value editing. Used to display the default to the UI. /// [HideInEditor] public interface IDefaultValueEditor { /// /// Checks if the handles supports the given type. /// /// The input box that uses this editor. /// The type to check. /// True if can create UI for this type editing, otherwise false. bool CanUse(InputBox box, ref ScriptType type); /// /// Creates the UI for the value editing. /// /// The input box that uses this editor. /// The control bounds (control can be smaller but cannot be bigger). /// The root control of the created UI Control Create(InputBox box, ref Rectangle bounds); /// /// Returns true if given control is valid root editor for the value. /// /// The input box that uses this editor. /// The root control of the editor UI. /// true if the specified control is valid; otherwise, false. bool IsValid(InputBox box, Control control); /// /// Updates the default value editor UI value. /// /// The input box that uses this editor. /// The root control of the editor UI. void UpdateDefaultValue(InputBox box, Control control); /// /// Updates the UI after box attributes change. /// /// The input box that uses this editor. /// The custom attributes collection. /// The root control of the editor UI. void UpdateAttributes(InputBox box, object[] attributes, Control control); } class BooleanDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(bool); } public Control Create(InputBox box, ref Rectangle bounds) { var value = BoolValue.Get(box.ParentNode, box.Archetype); var control = new CheckBox(bounds.X, bounds.Y, value, bounds.Height) { Parent = box.Parent, Tag = box, }; control.StateChanged += OnCheckboxStateChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is CheckBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is CheckBox checkBox) { checkBox.Checked = BoolValue.Get(box.ParentNode, box.Archetype); } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private void OnCheckboxStateChanged(CheckBox control) { var box = (InputBox)control.Tag; box.ParentNode.SetValue(box.Archetype.ValueIndex, control.Checked); } } class IntegerDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(int); } public Control Create(InputBox box, ref Rectangle bounds) { var value = IntegerValue.Get(box.ParentNode, box.Archetype); var control = new IntValueBox(value, bounds.X, bounds.Y, 40, int.MinValue, int.MaxValue, 0.01f) { Height = bounds.Height, Parent = box.Parent, Tag = box, }; control.BoxValueChanged += OnIntValueBoxChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is IntValueBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is IntValueBox intValue) { intValue.Value = IntegerValue.Get(box.ParentNode, box.Archetype); } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private void OnIntValueBoxChanged(ValueBox control) { var box = (InputBox)control.Tag; IntegerValue.Set(box.ParentNode, box.Archetype, control.Value); } } class UnsignedIntegerDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(uint); } public Control Create(InputBox box, ref Rectangle bounds) { var value = UnsignedIntegerValue.Get(box.ParentNode, box.Archetype); var control = new UIntValueBox(value, bounds.X, bounds.Y, 40, uint.MinValue, uint.MaxValue, 0.01f) { Height = bounds.Height, Parent = box.Parent, Tag = box, }; control.BoxValueChanged += OnValueBoxChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is UIntValueBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is UIntValueBox intValue) { intValue.Value = UnsignedIntegerValue.Get(box.ParentNode, box.Archetype); } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private void OnValueBoxChanged(ValueBox control) { var box = (InputBox)control.Tag; UnsignedIntegerValue.Set(box.ParentNode, box.Archetype, control.Value); } } class FloatingDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(float) || type.Type == typeof(double); } public Control Create(InputBox box, ref Rectangle bounds) { var value = FloatValue.Get(box.ParentNode, box.Archetype); var control = new FloatValueBox(value, bounds.X, bounds.Y, 40, float.MinValue, float.MaxValue, 0.01f) { Height = bounds.Height, Parent = box.Parent, Tag = box, }; control.BoxValueChanged += OnFloatValueBoxChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is FloatValueBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is FloatValueBox floatValue) { floatValue.Value = FloatValue.Get(box.ParentNode, box.Archetype); } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private void OnFloatValueBoxChanged(ValueBox control) { var box = (InputBox)control.Tag; FloatValue.Set(box.ParentNode, box.Archetype, control.Value); } } class StringDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(string) && (box.Attributes == null || box.Attributes.All(x => x.GetType() != typeof(TypeReferenceAttribute))); } public Control Create(InputBox box, ref Rectangle bounds) { var value = box.ParentNode.Values[box.Archetype.ValueIndex] as string; var control = new TextBox(false, bounds.X, bounds.Y, 40) { Text = value, Height = bounds.Height, Parent = box.Parent, Tag = box, }; control.TextBoxEditEnd += OnTextBoxTextChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is TextBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is TextBox textBox) { textBox.Text = box.ParentNode.Values[box.Archetype.ValueIndex] as string; } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private void OnTextBoxTextChanged(TextBoxBase control) { var box = (InputBox)control.Tag; box.ParentNode.SetValue(box.Archetype.ValueIndex, control.Text); } } class Vector2DefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(Vector2); } public Control Create(InputBox box, ref Rectangle bounds) { var value = GetValue(box); var control = new ContainerControl(bounds.X, bounds.Y, 22 * 2 - 2, bounds.Height) { ClipChildren = false, AutoFocus = false, Parent = box.Parent, Tag = box, }; var floatX = new FloatValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatX.BoxValueChanged += OnVector2ValueChanged; var floatY = new FloatValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatY.BoxValueChanged += OnVector2ValueChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is ContainerControl vec2 && vec2.ChildrenCount == 2 && vec2.Children[0] is FloatValueBox && vec2.Children[1] is FloatValueBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is ContainerControl vec2 && vec2.Tag as Type == typeof(Vector2) && vec2.ChildrenCount == 2 && vec2.Children[0] is FloatValueBox x && vec2.Children[1] is FloatValueBox y) { var value = GetValue(box); x.Value = value.X; y.Value = value.Y; } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private Vector2 GetValue(InputBox box) { var value = Vector2.Zero; var v = box.ParentNode.Values[box.Archetype.ValueIndex]; if (v is Vector2 vec2) value = vec2; else if (v is Vector3 vec3) value = new Vector2(vec3); else if (v is Vector4 vec4) value = new Vector2(vec4); else if (v is Color col) value = new Vector2(col.R, col.G); else if (v is float f) value = new Vector2(f); else if (v is int i) value = new Vector2(i); return value; } private void OnVector2ValueChanged(ValueBox valueBox) { var control = valueBox.Parent; var box = (InputBox)control.Tag; var x = ((FloatValueBox)control.Children[0]).Value; var y = ((FloatValueBox)control.Children[1]).Value; box.ParentNode.SetValue(box.Archetype.ValueIndex, new Vector2(x, y)); } } class Vector3DefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(Vector3); } public Control Create(InputBox box, ref Rectangle bounds) { var value = GetValue(box); var control = new ContainerControl(bounds.X, bounds.Y, 22 * 3 - 2, bounds.Height) { ClipChildren = false, AutoFocus = false, Parent = box.Parent, Tag = box, }; var floatX = new FloatValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatX.BoxValueChanged += OnVector3ValueChanged; var floatY = new FloatValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatY.BoxValueChanged += OnVector3ValueChanged; var floatZ = new FloatValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatZ.BoxValueChanged += OnVector3ValueChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is ContainerControl vec3 && vec3.ChildrenCount == 3 && vec3.Children[0] is FloatValueBox && vec3.Children[1] is FloatValueBox && vec3.Children[2] is FloatValueBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is ContainerControl vec3 && vec3.ChildrenCount == 3 && vec3.Children[0] is FloatValueBox x && vec3.Children[1] is FloatValueBox y && vec3.Children[2] is FloatValueBox z) { var value = GetValue(box); x.Value = value.X; y.Value = value.Y; z.Value = value.Z; } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private Vector3 GetValue(InputBox box) { var value = Vector3.Zero; var v = box.ParentNode.Values[box.Archetype.ValueIndex]; if (v is Vector2 vec2) value = new Vector3(vec2, 0.0f); else if (v is Vector3 vec3) value = vec3; else if (v is Vector4 vec4) value = new Vector3(vec4); else if (v is Color col) value = col; else if (v is float f) value = new Vector3(f); else if (v is int i) value = new Vector3(i); return value; } private void OnVector3ValueChanged(ValueBox valueBox) { var control = valueBox.Parent; var box = (InputBox)control.Tag; var x = ((FloatValueBox)control.Children[0]).Value; var y = ((FloatValueBox)control.Children[1]).Value; var z = ((FloatValueBox)control.Children[2]).Value; box.ParentNode.SetValue(box.Archetype.ValueIndex, new Vector3(x, y, z)); } } class Vector4DefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(Vector4); } public Control Create(InputBox box, ref Rectangle bounds) { var value = GetValue(box); var control = new ContainerControl(bounds.X, bounds.Y, 22 * 4 - 2, bounds.Height) { ClipChildren = false, AutoFocus = false, Parent = box.Parent, Tag = box, }; var floatX = new FloatValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatX.BoxValueChanged += OnVector4ValueChanged; var floatY = new FloatValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatY.BoxValueChanged += OnVector4ValueChanged; var floatZ = new FloatValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatZ.BoxValueChanged += OnVector4ValueChanged; var floatW = new FloatValueBox(value.W, 66, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatW.BoxValueChanged += OnVector4ValueChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is ContainerControl vec4 && vec4.ChildrenCount == 4 && vec4.Children[0] is FloatValueBox && vec4.Children[1] is FloatValueBox && vec4.Children[2] is FloatValueBox && vec4.Children[3] is FloatValueBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is ContainerControl vec4 && vec4.ChildrenCount == 4 && vec4.Children[0] is FloatValueBox x && vec4.Children[1] is FloatValueBox y && vec4.Children[2] is FloatValueBox z && vec4.Children[3] is FloatValueBox w) { var value = GetValue(box); x.Value = value.X; y.Value = value.Y; z.Value = value.Z; w.Value = value.W; } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private Vector4 GetValue(InputBox box) { var value = Vector4.Zero; var v = box.ParentNode.Values[box.Archetype.ValueIndex]; if (v is Vector2 vec2) value = new Vector4(vec2, 0.0f, 0.0f); else if (v is Vector3 vec3) value = new Vector4(vec3, 0.0f); else if (v is Vector4 vec4) value = vec4; else if (v is Color col) value = col; else if (v is float f) value = new Vector4(f); else if (v is int i) value = new Vector4(i); return value; } private void OnVector4ValueChanged(ValueBox valueBox) { var control = valueBox.Parent; var box = (InputBox)control.Tag; var x = ((FloatValueBox)control.Children[0]).Value; var y = ((FloatValueBox)control.Children[1]).Value; var z = ((FloatValueBox)control.Children[2]).Value; var w = ((FloatValueBox)control.Children[3]).Value; box.ParentNode.SetValue(box.Archetype.ValueIndex, new Vector4(x, y, z, w)); } } class QuaternionDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(Quaternion); } public Control Create(InputBox box, ref Rectangle bounds) { var value = GetValue(box).EulerAngles; var control = new ContainerControl(bounds.X, bounds.Y, 22 * 3 - 2, bounds.Height) { ClipChildren = false, AutoFocus = false, Parent = box.Parent, Tag = box, }; var floatX = new FloatValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatX.BoxValueChanged += OnQuaternionValueChanged; var floatY = new FloatValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatY.BoxValueChanged += OnQuaternionValueChanged; var floatZ = new FloatValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f) { Height = bounds.Height, Parent = control, }; floatZ.BoxValueChanged += OnQuaternionValueChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is ContainerControl vec3 && vec3.ChildrenCount == 3 && vec3.Children[0] is FloatValueBox && vec3.Children[1] is FloatValueBox && vec3.Children[2] is FloatValueBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is ContainerControl quat && quat.ChildrenCount == 3 && quat.Children[0] is FloatValueBox x && quat.Children[1] is FloatValueBox y && quat.Children[2] is FloatValueBox z) { var value = GetValue(box).EulerAngles; x.Value = value.X; y.Value = value.Y; z.Value = value.Z; } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private Quaternion GetValue(InputBox box) { var value = Quaternion.Identity; var v = box.ParentNode.Values[box.Archetype.ValueIndex]; if (v is Quaternion quat) value = quat; else if (v is Transform transform) value = transform.Orientation; return value; } private void OnQuaternionValueChanged(ValueBox valueBox) { var control = valueBox.Parent; var box = (InputBox)control.Tag; var x = ((FloatValueBox)control.Children[0]).Value; var y = ((FloatValueBox)control.Children[1]).Value; var z = ((FloatValueBox)control.Children[2]).Value; box.ParentNode.SetValue(box.Archetype.ValueIndex, Quaternion.Euler(x, y, z)); } } class ColorDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.Type == typeof(Color); } public Control Create(InputBox box, ref Rectangle bounds) { var value = GetValue(box); var control = new ColorValueBox(value, bounds.X, bounds.Y) { Height = bounds.Height, Parent = box.Parent, Tag = box, }; control.ColorValueChanged += OnColorValueChanged; return control; } public bool IsValid(InputBox box, Control control) { return control is ColorValueBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is ColorValueBox colorValueBox) { colorValueBox.Value = GetValue(box); } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private Vector4 GetValue(InputBox box) { var value = Color.Black; var v = box.ParentNode.Values[box.Archetype.ValueIndex]; if (v is Vector2 vec2) value = new Color(vec2.X, vec2.Y, 0.0f, 1.0f); else if (v is Vector3 vec3) value = new Color(vec3.X, vec3.Y, vec3.Z, 1.0f); else if (v is Vector4 vec4) value = new Color(vec4.X, vec4.Y, vec4.Z, vec4.W); else if (v is Color col) value = col; else if (v is float f) value = new Color(f); else if (v is int i) value = new Color(i); return value; } private void OnColorValueChanged(ColorValueBox control) { var box = (InputBox)control.Tag; box.ParentNode.SetValue(box.Archetype.ValueIndex, control.Value); } } class EnumDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { return type.IsEnum; } public Control Create(InputBox box, ref Rectangle bounds) { var value = GetValue(box); var control = new EnumComboBox(box.CurrentType.Type) { Location = new Vector2(bounds.X, bounds.Y), Size = new Vector2(60.0f, bounds.Height), EnumTypeValue = value ?? box.CurrentType.CreateInstance(), Parent = box.Parent, Tag = box, }; control.EnumValueChanged += OnEnumValueChanged; return control; } private void OnEnumValueChanged(EnumComboBox control) { var box = (InputBox)control.Tag; box.ParentNode.SetValue(box.Archetype.ValueIndex, control.EnumTypeValue); } public bool IsValid(InputBox box, Control control) { return control is EnumComboBox; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is EnumComboBox enumComboBox) { enumComboBox.EnumTypeValue = GetValue(box); } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { } private object GetValue(InputBox box) { var value = box.CurrentType.CreateInstance(); var v = box.ParentNode.Values[box.Archetype.ValueIndex]; if (v != null && v.GetType().IsEnum) value = v; return value; } } class TypeDefaultValueEditor : IDefaultValueEditor { public bool CanUse(InputBox box, ref ScriptType type) { if (type.Type == typeof(string) && box.Attributes != null && box.Attributes.Any(x => x.GetType() == typeof(TypeReferenceAttribute))) return true; return type.Type == typeof(Type) || type.Type == typeof(ScriptType); } public Control Create(InputBox box, ref Rectangle bounds) { var value = GetValue(box); var control = new TypePickerControl { Location = new Vector2(bounds.X, bounds.Y), Size = new Vector2(60.0f, bounds.Height), ValueTypeName = value, Parent = box.Parent, Tag = box, }; if (box.CurrentType.Type == typeof(Type)) control.CheckValid = type => type.Type != null; control.TypePickerValueChanged += OnTypeValueChanged; return control; } private void OnTypeValueChanged(TypePickerControl control) { var box = (InputBox)control.Tag; var v = box.ParentNode.Values[box.Archetype.ValueIndex]; if (v is string) box.ParentNode.SetValue(box.Archetype.ValueIndex, control.ValueTypeName); else if (v is Type) box.ParentNode.SetValue(box.Archetype.ValueIndex, TypeUtils.GetType(control.Value)); else box.ParentNode.SetValue(box.Archetype.ValueIndex, control.Value); } public bool IsValid(InputBox box, Control control) { return control is TypePickerControl; } public void UpdateDefaultValue(InputBox box, Control control) { if (control is TypePickerControl typePickerControl) { typePickerControl.ValueTypeName = GetValue(box); } } public void UpdateAttributes(InputBox box, object[] attributes, Control control) { var typeReference = (TypeReferenceAttribute)attributes.FirstOrDefault(x => x.GetType() == typeof(TypeReferenceAttribute)); var type = typeReference != null ? TypeUtils.GetType(typeReference.TypeName) : ScriptType.Null; ((TypePickerControl)control).Type = type ? type : new ScriptType(typeof(object)); } private string GetValue(InputBox box) { var v = box.ParentNode.Values[box.Archetype.ValueIndex]; if (v is Type asType) return asType.FullName; if (v is ScriptType asScriptType) return asScriptType.TypeName; if (v is string asString) return asString; return string.Empty; } } /// /// Visject Surface input box element. /// /// [HideInEditor] public class InputBox : Box { private Control _defaultValueEditor; private IDefaultValueEditor _editor; /// /// The handlers for the input box default value editing. Used to display the default to the UI. /// public static readonly List DefaultValueEditors = new List() { new BooleanDefaultValueEditor(), new IntegerDefaultValueEditor(), new UnsignedIntegerDefaultValueEditor(), new FloatingDefaultValueEditor(), new StringDefaultValueEditor(), new Vector2DefaultValueEditor(), new Vector3DefaultValueEditor(), new Vector4DefaultValueEditor(), new QuaternionDefaultValueEditor(), new ColorDefaultValueEditor(), new EnumDefaultValueEditor(), new TypeDefaultValueEditor(), }; /// /// Gets the control that is used to edit default value (optional). /// public Control DefaultValueEditor => _defaultValueEditor; /// public InputBox(SurfaceNode parentNode, NodeElementArchetype archetype) : base(parentNode, archetype, archetype.Position) { // Check if use inlined default value editor if (Archetype.ValueIndex != -1) { ParentNode.ValuesChanged += UpdateDefaultValue; } } /// /// Updates the default value editor UI value. /// public void UpdateDefaultValue() { var currentType = CurrentType.Type; if (_defaultValueEditor != null && currentType != null) { _editor.UpdateDefaultValue(this, _defaultValueEditor); } } /// public override bool IsOutput => false; /// protected override void OnLocationChanged() { base.OnLocationChanged(); if (_defaultValueEditor != null) { _defaultValueEditor.Location = new Vector2(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y); } } /// public override void Draw() { base.Draw(); // Box DrawBox(); // Draw text var style = Style.Current; var rect = new Rectangle(Width + 4, 0, 1410, Height); Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center); } /// protected override void OnCurrentTypeChanged() { base.OnCurrentTypeChanged(); if (_defaultValueEditor != null && !_editor.IsValid(this, _defaultValueEditor)) { _defaultValueEditor.Dispose(); _defaultValueEditor = null; _editor = null; } if (Connections.Count == 0) { CreateDefaultEditor(); } } /// public override void OnConnectionsChanged() { bool showEditor = Connections.Count == 0 && Archetype.ValueIndex != -1; if (showEditor) { CreateDefaultEditor(); } if (_defaultValueEditor != null) { _defaultValueEditor.Enabled = showEditor; _defaultValueEditor.Visible = showEditor; } } /// protected override void OnAttributesChanged() { OnCurrentTypeChanged(); _editor?.UpdateAttributes(this, _attributes ?? Utils.GetEmptyArray(), _defaultValueEditor); } /// public override void OnSurfaceCanEditChanged(bool canEdit) { base.OnSurfaceCanEditChanged(canEdit); if (_defaultValueEditor != null) { _defaultValueEditor.Enabled = canEdit; } } /// /// Creates the default value editor control. /// private void CreateDefaultEditor() { if (_defaultValueEditor != null || Archetype.ValueIndex == -1) return; for (int i = 0; i < DefaultValueEditors.Count; i++) { if (DefaultValueEditors[i].CanUse(this, ref _currentType)) { var bounds = new Rectangle(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y, 90, Height); _editor = DefaultValueEditors[i]; _defaultValueEditor = _editor.Create(this, ref bounds); if (_attributes != null) _editor.UpdateAttributes(this, _attributes, _defaultValueEditor); break; } } } } }