Skip to content

Commit 6361095

Browse files
committed
Fix moving ICanvasElement while InlineEditor is running
1 parent 2e07b87 commit 6361095

5 files changed

Lines changed: 148 additions & 180 deletions

File tree

COMPILATION_FIXES.md

Lines changed: 0 additions & 169 deletions
This file was deleted.

src/XTMF2.GUI/Controls/ModelSystemCanvas.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ public ModelSystemCanvas()
398398
// ── Resize drag state ─────────────────────────────────────────────────
399399
/// <summary>The canvas element being resized, or <c>null</c> when not resizing.</summary>
400400
private ICanvasElement? _resizing;
401+
/// <summary><c>true</c> while a drag or resize operation is in progress (used to prevent inline editor close on focus loss).</summary>
402+
private bool _inDragOrResize;
401403
/// <summary>Pointer position at the start of the resize drag.</summary>
402404
private Point _resizeStartPos;
403405
/// <summary>Node rendered width at the start of the resize drag.</summary>

src/XTMF2.GUI/Controls/ModelSystemCanvas/ModelSystemCanvas.Input.cs

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,20 @@ private void OnPointerPressedTunnel(object? sender, PointerPressedEventArgs e)
260260
var resizeHit = HitTestResizeHandle(mpos);
261261
if (resizeHit is null) return;
262262

263-
// Commit any open editor so its LostFocus handler doesn't fire after
264-
// we capture the pointer, which would interfere with the resize drag.
265-
if (_editingParamNode is not null) CommitParamEdit();
266-
if (_editingCommentBlock is not null) CommitCommentEdit();
267-
if (_editingNameElement is not null) CommitNameEdit();
263+
// Don't commit open editors if we're resizing the element being edited.
264+
// The _inDragOrResize flag will prevent LostFocus handlers from closing them,
265+
// and SyncEditingElementPositions() will keep them synchronized during the resize.
266+
bool isResizingEditedElement =
267+
ReferenceEquals(resizeHit, _editingParamNode) ||
268+
ReferenceEquals(resizeHit, _editingNameElement) ||
269+
ReferenceEquals(resizeHit, _editingCommentBlock);
270+
271+
if (!isResizingEditedElement)
272+
{
273+
if (_editingParamNode is not null) CommitParamEdit();
274+
if (_editingCommentBlock is not null) CommitCommentEdit();
275+
if (_editingNameElement is not null) CommitNameEdit();
276+
}
268277

269278
ClearMultiSelection();
270279
_resizing = resizeHit;
@@ -307,9 +316,18 @@ protected override void OnPointerPressed(PointerPressedEventArgs e)
307316
var resizeHit = HitTestResizeHandle(mpos);
308317
if (resizeHit is not null)
309318
{
310-
if (_editingParamNode is not null) CommitParamEdit();
311-
if (_editingCommentBlock is not null) CommitCommentEdit();
312-
if (_editingNameElement is not null) CommitNameEdit();
319+
// Don't commit editors if we're resizing the element being edited.
320+
bool isResizingEditedElement =
321+
ReferenceEquals(resizeHit, _editingParamNode) ||
322+
ReferenceEquals(resizeHit, _editingNameElement) ||
323+
ReferenceEquals(resizeHit, _editingCommentBlock);
324+
325+
if (!isResizingEditedElement)
326+
{
327+
if (_editingParamNode is not null) CommitParamEdit();
328+
if (_editingCommentBlock is not null) CommitCommentEdit();
329+
if (_editingNameElement is not null) CommitNameEdit();
330+
}
313331
ClearMultiSelection();
314332
_resizing = resizeHit;
315333
_resizeStartPos = mpos;
@@ -365,11 +383,26 @@ protected override void OnPointerPressed(PointerPressedEventArgs e)
365383
// Clicking elsewhere commits any open edit.
366384
// Guard: if the click was already handled by a child (e.g. the variable
367385
// autocomplete dropdown's TextBlock items), do not commit the edit.
386+
// Also: if we're about to drag one of the edited elements, keep the editor open.
368387
if (!e.Handled)
369388
{
370-
if (_editingParamNode is not null) CommitParamEdit();
371-
if (_editingCommentBlock is not null) CommitCommentEdit();
372-
if (_editingNameElement is not null) CommitNameEdit();
389+
var clickedElement = HitTest(mpos, testComments: false);
390+
bool isDraggingEditedElement =
391+
ReferenceEquals(clickedElement, _editingParamNode) ||
392+
ReferenceEquals(clickedElement, _editingNameElement) ||
393+
ReferenceEquals(clickedElement, _editingCommentBlock) ||
394+
(clickedElement is not null && _multiSelection.Contains(clickedElement) &&
395+
((_editingParamNode is not null && _multiSelection.Contains(_editingParamNode)) ||
396+
(_editingNameElement is not null && _multiSelection.Contains(_editingNameElement)) ||
397+
(_editingCommentBlock is not null && _multiSelection.Contains(_editingCommentBlock))));
398+
399+
// Only commit if we're not about to drag one of the edited elements.
400+
if (!isDraggingEditedElement)
401+
{
402+
if (_editingParamNode is not null) CommitParamEdit();
403+
if (_editingCommentBlock is not null) CommitCommentEdit();
404+
if (_editingNameElement is not null) CommitNameEdit();
405+
}
373406
}
374407
}
375408

