// Copyright (c) Wojciech Figat. All rights reserved. using FlaxEditor.GUI.ContextMenu; using FlaxEditor.Utilities; using FlaxEngine; using FlaxEngine.GUI; namespace FlaxEditor.CustomEditors.GUI { /// /// Displays custom editor property name. /// /// [HideInEditor] public class PropertyNameLabel : Label { // TODO: if name is too long to show -> use tooltip to show it /// /// Custom event delegate that can be used to extend the property name label with an additional functionality. /// /// The label. /// The menu. /// The linked editor. Can be null. public delegate void SetupContextMenuDelegate(PropertyNameLabel label, ContextMenu menu, CustomEditor linkedEditor); private bool _mouseDown; /// /// Helper value used by the to draw property names in a proper area. /// internal int FirstChildControlIndex; /// /// Helper value used by the to draw property names in a proper area. /// internal PropertiesList FirstChildControlContainer; /// /// The linked custom editor (shows the label property). /// internal CustomEditor LinkedEditor; /// /// The highlight strip color drawn on a side (transparent if skip rendering). /// public Color HighlightStripColor; /// /// The active search text query used to highlight matching parts of the label. /// public string SearchText = string.Empty; private string _lastSearchText; private string _lastText; private QueryFilterHelper.Range[] _highlightRanges; private void UpdateHighlights() { var text = Text?.ToString() ?? string.Empty; if (_lastSearchText == SearchText && _lastText == text) return; _lastSearchText = SearchText; _lastText = text; if (!string.IsNullOrEmpty(SearchText)) { QueryFilterHelper.Match(SearchText, text, out _highlightRanges); } else { _highlightRanges = null; } } /// /// Occurs when label creates the context menu popup for th property. Can be used to add some custom logic per property editor. /// public event SetupContextMenuDelegate SetupContextMenu; /// /// Initializes a new instance of the class. /// /// The name. public PropertyNameLabel(string name) { Text = name; HorizontalAlignment = TextAlignment.Near; VerticalAlignment = TextAlignment.Center; Margin = new Margin(4, 0, 0, 0); ClipText = true; HighlightStripColor = Color.Transparent; } internal void LinkEditor(CustomEditor editor) { if (LinkedEditor == null) { LinkedEditor = editor; editor.LinkLabel(this); } } /// public override void Draw() { base.Draw(); if (HighlightStripColor.A > 0.0f) { Render2D.FillRectangle(new Rectangle(0, 0, 2, Height), HighlightStripColor); } UpdateHighlights(); if (_highlightRanges != null && _highlightRanges.Length > 0) { var text = Text.ToString(); var font = Font?.GetFont(); if (font != null) { var style = Style.Current; var color = style.ProgressNormal * 0.6f; var margin = Margin; var textSize = font.MeasureText(text); var textX = margin.Left; var textY = margin.Top + (Height - margin.Height - textSize.Y) * 0.5f; for (int i = 0; i < _highlightRanges.Length; i++) { var start = font.GetCharPosition(text, _highlightRanges[i].StartIndex); var end = font.GetCharPosition(text, _highlightRanges[i].EndIndex); var highlightRect = new Rectangle(start.X + textX, textY, end.X - start.X, textSize.Y); Render2D.FillRectangle(highlightRect, color); } } } } /// public override void OnMouseLeave() { _mouseDown = false; base.OnMouseLeave(); } /// public override bool OnMouseDown(Float2 location, MouseButton button) { if (button == MouseButton.Right) { _mouseDown = true; } return base.OnMouseDown(location, button); } /// public override bool OnMouseUp(Float2 location, MouseButton button) { if (base.OnMouseUp(location, button)) return true; if (_mouseDown && button == MouseButton.Right) { _mouseDown = false; // Skip if is not extended var linkedEditor = LinkedEditor; if (linkedEditor == null && SetupContextMenu == null) return false; var menu = new ContextMenu(); if (linkedEditor != null) { var features = linkedEditor.Presenter.Features; if ((features & (FeatureFlags.UseDefault | FeatureFlags.UsePrefab)) != 0) { if ((features & FeatureFlags.UsePrefab) != 0) menu.AddButton("Revert to Prefab", linkedEditor.RevertToReferenceValue).Enabled = linkedEditor.CanRevertReferenceValue; if ((features & FeatureFlags.UseDefault) != 0) menu.AddButton("Reset to default", linkedEditor.RevertToDefaultValue).Enabled = linkedEditor.CanRevertDefaultValue; menu.AddSeparator(); } menu.AddButton("Copy", linkedEditor.Copy); var paste = menu.AddButton("Paste", linkedEditor.Paste); paste.Enabled = linkedEditor.CanPaste; } SetupContextMenu?.Invoke(this, menu, linkedEditor); menu.Show(this, location); return true; } return false; } /// public override void OnLostFocus() { _mouseDown = false; base.OnLostFocus(); } /// public override void OnDestroy() { SetupContextMenu = null; LinkedEditor = null; FirstChildControlContainer = null; base.OnDestroy(); } /// public override string ToString() { return Text.ToString(); } } }