_windows window and tab dragging done

This commit is contained in:
2025-01-19 21:56:10 +02:00
parent 28957fea3e
commit 0aefdf4411
10 changed files with 438 additions and 160 deletions

View File

@@ -22,10 +22,12 @@ namespace FlaxEditor.GUI.Docking
private DockPanel _toDock;
private bool _lateDragOffsetUpdate;
private float _lateDragStartTimer;
private bool _moveWindow;
private Window _dragSourceWindow;
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
private DockHintWindow(FloatWindowDockPanel toMove, bool draggingTab)
private DockHintWindow(FloatWindowDockPanel toMove, Window dragSourceWindow)
{
_toMove = toMove;
_toSet = DockState.Float;
@@ -85,24 +87,29 @@ namespace FlaxEditor.GUI.Docking
/*Proxy.Window.RenderingEnabled = true;
Proxy.Window.Show();
Proxy.Window.Focus();*/
// Hide base window
//window.Hide();
// window.Show();
if (draggingTab)
// window.Show();
_dragSourceWindow = dragSourceWindow;
_moveWindow = _dragSourceWindow != null;
if (_dragSourceWindow != null) // Detaching a tab from existing window
{
_dragOffset = new Float2(window.Size.X / 2, 10.0f);
window.StartDragging(_dragOffset, toMove.MasterPanel?.RootWindow.Window ?? Editor.Instance.Windows.MainWindow);
// TODO: when detaching tab in floating window (not main window), the drag source window is still main window?
var dragSourceWindowWayland = toMove.MasterPanel?.RootWindow.Window ?? Editor.Instance.Windows.MainWindow;
window.DoDragDrop("", _dragOffset, dragSourceWindowWayland);
_dragSourceWindow.MouseUp += OnMouseUp; // The mouse up event is sent to the source window on Windows
}
else
{
var mouseClientPosition = Platform.MousePosition;
CalculateDragOffset(mouseClientPosition);
window.StartDragging(_dragOffset, window);
window.DoDragDrop("", _dragOffset, window);
}
//window.Show();
@@ -146,6 +153,9 @@ namespace FlaxEditor.GUI.Docking
if (_toMove?.Window?.Window)
_toMove.Window.Window.MouseUp -= OnMouseUp;
if (_dragSourceWindow != null)
_dragSourceWindow.MouseUp -= OnMouseUp; // The mouse up event is sent to the source window on Windows
if (_toMove == null)
return;
@@ -160,7 +170,7 @@ namespace FlaxEditor.GUI.Docking
var mouse = Platform.MousePosition;
// Move base window
window.Position = mouse - _dragOffset;
//window.Position = mouse - _dragOffset;
// Show base window
window.Show();
@@ -222,7 +232,7 @@ namespace FlaxEditor.GUI.Docking
if (toMove == null)
throw new ArgumentNullException();
return new DockHintWindow(toMove, false);
return new DockHintWindow(toMove, null);
}
/// <summary>
@@ -230,13 +240,13 @@ namespace FlaxEditor.GUI.Docking
/// </summary>
/// <param name="toMove">Dock window to move.</param>
/// <returns>The dock hint window object.</returns>
public static DockHintWindow Create(DockWindow toMove)
public static DockHintWindow Create(DockWindow toMove, Window dragSourceWindow)
{
if (toMove == null)
throw new ArgumentNullException();
// Show floating
toMove.ShowFloating();
toMove.CreateFloating();
// Move window to the mouse position (with some offset for caption bar)
var window = (WindowRootControl)toMove.Root;
@@ -246,7 +256,7 @@ namespace FlaxEditor.GUI.Docking
// Get floating panel
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
return new DockHintWindow(floatingPanelToMove, true);
return new DockHintWindow(floatingPanelToMove, dragSourceWindow);
}
/// <summary>
@@ -285,9 +295,9 @@ namespace FlaxEditor.GUI.Docking
private void CalculateDragOffset(Float2 mouseScreenPosition)
{
var baseWinPos = _toMove.Window.Window.Position;
_dragOffset = mouseScreenPosition - baseWinPos;
//_dragOffset = mouseScreenPosition - baseWinPos;
Editor.Log($"_dragOffset: {_dragOffset}, mouse: {mouseScreenPosition}, basewinpos: {baseWinPos}");
//Editor.Log($"_dragOffset: {_dragOffset}, mouse: {mouseScreenPosition}, basewinpos: {baseWinPos}");
}
DockHintControl _dockHintDown;
@@ -300,6 +310,9 @@ namespace FlaxEditor.GUI.Docking
if (_toDock == null)
return;
if (_toDock.RootWindow.Window != _dragSourceWindow)
_toDock.RootWindow.Window.MouseUp += OnMouseUp;
_dockHintDown = AddHintControl(new Float2(0.5f, 1));
_dockHintUp = AddHintControl(new Float2(0.5f, 0));
_dockHintLeft = AddHintControl(new Float2(0, 0.5f));
@@ -322,7 +335,10 @@ namespace FlaxEditor.GUI.Docking
{
if (_toDock == null)
return;
if (_toDock.RootWindow.Window != _dragSourceWindow)
_toDock.RootWindow.Window.MouseUp -= OnMouseUp;
_dockHintDown?.Parent.RemoveChild(_dockHintDown);
_dockHintUp?.Parent.RemoveChild(_dockHintUp);
_dockHintLeft?.Parent.RemoveChild(_dockHintLeft);
@@ -338,18 +354,44 @@ namespace FlaxEditor.GUI.Docking
// Check intersection with any dock panel
var uiMouse = _mouse;
var dockPanel = _toMove.MasterPanel.HitTest(ref uiMouse, _toMove);
DockPanel dockPanel = null;
if (_toMove.MasterPanel.HitTest(ref uiMouse, _toMove, out var hitResults))
{
dockPanel = hitResults[0];
// Prefer panel which currently has focus
foreach (var hit in hitResults)
{
if (hit.RootWindow.Window.IsFocused)
{
dockPanel = hit;
break;
}
}
// Prefer panel in the same window we hit earlier
if (dockPanel?.RootWindow != _toDock?.RootWindow)
{
foreach (var hit in hitResults)
{
if (hit.RootWindow == _toDock?.RootWindow)
{
dockPanel = _toDock;
break;
}
}
}
}
if (dockPanel != _toDock)
{
Editor.Log($"UpdateRects: {_mouse}, panel: {dockPanel?.RootWindow?.Window?.Title}");
_toDock?.RootWindow.Window.RemoveDockHints();
RemoveDockHints();
_toDock = dockPanel;
_toDock?.RootWindow.Window.CreateDockHints();
AddDockHints();
// Make sure the all the dock hint areas are not under other windows
_toDock?.RootWindow.Window.BringToFront();
_toMove.RootWindow.Window.BringToFront();
}
// Check dock state to use
@@ -526,13 +568,17 @@ namespace FlaxEditor.GUI.Docking
var mousePos = Platform.MousePosition;
if (_mouse != mousePos)
{
Editor.Log($"mouse pos {_mouse} -> {mousePos}");
//Editor.Log($"mouse pos {_mouse} -> {mousePos}");
OnMouseMove(mousePos);
}
}
private void OnMouseMove(Float2 mousePos)
{
if (_moveWindow)
{
_toMove.Window.Window.Position = mousePos - _dragOffset;
}
//Editor.Log("OnMouseMove");
// Recalculate the drag offset because the current mouse screen position was invalid when we initialized the window
if (_lateDragOffsetUpdate)

View File

@@ -181,7 +181,7 @@ namespace FlaxEditor.GUI.Docking
_panel.SelectTab(index - 1);
// Create docking hint window
DockHintWindow.Create(win);
DockHintWindow.Create(win, _panel.RootWindow.Window);
}
}
}

