Add Tab navigation for Editor UI

This commit is contained in:
Wojciech Figat
2021-12-21 18:13:45 +01:00
parent c178afdf6b
commit af75751bf1
15 changed files with 293 additions and 195 deletions

View File

@@ -374,6 +374,72 @@ namespace FlaxEditor.GUI
}
}
/// <summary>
/// Shows the context menu popup.
/// </summary>
protected void ShowPopup()
{
// Ensure to have valid menu
if (_popupMenu == null)
{
_popupMenu = OnCreatePopup();
_popupMenu.MaximumItemsInViewCount = MaximumItemsInViewCount;
// Bind events
_popupMenu.VisibleChanged += cm =>
{
var win = Root;
_blockPopup = win != null && new Rectangle(Vector2.Zero, Size).Contains(PointFromWindow(win.MousePosition));
if (!_blockPopup)
Focus();
};
_popupMenu.ButtonClicked += btn =>
{
OnItemClicked((int)btn.Tag);
_popupMenu?.Hide();
};
}
// Check if menu hs been already shown
if (_popupMenu.Visible)
{
_popupMenu.Hide();
return;
}
PopupShowing?.Invoke(this);
// Check if has any items
if (_items.Count > 0)
{
// Setup items list
var itemControls = _popupMenu.Items.ToArray();
foreach (var e in itemControls)
e.Dispose();
if (Sorted)
_items.Sort();
var style = Style.Current;
for (int i = 0; i < _items.Count; i++)
{
var btn = _popupMenu.AddButton(_items[i]);
if (_selectedIndices.Contains(i))
{
btn.Icon = style.CheckBoxTick;
}
if (_tooltips != null && _tooltips.Length > i)
{
btn.TooltipText = _tooltips[i];
}
btn.Tag = i;
}
// Show dropdown list
_popupMenu.MinimumWidth = Width;
_popupMenu.Show(this, new Vector2(1, Height));
}
}
/// <summary>
/// Creates the popup menu.
/// </summary>
@@ -426,7 +492,7 @@ namespace FlaxEditor.GUI
borderColor = BorderColorSelected;
arrowColor = ArrowColorSelected;
}
else if (IsMouseOver)
else if (IsMouseOver || IsNavFocused)
{
backgroundColor = BackgroundColorHighlighted;
borderColor = BorderColorHighlighted;
@@ -478,11 +544,10 @@ namespace FlaxEditor.GUI
/// <inheritdoc />
public override bool OnMouseDown(Vector2 location, MouseButton button)
{
// Check mouse buttons
if (button == MouseButton.Left)
{
// Set flag
_mouseDown = true;
Focus();
}
return base.OnMouseDown(location, button);
@@ -491,72 +556,10 @@ namespace FlaxEditor.GUI
/// <inheritdoc />
public override bool OnMouseUp(Vector2 location, MouseButton button)
{
// Check flags
if (_mouseDown && !_blockPopup)
{
// Clear flag
_mouseDown = false;
// Ensure to have valid menu
if (_popupMenu == null)
{
_popupMenu = OnCreatePopup();
_popupMenu.MaximumItemsInViewCount = MaximumItemsInViewCount;
// Bind events
_popupMenu.VisibleChanged += cm =>
{
var win = Root;
_blockPopup = win != null && new Rectangle(Vector2.Zero, Size).Contains(PointFromWindow(win.MousePosition));
if (!_blockPopup)
Focus();
};
_popupMenu.ButtonClicked += btn =>
{
OnItemClicked((int)btn.Tag);
_popupMenu?.Hide();
};
}
// Check if menu hs been already shown
if (_popupMenu.Visible)
{
// Hide
_popupMenu.Hide();
return true;
}
PopupShowing?.Invoke(this);
// Check if has any items
if (_items.Count > 0)
{
// Setup items list
var itemControls = _popupMenu.Items.ToArray();
foreach (var e in itemControls)
e.Dispose();
if (Sorted)
_items.Sort();
var style = Style.Current;
for (int i = 0; i < _items.Count; i++)
{
var btn = _popupMenu.AddButton(_items[i]);
if (_selectedIndices.Contains(i))
{
btn.Icon = style.CheckBoxTick;
}
if (_tooltips != null && _tooltips.Length > i)
{
btn.TooltipText = _tooltips[i];
}
btn.Tag = i;
}
// Show dropdown list
_popupMenu.MinimumWidth = Width;
_popupMenu.Show(this, new Vector2(1, Height));
}
ShowPopup();
}
else
{
@@ -565,5 +568,13 @@ namespace FlaxEditor.GUI
return true;
}
/// <inheritdoc />
public override void OnSubmit()
{
base.OnSubmit();
ShowPopup();
}
}
}

View File

@@ -34,7 +34,6 @@ namespace FlaxEditor.GUI.Dialogs
private Color _value;
private bool _disableEvents;
private bool _useDynamicEditing;
private bool _isClosing;
private ColorValueBox.ColorPickerEvent _onChanged;
private ColorValueBox.ColorPickerClosedEvent _onClosed;
@@ -139,7 +138,7 @@ namespace FlaxEditor.GUI.Dialogs
_cBlue.ValueChanged += OnRGBAChanged;
// Alpha
_cAlpha = new FloatValueBox(0, _cRed.X, _cBlue.Bottom + ChannelsMargin, _cRed.Width, 0, float.MaxValue, 0.001f)
_cAlpha = new FloatValueBox(0, _cRed.X, _cBlue.Bottom + ChannelsMargin, _cRed.Width, 0, float.MaxValue, 0.001f)
{
Parent = this
};
@@ -183,7 +182,7 @@ namespace FlaxEditor.GUI.Dialogs
Text = "Cancel",
Parent = this
};
_cCancel.Clicked += OnCancelClicked;
_cCancel.Clicked += OnCancel;
// OK
_cOK = new Button(_cCancel.Left - ButtonsWidth - PickerMargin, _cCancel.Y, ButtonsWidth)
@@ -191,42 +190,12 @@ namespace FlaxEditor.GUI.Dialogs
Text = "Ok",
Parent = this
};
_cOK.Clicked += OnOkClicked;
_cOK.Clicked += OnSubmit;
// Set initial color
SelectedColor = initialValue;
}
private void OnOkClicked()
{
if (_isClosing)
return;
_isClosing = true;
// Send color event if modified
if (_value != _initialValue)
{
_onChanged?.Invoke(_value, false);
}
Close(DialogResult.OK);
}
private void OnCancelClicked()
{
if (_isClosing)
return;
_isClosing = true;
// Restore color if modified
if (_useDynamicEditing && _initialValue != _value)
{
_onChanged?.Invoke(_initialValue, false);
}
Close(DialogResult.Cancel);
}
private void OnRGBAChanged()
{
if (_disableEvents)
@@ -300,11 +269,43 @@ namespace FlaxEditor.GUI.Dialogs
protected override void OnShow()
{
// Auto cancel on lost focus
((WindowRootControl)Root).Window.LostFocus += OnCancelClicked;
((WindowRootControl)Root).Window.LostFocus += OnCancel;
base.OnShow();
}
/// <inheritdoc />
public override void OnSubmit()
{
if (_disableEvents)
return;
_disableEvents = true;
// Send color event if modified
if (_value != _initialValue)
{
_onChanged?.Invoke(_value, false);
}
base.OnSubmit();
}
/// <inheritdoc />
public override void OnCancel()
{
if (_disableEvents)
return;
_disableEvents = true;
// Restore color if modified
if (_useDynamicEditing && _initialValue != _value)
{
_onChanged?.Invoke(_initialValue, false);
}
base.OnCancel();
}
/// <inheritdoc />
public override void OnDestroy()
{
@@ -316,7 +317,7 @@ namespace FlaxEditor.GUI.Dialogs
/// <inheritdoc />
public void ClosePicker()
{
OnCancelClicked();
OnCancel();
}
}
}