@@ -632,9 +665,17 @@ protected override void OnPointerMoved(PointerEventArgs e)
632665
// ── Resize drag ───────────────────────────────────────────────────
633666
if (_resizing is not null)
634667
{
668+
_inDragOrResize = true;
635669
var dw = mpos.X - _resizeStartPos.X;
636670
var dh = mpos.Y - _resizeStartPos.Y;
637671
_resizing.ResizeToPreview(_resizeStartW + dw, _resizeStartH + dh);
672+
// Only sync inline editor if it's the element being resized
673+
if (ReferenceEquals(_resizing, _editingParamNode) ||
674+
ReferenceEquals(_resizing, _editingNameElement) ||
675+
ReferenceEquals(_resizing, _editingCommentBlock))
676+
{
677+
SyncEditingElementPositions();
678+
}
638679
InvalidateAndMeasure();
639680
e.Handled = true;
640681
return;
@@ -675,6 +716,7 @@ protected override void OnPointerMoved(PointerEventArgs e)
675716
if (_dragging is null) return;
676717

677718
// ── Element drag (single or group) ────────────────────────────────
719+
_inDragOrResize = true;
678720
if (_multiSelection.Count > 1 && _multiSelection.Contains(_dragging))
679721
{
680722
// Group drag: preview every element in the multi-selection by the per-frame delta.
@@ -696,6 +738,22 @@ protected override void OnPointerMoved(PointerEventArgs e)
696738
_dragging.MoveToPreview(newX, newY);
697739
}
698740

741+
// Only sync inline editor if it's being dragged as part of the current drag operation
742+
if (_multiSelection.Count > 1)
743+
{
744+
if ((_editingParamNode is not null && _multiSelection.Contains(_editingParamNode)) ||
745+
(_editingNameElement is not null && _multiSelection.Contains(_editingNameElement)) ||
746+
(_editingCommentBlock is not null && _multiSelection.Contains(_editingCommentBlock)))
747+
{
748+
SyncEditingElementPositions();
749+
}
750+
}
751+
else if (ReferenceEquals(_dragging, _editingParamNode) ||
752+
ReferenceEquals(_dragging, _editingNameElement) ||
753+
ReferenceEquals(_dragging, _editingCommentBlock))
754+
{
755+
SyncEditingElementPositions();
756+
}
699757
InvalidateAndMeasure();
700758
TryAutoScrollForDrag(svPos);
701759
e.Handled = true;
@@ -733,6 +791,9 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e)
733791
}
734792
}
735793

794+
// ── Drag/resize release ──────────────────────────────────────────────
795+
_inDragOrResize = false;
796+
736797
// ── Right-drag release: complete link creation ────────────────────
737798
if (_linkOrigin is not null)
738799
{

src/XTMF2.GUI/Controls/ModelSystemCanvas/ModelSystemCanvas.NameCommentEditing.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ private void OnNameEditorKeyDown(object? sender, KeyEventArgs e)
146146

147147
private void OnNameEditorLostFocus(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
148148
{
149+
// Don't commit if we're in the middle of a drag/resize operation.
150+
if (_inDragOrResize) return;
151+
149152
if (_editingNameElement is not null)
150153
{
151154
CommitNameEdit();
@@ -240,6 +243,9 @@ private void OnCommentEditorKeyDown(object? sender, KeyEventArgs e)
240243

241244
private void OnCommentEditorLostFocus(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
242245
{
246+
// Don't commit if we're in the middle of a drag/resize operation.
247+
if (_inDragOrResize) return;
248+
243249
if (_editingCommentBlock is not null)
244250
{
245251
CommitCommentEdit();

0 commit comments

Comments
 (0)