diff --git a/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs b/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs new file mode 100644 index 000000000..eb559d66b --- /dev/null +++ b/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs @@ -0,0 +1,183 @@ +// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Globalization; +using FlaxEditor.GUI; +using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.GUI.Tree; +using FlaxEditor.Utilities; +using FlaxEngine; +using FlaxEngine.GUI; + +namespace FlaxEditor.CustomEditors.Editors +{ + /// + /// Default implementation of the inspector used to edit value type properties. Supports editing property of type (as culture name). + /// + [CustomEditor(typeof(CultureInfo)), DefaultEditor] + internal class CultureInfoEditor : CustomEditor + { + private ClickableLabel _label; + + /// + public override DisplayStyle Style => DisplayStyle.Inline; + + /// + public override void Initialize(LayoutElementsContainer layout) + { + _label = layout.ClickableLabel(GetName(Culture)).CustomControl; + _label.RightClick += ShowPicker; + var button = new Button + { + Width = 16.0f, + Text = "...", + Parent = _label, + }; + button.SetAnchorPreset(AnchorPresets.MiddleRight, false, true); + button.Clicked += ShowPicker; + } + + /// + public override void Refresh() + { + base.Refresh(); + + _label.Text = GetName(Culture); + } + + /// + protected override void Deinitialize() + { + _label = null; + + base.Deinitialize(); + } + + private CultureInfo Culture + { + get + { + if (Values[0] is CultureInfo asCultureInfo) + return asCultureInfo; + if (Values[0] is string asString) + return new CultureInfo(asString); + return null; + } + set + { + if (Values[0] is CultureInfo) + SetValue(value); + else if (Values[0] is string) + SetValue(value.Name); + } + } + + private class CultureInfoComparer : IComparer + { + public int Compare(CultureInfo a, CultureInfo b) + { + return string.Compare(a.Name, b.Name, StringComparison.Ordinal); + } + } + + public static void UpdateFilter(TreeNode node, string filterText) + { + // Update children + bool isAnyChildVisible = false; + for (int i = 0; i < node.Children.Count; i++) + { + if (node.Children[i] is TreeNode child) + { + UpdateFilter(child, filterText); + isAnyChildVisible |= child.Visible; + } + } + + // Update itself + bool noFilter = string.IsNullOrWhiteSpace(filterText); + bool isThisVisible = noFilter || QueryFilterHelper.Match(filterText, node.Text); + bool isExpanded = isAnyChildVisible; + if (isExpanded) + node.Expand(true); + else + node.Collapse(true); + node.Visible = isThisVisible | isAnyChildVisible; + } + + private void ShowPicker() + { + var menu = new ContextMenuBase + { + Size = new Vector2(320, 220), + }; + var searchBox = new TextBox(false, 1, 1) + { + Width = menu.Width - 3, + WatermarkText = "Search...", + Parent = menu + }; + var panel1 = new Panel(ScrollBars.Vertical) + { + Bounds = new Rectangle(0, searchBox.Bottom + 1, menu.Width, menu.Height - searchBox.Bottom - 2), + Parent = menu + }; + var panel2 = new VerticalPanel + { + Parent = panel1, + AnchorPreset = AnchorPresets.HorizontalStretchTop, + IsScrollable = true, + }; + var tree = new Tree(false) + { + Parent = panel2, + Margin = new Margin(-16.0f, 0.0f, -16.0f, -0.0f), // Hide root node + }; + var root = tree.AddChild(); + var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); + Array.Sort(cultures, 1, cultures.Length - 2, new CultureInfoComparer()); // at 0 there is Invariant Culture + var lcidToNode = new Dictionary(); + for (var i = 0; i < cultures.Length; i++) + { + var culture = cultures[i]; + var node = new TreeNode + { + Tag = culture, + Text = GetName(culture), + }; + if (!lcidToNode.TryGetValue(culture.Parent.LCID, out ContainerControl parent)) + parent = root; + node.Parent = parent; + lcidToNode[culture.LCID] = node; + } + var value = Culture; + if (value != null) + tree.Select((TreeNode)lcidToNode[value.LCID]); + tree.SelectedChanged += delegate(List before, List after) + { + if (after.Count == 1) + { + menu.Hide(); + Culture = (CultureInfo)after[0].Tag; + } + }; + searchBox.TextChanged += delegate + { + if (tree.IsLayoutLocked) + return; + root.LockChildrenRecursive(); + var query = searchBox.Text; + UpdateFilter(root, query); + root.UnlockChildrenRecursive(); + menu.PerformLayout(); + }; + root.ExpandAll(true); + menu.Show(_label, new Vector2(0, _label.Height)); + } + + private static string GetName(CultureInfo value) + { + return value != null ? string.Format("{0} - {1}", value.Name, value.EnglishName) : null; + } + } +} diff --git a/Source/Editor/CustomEditors/Editors/EnumEditor.cs b/Source/Editor/CustomEditors/Editors/EnumEditor.cs index 7954e18bf..b91c0cf95 100644 --- a/Source/Editor/CustomEditors/Editors/EnumEditor.cs +++ b/Source/Editor/CustomEditors/Editors/EnumEditor.cs @@ -9,7 +9,7 @@ using FlaxEngine; namespace FlaxEditor.CustomEditors.Editors { /// - /// Default implementation of the inspector used to edit float value type properties. + /// Default implementation of the inspector used to edit enum value type properties. /// [CustomEditor(typeof(Enum)), DefaultEditor] public class EnumEditor : CustomEditor