// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using FlaxEditor.CustomEditors.Elements; using FlaxEditor.CustomEditors.GUI; using FlaxEditor.GUI; using FlaxEngine; using FlaxEngine.Assertions; using FlaxEngine.GUI; namespace FlaxEditor.CustomEditors { /// /// Represents a container control for . Can contain child elements. /// /// [HideInEditor] public abstract class LayoutElementsContainer : LayoutElement { /// /// Helper flag that is set to true if this container is in root presenter area, otherwise it's one of child groups. /// It's used to collapse all child groups and open the root ones by auto. /// internal bool isRootGroup = true; /// /// The children. /// public readonly List Children = new List(); /// /// Gets the control represented by this element. /// public abstract ContainerControl ContainerControl { get; } /// /// Adds new group element. /// /// The title. /// True if use drop down icon and transparent group header, otherwise use normal style. /// The created element. public GroupElement Group(string title, bool useTransparentHeader = false) { var element = new GroupElement(); if (!isRootGroup) { element.Panel.Close(false); } else if (this is CustomEditorPresenter presenter && presenter.CacheExpandedGroups) { if (Editor.Instance.ProjectCache.IsCollapsedGroup(title)) element.Panel.Close(false); element.Panel.IsClosedChanged += OnPanelIsClosedChanged; } element.isRootGroup = false; element.Panel.HeaderText = title; if (useTransparentHeader) { element.Panel.EnableDropDownIcon = true; element.Panel.HeaderColor = element.Panel.HeaderColorMouseOver = Color.Transparent; } OnAddElement(element); return element; } private void OnPanelIsClosedChanged(DropPanel panel) { Editor.Instance.ProjectCache.SetCollapsedGroup(panel.HeaderText, panel.IsClosed); } /// /// Adds new button element. /// /// The text. /// The created element. public ButtonElement Button(string text) { var element = new ButtonElement(); element.Init(text); OnAddElement(element); return element; } /// /// Adds new button element with custom color. /// /// The text. /// The color. /// The created element. public ButtonElement Button(string text, Color color) { ButtonElement element = new ButtonElement(); element.Init(text, color); OnAddElement(element); return element; } /// /// Adds new custom element. /// /// The custom control. /// The created element. public CustomElement Custom() where T : Control, new() { var element = new CustomElement(); OnAddElement(element); return element; } /// /// Adds new custom element with name label. /// /// The property name. /// The custom control. /// The property label tooltip text. /// The created element. public CustomElement Custom(string name, string tooltip = null) where T : Control, new() { var property = AddPropertyItem(name, tooltip); return property.Custom(); } /// /// Adds new custom elements container. /// /// The custom control. /// The created element. public CustomElementsContainer CustomContainer() where T : ContainerControl, new() { var element = new CustomElementsContainer(); OnAddElement(element); return element; } /// /// Adds new custom elements container with name label. /// /// The property name. /// The custom control. /// The property label tooltip text. /// The created element. public CustomElementsContainer CustomContainer(string name, string tooltip = null) where T : ContainerControl, new() { var property = AddPropertyItem(name); return property.CustomContainer(); } /// /// Adds new space. /// /// The space height. /// The created element. public SpaceElement Space(float height) { var element = new SpaceElement(); element.Init(height); OnAddElement(element); return element; } /// /// Adds sprite image to the layout. /// /// The sprite. /// The created element. public ImageElement Image(SpriteHandle sprite) { var element = new ImageElement(); element.Image.Brush = new SpriteBrush(sprite); OnAddElement(element); return element; } /// /// Adds texture image to the layout. /// /// The texture. /// The created element. public ImageElement Image(Texture texture) { var element = new ImageElement(); element.Image.Brush = new TextureBrush(texture); OnAddElement(element); return element; } /// /// Adds GPU texture image to the layout. /// /// The GPU texture. /// The created element. public ImageElement Image(GPUTexture texture) { var element = new ImageElement(); element.Image.Brush = new GPUTextureBrush(texture); OnAddElement(element); return element; } /// /// Adds new header control. /// /// The header text. /// The created element. public LabelElement Header(string text) { var element = Label(text); element.Label.Font = new FontReference(Style.Current.FontLarge); return element; } /// /// Adds new text box element. /// /// Enable/disable multiline text input support /// The created element. public TextBoxElement TextBox(bool isMultiline = false) { var element = new TextBoxElement(isMultiline); OnAddElement(element); return element; } /// /// Adds new check box element. /// /// The created element. public CheckBoxElement Checkbox() { var element = new CheckBoxElement(); OnAddElement(element); return element; } /// /// Adds new check box element with name label. /// /// The property name. /// The property label tooltip text. /// The created element. public CheckBoxElement Checkbox(string name, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.Checkbox(); } /// /// Adds new tree element. /// /// The created element. public TreeElement Tree() { var element = new TreeElement(); OnAddElement(element); return element; } /// /// Adds new label element. /// /// The label text. /// The label text horizontal alignment. /// The created element. public LabelElement Label(string text, TextAlignment horizontalAlignment = TextAlignment.Near) { var element = new LabelElement(); element.Label.Text = text; element.Label.HorizontalAlignment = horizontalAlignment; OnAddElement(element); return element; } /// /// Adds new label element with name label. /// /// The property name. /// The label text. /// The property label tooltip text. /// The created element. public LabelElement Label(string name, string text, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.Label(text); } /// /// Adds new label element. /// /// The label text. /// The label text horizontal alignment. /// The created element. public CustomElement ClickableLabel(string text, TextAlignment horizontalAlignment = TextAlignment.Near) { var element = new CustomElement(); element.CustomControl.Height = 18.0f; element.CustomControl.Text = text; element.CustomControl.HorizontalAlignment = horizontalAlignment; OnAddElement(element); return element; } /// /// Adds new label element with name label. /// /// The property name. /// The label text. /// The property label tooltip text. /// The created element. public CustomElement ClickableLabel(string name, string text, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.ClickableLabel(text); } /// /// Adds new float value element. /// /// The created element. public FloatValueElement FloatValue() { var element = new FloatValueElement(); OnAddElement(element); return element; } /// /// Adds new float value element with name label. /// /// The property name. /// The property label tooltip text. /// The created element. public FloatValueElement FloatValue(string name, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.FloatValue(); } /// /// Adds new double value element. /// /// The created element. public DoubleValueElement DoubleValue() { var element = new DoubleValueElement(); OnAddElement(element); return element; } /// /// Adds new double value element with name label. /// /// The property name. /// The property label tooltip text. /// The created element. public DoubleValueElement DoubleValue(string name, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.DoubleValue(); } /// /// Adds new slider element. /// /// The created element. public SliderElement Slider() { var element = new SliderElement(); OnAddElement(element); return element; } /// /// Adds new slider element with name label. /// /// The property name. /// The property label tooltip text. /// The created element. public SliderElement Slider(string name, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.Slider(); } /// /// Adds new signed integer (up to long range) value element. /// /// The created element. public SignedIntegerValueElement SignedIntegerValue() { var element = new SignedIntegerValueElement(); OnAddElement(element); return element; } /// /// Adds new unsigned signed integer (up to ulong range) value element. /// /// The created element. public UnsignedIntegerValueElement UnsignedIntegerValue() { var element = new UnsignedIntegerValueElement(); OnAddElement(element); return element; } /// /// Adds new integer value element. /// /// The created element. public IntegerValueElement IntegerValue() { var element = new IntegerValueElement(); OnAddElement(element); return element; } /// /// Adds new integer value element with name label. /// /// The property name. /// The property label tooltip text. /// The created element. public IntegerValueElement IntegerValue(string name, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.IntegerValue(); } /// /// Adds new combobox element. /// /// The created element. public ComboBoxElement ComboBox() { var element = new ComboBoxElement(); OnAddElement(element); return element; } /// /// Adds new combobox element with name label. /// /// The property name. /// The property label tooltip text. /// The created element. public ComboBoxElement ComboBox(string name, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.ComboBox(); } /// /// Adds new enum value element. /// /// The enum type. /// The custom entries layout builder. Allows to hide existing or add different enum values to editor. /// The formatting mode. /// The created element. public EnumElement Enum(Type type, EnumComboBox.BuildEntriesDelegate customBuildEntriesDelegate = null, EnumDisplayAttribute.FormatMode formatMode = EnumDisplayAttribute.FormatMode.Default) { var element = new EnumElement(type, customBuildEntriesDelegate, formatMode); OnAddElement(element); return element; } /// /// Adds new enum value element with name label. /// /// The property name. /// The enum type. /// The custom entries layout builder. Allows to hide existing or add different enum values to editor. /// The property label tooltip text. /// The formatting mode. /// The created element. public EnumElement Enum(string name, Type type, EnumComboBox.BuildEntriesDelegate customBuildEntriesDelegate = null, string tooltip = null, EnumDisplayAttribute.FormatMode formatMode = EnumDisplayAttribute.FormatMode.Default) { var property = AddPropertyItem(name, tooltip); return property.Enum(type, customBuildEntriesDelegate, formatMode); } /// /// Adds object(s) editor. Selects proper based on overrides. /// /// The values. /// The custom editor to use. If null will detect it by auto. /// The created element. public CustomEditor Object(ValueContainer values, CustomEditor overrideEditor = null) { if (values == null) throw new ArgumentNullException(); var editor = CustomEditorsUtil.CreateEditor(values, overrideEditor); OnAddEditor(editor); editor.Initialize(CustomEditor.CurrentCustomEditor.Presenter, this, values); return editor; } /// /// Adds object(s) editor with name label. Selects proper based on overrides. /// /// The property name. /// The values. /// The custom editor to use. If null will detect it by auto. /// The property label tooltip text. /// The created element. public CustomEditor Object(string name, ValueContainer values, CustomEditor overrideEditor = null, string tooltip = null) { var property = AddPropertyItem(name, tooltip); return property.Object(values, overrideEditor); } /// /// Adds object(s) editor with name label. Selects proper based on overrides. /// /// The property label. /// The values. /// The custom editor to use. If null will detect it by auto. /// The property label tooltip text. /// The created element. public CustomEditor Object(PropertyNameLabel label, ValueContainer values, CustomEditor overrideEditor = null, string tooltip = null) { var property = AddPropertyItem(label, tooltip); return property.Object(values, overrideEditor); } /// /// Adds object property editor. Selects proper based on overrides. /// /// The property name. /// The values. /// The custom editor to use. If null will detect it by auto. /// The property label tooltip text. /// The created element. public CustomEditor Property(string name, ValueContainer values, CustomEditor overrideEditor = null, string tooltip = null) { var editor = CustomEditorsUtil.CreateEditor(values, overrideEditor); var style = editor.Style; if (style == DisplayStyle.InlineIntoParent || name == EditorDisplayAttribute.InlineStyle) { return Object(values, editor); } if (style == DisplayStyle.Group) { var group = Group(name, true); group.Panel.Close(false); group.Panel.TooltipText = tooltip; return group.Object(values, editor); } var property = AddPropertyItem(name, tooltip); return property.Object(values, editor); } /// /// Adds object property editor. Selects proper based on overrides. /// /// The property label. /// The values. /// The custom editor to use. If null will detect it by auto. /// The property label tooltip text. /// The created element. public CustomEditor Property(PropertyNameLabel label, ValueContainer values, CustomEditor overrideEditor = null, string tooltip = null) { var editor = CustomEditorsUtil.CreateEditor(values, overrideEditor); var style = editor.Style; if (style == DisplayStyle.InlineIntoParent) { return Object(values, editor); } if (style == DisplayStyle.Group) { var group = Group(label.Text, true); group.Panel.Close(false); return group.Object(values, editor); } var property = AddPropertyItem(label, tooltip); return property.Object(values, editor); } private PropertiesListElement AddPropertyItem() { // Try to reuse previous control PropertiesListElement element; if (Children.Count > 0 && Children[Children.Count - 1] is PropertiesListElement propertiesListElement) { element = propertiesListElement; } else { element = new PropertiesListElement(); OnAddElement(element); } return element; } /// /// Adds the to the current layout or reuses the previous one. Used to inject properties. /// /// The property label name. /// The property label tooltip text. /// The element. public PropertiesListElement AddPropertyItem(string name, string tooltip = null) { var element = AddPropertyItem(); element.OnAddProperty(name, tooltip); return element; } /// /// Adds the to the current layout or reuses the previous one. Used to inject properties. /// /// The property label. /// The property label tooltip text. /// The element. public PropertiesListElement AddPropertyItem(PropertyNameLabel label, string tooltip = null) { if (label == null) throw new ArgumentNullException(); var element = AddPropertyItem(); element.OnAddProperty(label, tooltip); return element; } /// /// Called when element is added to the layout. /// /// The element. protected virtual void OnAddElement(LayoutElement element) { element.Control.Parent = ContainerControl; Children.Add(element); } /// /// Called when editor is added. /// /// The editor. protected virtual void OnAddEditor(CustomEditor editor) { // This could be passed by the calling code but it's easier to hide it from the user // Note: we need that custom editor to link generated editor into the parent var customEditor = CustomEditor.CurrentCustomEditor; Assert.IsNotNull(customEditor); customEditor.OnChildCreated(editor); } /// /// Clears the layout. /// public virtual void ClearLayout() { Children.Clear(); } /// public override Control Control => ContainerControl; } }