Add Tab navigation for Editor UI
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user