_wayland toplevel drag WIP
This commit is contained in:
@@ -21,21 +21,22 @@ namespace FlaxEditor.GUI.Docking
|
||||
private DockState _toSet;
|
||||
private DockPanel _toDock;
|
||||
private bool _lateDragOffsetUpdate;
|
||||
private float _lateDragStartTimer;
|
||||
|
||||
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
|
||||
|
||||
private DockHintWindow(FloatWindowDockPanel toMove)
|
||||
private DockHintWindow(FloatWindowDockPanel toMove, bool lateDragStart)
|
||||
{
|
||||
_toMove = toMove;
|
||||
_toSet = DockState.Float;
|
||||
var window = toMove.Window.Window;
|
||||
|
||||
// Remove focus from drag target
|
||||
_toMove.Focus();
|
||||
_toMove.Defocus();
|
||||
//_toMove.Focus();
|
||||
//_toMove.Defocus();
|
||||
|
||||
// Focus window
|
||||
window.Focus();
|
||||
//window.Focus();
|
||||
|
||||
// Check if window is maximized and restore window.
|
||||
if (window.IsMaximized)
|
||||
@@ -48,43 +49,62 @@ namespace FlaxEditor.GUI.Docking
|
||||
}
|
||||
|
||||
// Calculate dragging offset and move window to the destination position
|
||||
var mouseScreenPosition = Platform.MousePosition;
|
||||
var mouseClientPosition = Platform.MousePosition;
|
||||
CalculateDragOffset(mouseClientPosition);
|
||||
|
||||
// If the _toMove window was not focused when initializing this window, the result vector only contains zeros
|
||||
// and to prevent a failure, we need to perform an update for the drag offset at later time which will be done in the OnMouseMove event handler.
|
||||
if (mouseScreenPosition != Float2.Zero)
|
||||
CalculateDragOffset(mouseScreenPosition);
|
||||
else
|
||||
_lateDragOffsetUpdate = true;
|
||||
//if (mouseScreenPosition != Float2.Zero)
|
||||
// CalculateDragOffset(mouseScreenPosition);
|
||||
//else
|
||||
// _lateDragOffsetUpdate = true;
|
||||
|
||||
|
||||
|
||||
// Get initial size
|
||||
_defaultWindowSize = window.Size;
|
||||
|
||||
// Init proxy window
|
||||
Proxy.Init(ref _defaultWindowSize);
|
||||
/*Proxy.Init(ref _defaultWindowSize);
|
||||
|
||||
// Bind events
|
||||
*/
|
||||
|
||||
//FlaxEngine.Input.MouseMove += OnMouseMove;
|
||||
FlaxEngine.Scripting.Update += OnUpdate;
|
||||
_toMove.Window.Window.MouseUp += OnMouseUp;
|
||||
/*
|
||||
Proxy.Window.MouseUp += OnMouseUp;
|
||||
Proxy.Window.MouseMove += OnMouseMove;
|
||||
Proxy.Window.LostFocus += OnLostFocus;
|
||||
_toMove.Window.Window.MouseUp += OnMouseUp; // Intercept the drag release mouse event from source window
|
||||
|
||||
*/
|
||||
// Update window GUI
|
||||
Proxy.Window.GUI.PerformLayout();
|
||||
//Proxy.Window.GUI.PerformLayout();
|
||||
|
||||
// Update rectangles
|
||||
UpdateRects();
|
||||
|
||||
// Enable hit window presentation
|
||||
Proxy.Window.RenderingEnabled = true;
|
||||
/*Proxy.Window.RenderingEnabled = true;
|
||||
Proxy.Window.Show();
|
||||
Proxy.Window.Focus();
|
||||
Proxy.Window.Focus();*/
|
||||
|
||||
// Hide base window
|
||||
window.Hide();
|
||||
//window.Hide();
|
||||
|
||||
|
||||
if (lateDragStart)
|
||||
{
|
||||
// The window needs some time to be fully ready for dragging
|
||||
//_lateDragStartTimer = 1.5f;
|
||||
window.StartDragging(_dragOffset);
|
||||
}
|
||||
else
|
||||
window.StartDragging(_dragOffset);
|
||||
|
||||
// Start tracking mouse
|
||||
Proxy.Window.StartTrackingMouse(false);
|
||||
//Proxy.Window.StartTrackingMouse(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -93,7 +113,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
public void Dispose()
|
||||
{
|
||||
// End tracking mouse
|
||||
Proxy.Window.EndTrackingMouse();
|
||||
/*Proxy.Window.EndTrackingMouse();
|
||||
|
||||
// Disable rendering
|
||||
Proxy.Window.RenderingEnabled = false;
|
||||
@@ -106,11 +126,20 @@ namespace FlaxEditor.GUI.Docking
|
||||
_toMove.Window.Window.MouseUp -= OnMouseUp;
|
||||
|
||||
// Hide the proxy
|
||||
Proxy.Hide();
|
||||
Proxy.Hide();*/
|
||||
|
||||
RemoveDockHints();
|
||||
|
||||
//FlaxEngine.Input.MouseMove -= OnMouseMove;
|
||||
FlaxEngine.Scripting.Update -= OnUpdate;
|
||||
if (_toMove?.Window?.Window)
|
||||
_toMove.Window.Window.MouseUp -= OnMouseUp;
|
||||
|
||||
if (_toMove == null)
|
||||
return;
|
||||
|
||||
_toMove.Window?.Window.StopDragging();
|
||||
|
||||
// Check if window won't be docked
|
||||
if (_toSet == DockState.Float)
|
||||
{
|
||||
@@ -182,7 +211,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
if (toMove == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
return new DockHintWindow(toMove);
|
||||
return new DockHintWindow(toMove, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -200,13 +229,13 @@ namespace FlaxEditor.GUI.Docking
|
||||
|
||||
// Move window to the mouse position (with some offset for caption bar)
|
||||
var window = (WindowRootControl)toMove.Root;
|
||||
var mouse = Platform.MousePosition;
|
||||
window.Window.Position = mouse - new Float2(8, 8);
|
||||
/*var mouse = Platform.MousePosition;
|
||||
window.Window.Position = mouse - new Float2(8, 8);*/
|
||||
|
||||
// Get floating panel
|
||||
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
|
||||
|
||||
return new DockHintWindow(floatingPanelToMove);
|
||||
return new DockHintWindow(floatingPanelToMove, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -250,6 +279,47 @@ namespace FlaxEditor.GUI.Docking
|
||||
Editor.Log($"_dragOffset: {_dragOffset}, mouse: {mouseScreenPosition}, basewinpos: {baseWinPos}");
|
||||
}
|
||||
|
||||
DockHintControl _dockHintDown;
|
||||
DockHintControl _dockHintUp;
|
||||
DockHintControl _dockHintLeft;
|
||||
DockHintControl _dockHintRight;
|
||||
DockHintControl _dockHintCenter;
|
||||
private void AddDockHints()
|
||||
{
|
||||
if (_toDock == null)
|
||||
return;
|
||||
|
||||
_dockHintDown = AddHintControl(new Float2(0.5f, 1));
|
||||
_dockHintUp = AddHintControl(new Float2(0.5f, 0));
|
||||
_dockHintLeft = AddHintControl(new Float2(0, 0.5f));
|
||||
_dockHintRight = AddHintControl(new Float2(1, 0.5f));
|
||||
_dockHintCenter = AddHintControl(new Float2(0.5f, 0.5f));
|
||||
|
||||
DockHintControl AddHintControl(Float2 pivot)
|
||||
{
|
||||
DockHintControl hintControl = _toDock.AddChild<DockHintControl>();
|
||||
hintControl.Size = new Float2(Proxy.HintWindowsSize);
|
||||
hintControl.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
hintControl.Pivot = pivot;
|
||||
hintControl.PivotRelative = true;
|
||||
//.SetAnchorPreset(AnchorPresets.StretchAll, true);
|
||||
return hintControl;
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveDockHints()
|
||||
{
|
||||
if (_toDock == null)
|
||||
return;
|
||||
|
||||
_dockHintDown?.Parent.RemoveChild(_dockHintDown);
|
||||
_dockHintUp?.Parent.RemoveChild(_dockHintUp);
|
||||
_dockHintLeft?.Parent.RemoveChild(_dockHintLeft);
|
||||
_dockHintRight?.Parent.RemoveChild(_dockHintRight);
|
||||
_dockHintCenter?.Parent.RemoveChild(_dockHintCenter);
|
||||
_dockHintDown = _dockHintUp = _dockHintLeft = _dockHintRight = _dockHintCenter = null;
|
||||
}
|
||||
|
||||
private void UpdateRects()
|
||||
{
|
||||
// Cache mouse position
|
||||
@@ -257,12 +327,26 @@ namespace FlaxEditor.GUI.Docking
|
||||
|
||||
// Check intersection with any dock panel
|
||||
var uiMouse = _mouse;
|
||||
_toDock = _toMove.MasterPanel.HitTest(ref uiMouse, _toMove);
|
||||
var dockPanel = _toMove.MasterPanel.HitTest(ref uiMouse, _toMove);
|
||||
|
||||
if (dockPanel != _toDock)
|
||||
{
|
||||
//Editor.Log($"UpdateRects: {_mouse}, panel: {dockPanel?.RootWindow?.Window?.Title}");
|
||||
|
||||
_toDock?.RootWindow.Window.RemoveDockHints();
|
||||
RemoveDockHints();
|
||||
|
||||
_toDock = dockPanel;
|
||||
_toDock?.RootWindow.Window.CreateDockHints();
|
||||
AddDockHints();
|
||||
}
|
||||
|
||||
// Check dock state to use
|
||||
bool showProxyHints = _toDock != null;
|
||||
bool showBorderHints = showProxyHints;
|
||||
bool showCenterHint = showProxyHints;
|
||||
DockHintControl hoveredHintControl = null;
|
||||
Float2 hoveredSizeOverride = Float2.Zero;
|
||||
if (showProxyHints)
|
||||
{
|
||||
// If moved window has not only tabs but also child panels disable docking as tab
|
||||
@@ -277,11 +361,12 @@ namespace FlaxEditor.GUI.Docking
|
||||
_rectDock = _toDock.DockAreaBounds;
|
||||
|
||||
// Cache dock rectangles
|
||||
var size = _rectDock.Size;
|
||||
var offset = _rectDock.Location;
|
||||
var size = _rectDock.Size / Platform.DpiScale;
|
||||
var offset = _toDock.PointFromScreen(_rectDock.Location);
|
||||
var borderMargin = 4.0f;
|
||||
var hintWindowsSize = Proxy.HintWindowsSize * Platform.DpiScale;
|
||||
var hintWindowsSize = Proxy.HintWindowsSize;
|
||||
var hintWindowsSize2 = hintWindowsSize * 0.5f;
|
||||
var hintPreviewSize = new Float2(Math.Max(Proxy.HintWindowsSize * 2, size.X * 0.5f), Math.Max(Proxy.HintWindowsSize * 2, size.Y * 0.5f));
|
||||
var centerX = size.X * 0.5f;
|
||||
var centerY = size.Y * 0.5f;
|
||||
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
|
||||
@@ -294,71 +379,150 @@ namespace FlaxEditor.GUI.Docking
|
||||
DockState toSet = DockState.Float;
|
||||
if (showBorderHints)
|
||||
{
|
||||
if (_rUpper.Contains(_mouse))
|
||||
if (_rUpper.Contains(_toDock.PointFromScreen(_mouse)))
|
||||
{
|
||||
toSet = DockState.DockTop;
|
||||
else if (_rBottom.Contains(_mouse))
|
||||
hoveredHintControl = _dockHintUp;
|
||||
hoveredSizeOverride = new Float2(size.X, hintPreviewSize.Y);
|
||||
}
|
||||
else if (_rBottom.Contains(_toDock.PointFromScreen(_mouse)))
|
||||
{
|
||||
toSet = DockState.DockBottom;
|
||||
else if (_rLeft.Contains(_mouse))
|
||||
hoveredHintControl = _dockHintDown;
|
||||
hoveredSizeOverride = new Float2(size.X, hintPreviewSize.Y);
|
||||
}
|
||||
else if (_rLeft.Contains(_toDock.PointFromScreen(_mouse)))
|
||||
{
|
||||
toSet = DockState.DockLeft;
|
||||
else if (_rRight.Contains(_mouse))
|
||||
hoveredHintControl = _dockHintLeft;
|
||||
hoveredSizeOverride = new Float2(hintPreviewSize.X, size.Y);
|
||||
}
|
||||
else if (_rRight.Contains(_toDock.PointFromScreen(_mouse)))
|
||||
{
|
||||
toSet = DockState.DockRight;
|
||||
hoveredHintControl = _dockHintRight;
|
||||
hoveredSizeOverride = new Float2(hintPreviewSize.X, size.Y);
|
||||
}
|
||||
}
|
||||
if (showCenterHint && _rCenter.Contains(_mouse))
|
||||
if (showCenterHint && _rCenter.Contains(_toDock.PointFromScreen(_mouse)))
|
||||
{
|
||||
toSet = DockState.DockFill;
|
||||
_toSet = toSet;
|
||||
hoveredHintControl = _dockHintCenter;
|
||||
hoveredSizeOverride = new Float2(size.X, size.Y);
|
||||
}
|
||||
|
||||
// Show proxy hint windows
|
||||
Proxy.Down.Position = _rBottom.Location;
|
||||
Proxy.Left.Position = _rLeft.Location;
|
||||
Proxy.Right.Position = _rRight.Location;
|
||||
Proxy.Up.Position = _rUpper.Location;
|
||||
Proxy.Center.Position = _rCenter.Location;
|
||||
if (toSet != DockState.Float)
|
||||
Editor.Log($"docking: {toSet}");
|
||||
|
||||
_toSet = toSet;
|
||||
}
|
||||
else
|
||||
{
|
||||
_toSet = DockState.Float;
|
||||
}
|
||||
|
||||
// Update proxy hint windows visibility
|
||||
Proxy.Down.IsVisible = showProxyHints & showBorderHints;
|
||||
Proxy.Left.IsVisible = showProxyHints & showBorderHints;
|
||||
Proxy.Right.IsVisible = showProxyHints & showBorderHints;
|
||||
Proxy.Up.IsVisible = showProxyHints & showBorderHints;
|
||||
Proxy.Center.IsVisible = showProxyHints & showCenterHint;
|
||||
|
||||
// Calculate proxy/dock/window rectangles
|
||||
if (_toDock == null)
|
||||
{
|
||||
// Floating window over nothing
|
||||
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
|
||||
//_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
|
||||
if (hoveredHintControl != null)
|
||||
hoveredHintControl.BackgroundColor = Color.Green;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hoveredHintControl != _dockHintDown)
|
||||
{
|
||||
_dockHintDown.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintDown.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (hoveredHintControl != _dockHintLeft)
|
||||
{
|
||||
_dockHintLeft.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintLeft.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (hoveredHintControl != _dockHintRight)
|
||||
{
|
||||
_dockHintRight.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintRight.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (hoveredHintControl != _dockHintUp)
|
||||
{
|
||||
_dockHintUp.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintUp.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (hoveredHintControl != _dockHintCenter)
|
||||
{
|
||||
_dockHintCenter.Size = new Float2(Proxy.HintWindowsSize);
|
||||
_dockHintCenter.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
|
||||
}
|
||||
if (_toSet == DockState.Float)
|
||||
{
|
||||
// Floating window over dock panel
|
||||
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
|
||||
if (hoveredHintControl != null)
|
||||
hoveredHintControl.BackgroundColor = Color.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use only part of the dock panel to show hint
|
||||
_rectWindow = CalculateDockRect(_toSet, ref _rectDock);
|
||||
if (hoveredHintControl != null)
|
||||
{
|
||||
hoveredHintControl.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(1.0f);
|
||||
hoveredHintControl.Size = hoveredSizeOverride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showProxyHints)
|
||||
{
|
||||
if (hoveredHintControl != _dockHintDown)
|
||||
_dockHintDown.Location = _rBottom.Location;
|
||||
if (hoveredHintControl != _dockHintLeft)
|
||||
_dockHintLeft.Location = _rLeft.Location;
|
||||
if (hoveredHintControl != _dockHintRight)
|
||||
_dockHintRight.Location = _rRight.Location;
|
||||
if (hoveredHintControl != _dockHintUp)
|
||||
_dockHintUp.Location = _rUpper.Location;
|
||||
if (hoveredHintControl != _dockHintCenter)
|
||||
_dockHintCenter.Location = _rCenter.Location;
|
||||
|
||||
// Update proxy hint windows visibility
|
||||
_dockHintDown.Visible = showProxyHints & showBorderHints;
|
||||
_dockHintLeft.Visible = showProxyHints & showBorderHints;
|
||||
_dockHintRight.Visible = showProxyHints & showBorderHints;
|
||||
_dockHintUp.Visible = showProxyHints & showBorderHints;
|
||||
_dockHintCenter.Visible = showProxyHints & showCenterHint;
|
||||
}
|
||||
|
||||
// Update proxy window
|
||||
Proxy.Window.ClientBounds = _rectWindow;
|
||||
//Proxy.Window.ClientBounds = _rectWindow;
|
||||
}
|
||||
|
||||
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
|
||||
{
|
||||
Editor.Log("DockHintWindow.OnMouseUp");
|
||||
if (button == MouseButton.Left)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseMove(ref Float2 mousePos)
|
||||
private void OnUpdate()
|
||||
{
|
||||
if (_lateDragStartTimer > 0)
|
||||
{
|
||||
_lateDragStartTimer -= Time.UnscaledDeltaTime;
|
||||
if (_lateDragStartTimer <= 0)
|
||||
_toMove.Window.Window.StartDragging(_dragOffset);
|
||||
}
|
||||
var mousePos = Platform.MousePosition;
|
||||
if (_mouse != mousePos)
|
||||
{
|
||||
OnMouseMove(mousePos);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseMove(Float2 mousePos)
|
||||
{
|
||||
// Recalculate the drag offset because the current mouse screen position was invalid when we initialized the window
|
||||
if (_lateDragOffsetUpdate)
|
||||
@@ -377,6 +541,15 @@ namespace FlaxEditor.GUI.Docking
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public class DockHintControl : Control
|
||||
{
|
||||
public DockHintControl()
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll;
|
||||
Offsets = Margin.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains helper proxy windows shared across docking panels. They are used to visualize docking window locations.
|
||||
|
||||
@@ -200,13 +200,16 @@ namespace FlaxEditor.GUI.Docking
|
||||
windowGUI.PerformLayout();
|
||||
|
||||
// Show
|
||||
window.Show();
|
||||
window.BringToFront();
|
||||
window.Focus();
|
||||
OnShow();
|
||||
FlaxEngine.Scripting.InvokeOnUpdate(() =>
|
||||
{
|
||||
window.Show();
|
||||
window.BringToFront();
|
||||
window.Focus();
|
||||
OnShow();
|
||||
|
||||
// Perform layout again
|
||||
windowGUI.PerformLayout();
|
||||
// Perform layout again
|
||||
windowGUI.PerformLayout();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -51,8 +51,9 @@ namespace FlaxEditor.GUI.Docking
|
||||
if (_window == null)
|
||||
return;
|
||||
|
||||
_window.Window.StartDragging(Float2.Zero);
|
||||
// Create docking hint window
|
||||
DockHintWindow.Create(this);
|
||||
//DockHintWindow.Create(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// <summary>
|
||||
/// Performs hit test over dock panel.
|
||||
/// </summary>
|
||||
/// <param name="position">Screen space position to test.</param>
|
||||
/// <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>
|
||||
/// <returns>Dock panel that has been hit or null if nothing found.</returns>
|
||||
public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded)
|
||||
@@ -87,13 +87,39 @@ namespace FlaxEditor.GUI.Docking
|
||||
var win = FloatingPanels[i];
|
||||
if (win.Visible && win != excluded)
|
||||
{
|
||||
var result = win.HitTest(ref position);
|
||||
if (result != null)
|
||||
return result;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Base
|
||||
if (!Root?.RootWindow.Window.IsFocused ?? false)
|
||||
return null;
|
||||
return base.HitTest(ref position);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user