Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 95 additions & 50 deletions BeefLibs/Beefy2D/src/widgets/EditWidget.bf
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ namespace Beefy.widgets
{
GetLineCharAtCoord(x, y, var line, var lineChar, ?);
int textPos = GetTextIdx(line, lineChar);
if ((textPos > CurSelection.Value.MinPos) && (textPos < CurSelection.Value.MaxPos))
if (GetTextCursorAtIdx(textPos) != null)
{
// Leave selection
mDragSelectionKind = .ClickedInside;
Expand Down Expand Up @@ -4314,52 +4314,6 @@ namespace Beefy.widgets
return (lhsSelection.mStartPos <=> rhsSelection.mStartPos);
}

public void RemoveIntersectingTextCursors()
{
if (mTextCursors.Count == 1)
return;

for (var x = mTextCursors.Count-1; x >= 0; x--)
{
for (var y = mTextCursors.Count-1; y >= 0; y--)
{
if (x == y)
continue;

var lhs = mTextCursors[x];
var rhs = mTextCursors[y];

if (TextCursorsIntersects(lhs, rhs))
{
if (lhs.mId != 0)
{
delete mTextCursors[x];
mTextCursors.RemoveAt(x);
}
else
{
delete mTextCursors[y];
mTextCursors.RemoveAt(y);
}

break;
}
}
}
}

public bool TextCursorsIntersects(TextCursor lhs, TextCursor rhs)
{
// Returns true if two text cursors intersect or collide with each other
var lhsSelection = GetAsSelection(lhs, true);
var rhsSelection = GetAsSelection(rhs, true);

if (lhsSelection.mStartPos == rhsSelection.mStartPos)
return true;

return !((lhsSelection.mEndPos <= rhsSelection.mStartPos) || (rhsSelection.mEndPos <= lhsSelection.mStartPos));
}

public virtual void AddSelectionToNextFindMatch(bool createCursor = true, bool exhaustiveSearch = false)
{
SetPrimaryTextCursor();
Expand Down Expand Up @@ -4474,6 +4428,98 @@ namespace Beefy.widgets
delete newCursor;
}
}

public void MergeIntersectingTextCursors()
{
if (mTextCursors.Count == 1)
return;

var primarySelection = GetAsSelection(mTextCursors.Front, false);
var direction = (primarySelection.mStartPos <= primarySelection.mEndPos)
? +1 : -1;

for (var x = mTextCursors.Count-1; x >= 0; x--)
{
var lhs = mTextCursors[x];
var lhsSelection = GetAsSelection(lhs, true);

for (var y = mTextCursors.Count-1; y >= 0; y--)
{
if (x == y)
continue;

var rhs = mTextCursors[y];
var rhsSelection = GetAsSelection(rhs, true);

if (TextCursorsIntersect(lhsSelection, rhsSelection))
{
if (lhs.mId != 0)
{
MergeTextCursors(rhs, rhsSelection, lhs, lhsSelection, direction);
delete lhs;
mTextCursors.RemoveAt(x);
break;
}
else
{
MergeTextCursors(lhs, lhsSelection, rhs, rhsSelection, direction);
delete rhs;
mTextCursors.RemoveAt(y);
}
}
}

if (mTextCursors.Count == 1)
break;
}
}

public bool TextCursorsIntersect(EditSelection lhs, EditSelection rhs)
{
// Selections expected to be forward
Debug.Assert(lhs.mStartPos <= lhs.mEndPos);
Debug.Assert(rhs.mStartPos <= rhs.mEndPos);

if ((!lhs.HasSelection) || (!rhs.HasSelection))
{
if ((lhs.mStartPos == rhs.mStartPos) || (lhs.mEndPos == rhs.mEndPos))
return true;
}

return !((lhs.mEndPos <= rhs.mStartPos) || (rhs.mEndPos <= lhs.mStartPos));
}

void MergeTextCursors(TextCursor lhs, EditSelection lhsSelection, TextCursor rhs, EditSelection rhsSelection, int direction)
{
var startPos = Math.Min(lhsSelection.mStartPos, rhsSelection.mStartPos);
var endPos = Math.Max(lhsSelection.mEndPos, rhsSelection.mEndPos);

if (direction == -1)
Swap!(startPos, endPos);

lhs.mSelection = EditSelection(startPos, endPos);
lhs.mVirtualCursorPos = null;
lhs.mCursorTextPos = endPos;
lhs.mCursorImplicitlyMoved = false;
lhs.mJustInsertedCharPair = false;

if (mDragSelectionKind != .None)
mDragSelectionKind = .Dragging;
}

public TextCursor GetTextCursorAtIdx(int idx)
{
for (var cursor in mTextCursors)
{
if (!cursor.mSelection.HasValue)
continue;

if ((idx > cursor.mSelection.Value.MinPos) && (idx < cursor.mSelection.Value.MaxPos))
return cursor;
}

return null;
}
}

public abstract class EditWidget : ScrollableWidget
Expand Down Expand Up @@ -4680,8 +4726,6 @@ namespace Beefy.widgets
isSingleInvoke = true;
}

ewc.RemoveIntersectingTextCursors();

for (var cursor in ewc.mTextCursors)
{
ewc.SetTextCursor(cursor);
Expand All @@ -4690,14 +4734,15 @@ namespace Beefy.widgets
break;
}

ewc.MergeIntersectingTextCursors();
ewc.SetPrimaryTextCursor();
ewc.CloseMultiCursorUndoBatch();
}

public override void KeyChar(KeyCharEvent keyEvent)
{
var ewc = Content;
ewc.RemoveIntersectingTextCursors();
ewc.MergeIntersectingTextCursors();
for (var cursor in ewc.mTextCursors)
{
ewc.SetTextCursor(cursor);
Expand Down