View File

@@ -182,6 +182,25 @@ namespace FlaxEditor.GUI.Docking
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
/// <param name="position">Window location.</param>
public void ShowFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent)
{
CreateFloating(location, size, position, true);
}
/// <summary>
/// Creates the window in a floating state.
/// </summary>
public void CreateFloating()
{
CreateFloating(Float2.Zero, Float2.Zero);
}
/// <summary>
/// Creates the window in a floating state.
/// </summary>
/// <param name="location">Window location.</param>
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
/// <param name="position">Window location.</param>
/// <param name="showWindow">Window visibility.</param>
public void CreateFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent, bool showWindow = false)
{
Undock();
@@ -199,9 +218,9 @@ namespace FlaxEditor.GUI.Docking
windowGUI.UnlockChildrenRecursive();
windowGUI.PerformLayout();
// Show
/*FlaxEngine.Scripting.InvokeOnUpdate(() =>
if (showWindow)
{
// Show
window.Show();
window.BringToFront();
window.Focus();
@@ -209,7 +228,7 @@ namespace FlaxEditor.GUI.Docking
// Perform layout again
windowGUI.PerformLayout();
});*/
}
}
/// <summary>

View File

@@ -53,7 +53,6 @@ namespace FlaxEditor.GUI.Docking
// Create docking hint window
DockHintWindow.Create(this);
//_window.Window.StartDragging(Float2.Zero);
}
/// <summary>