View File

@@ -220,6 +220,14 @@ namespace FlaxEditor.GUI.Dialogs
}
}
/// <summary>
/// Called to cancel action and close the dialog.
/// </summary>
public virtual void OnCancel()
{
Close(DialogResult.Cancel);
}
/// <summary>
/// Closes dialog with the specified result.
/// </summary>
@@ -243,6 +251,7 @@ namespace FlaxEditor.GUI.Dialogs
/// </summary>
protected virtual void OnShow()
{
Focus();
}
/// <summary>
@@ -254,5 +263,37 @@ namespace FlaxEditor.GUI.Dialogs
{
return true;
}
/// <inheritdoc />
public override void OnSubmit()
{
base.OnSubmit();
Close(DialogResult.OK);
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
if (base.OnKeyDown(key))
return true;
switch (key)
{
case KeyboardKeys.Return:
if (Root?.FocusedControl != null)
Root.SubmitFocused();
else
OnSubmit();
return true;
case KeyboardKeys.Escape:
OnCancel();
return true;
case KeyboardKeys.Tab:
Root?.Navigate(NavDirection.Next);
return true;
}
return false;
}
}
}

View File

@@ -78,8 +78,6 @@ namespace FlaxEditor.GUI.Input
if (_value != value)
{
_value = value;
// Fire event
OnValueChanged();
}
}
@@ -128,16 +126,24 @@ namespace FlaxEditor.GUI.Input
var r = new Rectangle(2, 2, Width - 4, Height - 4);
Render2D.FillRectangle(r, _value);
Render2D.DrawRectangle(r, IsMouseOver ? style.BackgroundSelected : Color.Black);
Render2D.DrawRectangle(r, IsMouseOver || IsNavFocused ? style.BackgroundSelected : Color.Black);
}
/// <inheritdoc />
public override bool OnMouseUp(Vector2 location, MouseButton button)
{
Focus();
OnSubmit();
return true;
}
/// <inheritdoc />
public override void OnSubmit()
{
base.OnSubmit();
// Show color picker dialog
_currentDialog = ShowPickColorDialog?.Invoke(this, _value, OnColorChanged, OnPickerClosed);
return true;
}
private void OnColorChanged(Color color, bool sliding)

View File

@@ -110,7 +110,7 @@ namespace FlaxEditor.GUI
bool enabled = EnabledInHierarchy;
// Draw background
if (enabled && (IsMouseOver || Checked))
if (enabled && (IsMouseOver || IsNavFocused || Checked))
Render2D.FillRectangle(clientRect, Checked ? style.BackgroundSelected : _mouseDown ? style.BackgroundHighlighted : (style.LightBackground * 1.3f));
// Draw icon

View File

@@ -1103,6 +1103,15 @@ namespace FlaxEditor.GUI.Tree
Height = Mathf.Max(_headerHeight, y);
}
/// <inheritdoc />
protected override bool CanNavigateChild(Control child)
{
// Closed tree node skips navigation for hidden children
if (IsCollapsed && child is TreeNode)
return false;
return base.CanNavigateChild(child);
}
/// <inheritdoc />
protected override void OnParentChangedInternal()
{