View File

@@ -81,48 +81,56 @@ namespace FlaxEditor.GUI.Docking
public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded)
{
// Check all floating windows
// TODO: gather windows order and take it into account when performing test
for (int i = 0; i < FloatingPanels.Count; i++)
{
var win = FloatingPanels[i];
if (win.Visible && win != excluded)
{
if (win.Window.Window.IsFocused) // We can't use screen space position in some platforms, only check windows under the cursor
{
var result = win.HitTest(ref position);
if (result != null)
{
Editor.Log($"hit: {win.Window.Window.Title}");
result = result;
}
else
Editor.Log($"no hit: {win.Window.Window.Title}");
}
else
Editor.Log($"no focus: {win.Window.Window.Title}");
}
}
for (int i = 0; i < FloatingPanels.Count; i++)
{
var win = FloatingPanels[i];
if (win.Visible && win != excluded)
{
if (win.Window.Window.IsFocused) // We can't use screen space position in some platforms, only check windows under the cursor
{
var result = win.HitTest(ref position);
if (result != null)
return result;
}
var result = win.HitTest(ref position);
if (result != null)
return result;
}
}
// Base
if (!Root?.RootWindow.Window.IsFocused ?? false)
return null;
//if (!Root?.RootWindow.Window.IsFocused ?? false)
// return null;
return base.HitTest(ref position);
}
/// <summary>
/// Performs hit test over dock panel.
/// </summary>
/// <param name="position">Window space position to test.</param>
/// <param name="excluded">Floating window to omit during searching (and all docked to that one).</param>
/// <param name="hitResults">Results of the hit test</param>
/// <returns>True if any dock panels were hit, otherwise false.</returns>
public bool HitTest(ref Float2 position, FloatWindowDockPanel excluded, out DockPanel[] hitResults)
{
// Check all floating windows
List<DockPanel> results = new(FloatingPanels.Count);
for (int i = 0; i < FloatingPanels.Count; i++)
{
var win = FloatingPanels[i];
if (win.Visible && win != excluded)
{
var result = win.HitTest(ref position);
if (result != null)
results.Add(result);
}
}
// Base
//if (!Root?.RootWindow.Window.IsFocused ?? false)
// return null;
var baseResult = base.HitTest(ref position);
if (baseResult != null)
results.Add(baseResult);
hitResults = results.ToArray();
return hitResults.Length > 0;
}
internal void LinkWindow(DockWindow window)
{
// Add to the windows list