1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-14 14:24:10 +02:00

Ctrl+Alt+Up/Down support, QuickFind Ctrl+D fixes

This commit is contained in:
Brian Fiete 2025-05-26 14:44:51 +02:00
parent 2ce4ec2e3f
commit adb7a2bdef
8 changed files with 259 additions and 110 deletions

View file

@ -68,6 +68,7 @@ namespace Beefy.theme.dark
public Range? mLineRange;
protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _;
public static bool sDebugMultiCursor;
public float LineHeight => Math.Max(Math.Round(mFont.GetLineSpacing() * mLineHeightScale), 1);
@ -573,7 +574,7 @@ namespace Beefy.theme.dark
bool drewCursor = false;
void DrawCursor(float x, float y)
void DrawCursor(float x, float y, bool isSecondary = false)
{
if (mHiliteCurrentLine && selStartIdx == selEndIdx)
{
@ -618,8 +619,18 @@ namespace Beefy.theme.dark
}
else
{
float cursorY = y + textYOffset;
float cursorHeight = fontLineSpacing;
float cursorWidth = Math.Max(1.0f, GS!(1));
if ((sDebugMultiCursor) && (mTextCursors.Count > 1))
{
if (isSecondary)
cursorColor.A = (.)(cursorColor.A * 0.5f);
}
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness))))
g.FillRect(x, y + textYOffset, Math.Max(1.0f, GS!(1)), fontLineSpacing);
g.FillRect(x, cursorY, cursorWidth, cursorHeight);
}
drewCursor = true;
}
@ -859,8 +870,7 @@ namespace Beefy.theme.dark
y = mLineCoords[eStartLine];
}
using (g.PushColor(0xFF80FFB3))
DrawCursor(x, y);
DrawCursor(x, y, true);
}
SetTextCursor(prevTextCursor);
}

View file

@ -2801,9 +2801,11 @@ namespace Beefy.widgets
}
}
public override void KeyDown(KeyCode keyCode, bool isRepeat)
public virtual void HandleKey(KeyCode keyCode, KeyFlags keyFlags, bool isRepeat)
{
base.KeyDown(keyCode, isRepeat);
bool shiftDown = keyFlags.HasFlag(.Shift);
bool ctrlDown = keyFlags.HasFlag(.Ctrl);
bool altDown = keyFlags.HasFlag(.Alt);
if (keyCode == KeyCode.Escape)
{
@ -2871,7 +2873,7 @@ namespace Beefy.widgets
{
bool doVirtualMove = true;
if ((mWidgetWindow.IsKeyDown(KeyCode.Shift)) || (mWidgetWindow.IsKeyDown(KeyCode.Control)))
if ((shiftDown) || (ctrlDown))
doVirtualMove = false;
else
{
@ -2907,7 +2909,7 @@ namespace Beefy.widgets
wasMoveKey = true;
SelectLeft(lineIdx, lineChar, mWidgetWindow.IsKeyDown(KeyCode.Control), mWidgetWindow.IsKeyDown(KeyCode.Alt));
SelectLeft(lineIdx, lineChar, ctrlDown, altDown);
}
}
break;
@ -2919,7 +2921,7 @@ namespace Beefy.widgets
{
bool doVirtualMove = true;
if ((mWidgetWindow.IsKeyDown(KeyCode.Shift)) || (mWidgetWindow.IsKeyDown(KeyCode.Control)))
if ((shiftDown) || (ctrlDown))
doVirtualMove = false;
else
{
@ -2947,7 +2949,7 @@ namespace Beefy.widgets
}
wasMoveKey = true;
SelectRight(lineIdx, lineChar, mWidgetWindow.IsKeyDown(KeyCode.Control), mWidgetWindow.IsKeyDown(KeyCode.Alt));
SelectRight(lineIdx, lineChar, ctrlDown, altDown);
}
}
break;
@ -2956,7 +2958,8 @@ namespace Beefy.widgets
case KeyCode.Down:
{
int32 aDir = (keyCode == KeyCode.Up) ? -1 : 1;
if ((HasSelection()) && (!mWidgetWindow.IsKeyDown(KeyCode.Shift)))
if ((HasSelection()) && (!shiftDown))
{
if (mAllowVirtualCursor)
{
@ -2972,7 +2975,7 @@ namespace Beefy.widgets
GetCursorLineChar(out lineIdx, out lineChar);
if (mWidgetWindow.IsKeyDown(KeyCode.Control))
if (ctrlDown)
{
mEditWidget.VertScrollTo(mEditWidget.mVertPos.mDest + aDir * mEditWidget.mScrollContentContainer.mHeight * 0.25f);
EnsureCursorVisible(false);
@ -3028,7 +3031,7 @@ namespace Beefy.widgets
case KeyCode.Home:
PrepareForCursorMove(-1);
wasMoveKey = true;
if (mWidgetWindow.IsKeyDown(KeyCode.Control))
if (ctrlDown)
CursorToStart();
else
CursorToLineStart(true);
@ -3037,7 +3040,7 @@ namespace Beefy.widgets
case KeyCode.End:
PrepareForCursorMove(1);
wasMoveKey = true;
if (mWidgetWindow.IsKeyDown(KeyCode.Control))
if (ctrlDown)
{
CursorToEnd();
}
@ -3185,7 +3188,7 @@ namespace Beefy.widgets
if (wasMoveKey)
{
if (mWidgetWindow.IsKeyDown(KeyCode.Shift))
if (shiftDown)
{
if (!HasSelection())
{
@ -3201,6 +3204,12 @@ namespace Beefy.widgets
}
}
public override void KeyDown(KeyCode keyCode, bool isRepeat)
{
base.KeyDown(keyCode, isRepeat);
HandleKey(keyCode, mWidgetWindow.GetKeyFlags(true), isRepeat);
}
public float GetCursorScreenRelY()
{
float cursorX;
@ -4350,7 +4359,7 @@ namespace Beefy.widgets
return !((lhsSelection.mEndPos <= rhsSelection.mStartPos) || (rhsSelection.mEndPos <= lhsSelection.mStartPos));
}
public void AddSelectionToNextFindMatch(bool createCursor = true, bool exhaustiveSearch = false)
public virtual void AddSelectionToNextFindMatch(bool createCursor = true, bool exhaustiveSearch = false)
{
SetPrimaryTextCursor();
@ -4432,6 +4441,38 @@ namespace Beefy.widgets
{
AddSelectionToNextFindMatch(createCursor: false);
}
public void AddMultiCursor(int32 dir)
{
var refTextCursor = mCurrentTextCursor;
var refTextPos = CursorTextPos;
for (var cursor in mTextCursors)
{
SetTextCursor(cursor);
var textPos = CursorTextPos;
if (Math.Sign(textPos <=> refTextPos) == dir)
{
refTextCursor = cursor;
refTextPos = textPos;
}
}
var newCursor = new TextCursor(-1, refTextCursor);
mTextCursors.Add(newCursor);
SetTextCursor(mTextCursors.Back);
var startCursorPos = CursorLineAndColumn;
HandleKey((dir < 0) ? .Up : .Down, .None, false);
bool moved = startCursorPos != CursorLineAndColumn;
SetPrimaryTextCursor();
if (!moved)
{
mTextCursors.Remove(newCursor);
delete newCursor;
}
}
}
public abstract class EditWidget : ScrollableWidget

View file

@ -194,6 +194,9 @@ namespace IDE
public void Init()
{
Add("About", new => gApp.ShowAbout);
Add("Add Selection to Next Find Match", new => gApp.Cmd_AddSelectionToNextFindMatch);
Add("Add Cursor Above", new => gApp.Cmd_AddCursorAbove);
Add("Add Cursor Below", new => gApp.Cmd_AddCursorBelow);
Add("Autocomplete", new => gApp.Cmd_ShowAutoComplete, .None);
Add("Bookmark Next", new => gApp.Cmd_NextBookmark, .Editor);
Add("Bookmark Prev", new => gApp.Cmd_PrevBookmark, .Editor);
@ -340,7 +343,6 @@ namespace IDE
Add("Zoom Out", new => gApp.Cmd_ZoomOut);
Add("Zoom Reset", new => gApp.Cmd_ZoomReset);
Add("Attach to Process", new => gApp.[Friend]DoAttach);
Add("Add Selection to Next Find Match", new => gApp.Cmd_AddSelectionToNextFindMatch);
Add("Move Last Selection to Next Find Match", new => gApp.Cmd_MoveLastSelectionToNextFindMatch);
Add("Test Enable Console", new => gApp.Cmd_TestEnableConsole);

View file

@ -5965,13 +5965,25 @@ namespace IDE
[IDECommand]
public void Cmd_AddSelectionToNextFindMatch()
{
GetActiveSourceEditWidgetContent()?.AddSelectionToNextFindMatch();
GetActiveSourceViewPanel()?.AddSelectionToNextFindMatch();
}
[IDECommand]
public void Cmd_MoveLastSelectionToNextFindMatch()
{
GetActiveSourceEditWidgetContent()?.MoveLastSelectionToNextFindMatch();
GetActiveSourceViewPanel()?.MoveLastSelectionToNextFindMatch();
}
[IDECommand]
public void Cmd_AddCursorAbove()
{
GetActiveSourceEditWidgetContent()?.AddMultiCursor(-1);
}
[IDECommand]
public void Cmd_AddCursorBelow()
{
GetActiveSourceEditWidgetContent()?.AddMultiCursor(1);
}
public void UpdateMenuItem_HasActivePanel(IMenu menu)
@ -8574,11 +8586,6 @@ namespace IDE
void SysKeyDown(KeyDownEvent evt)
{
if (evt.mKeyCode != .Alt)
{
NOP!();
}
if (!evt.mKeyFlags.HeldKeys.HasFlag(.Alt))
{
#if BF_PLATFORM_WINDOWS
@ -8756,6 +8763,13 @@ namespace IDE
break;
}
}
if ((evt.mKeyCode == .Return) && (evt.mKeyFlags.HasFlag(.Alt)))
{
// Don't "beep" for any Enter key combinations
window.mFocusWidget?.KeyDown(evt);
evt.mHandled = true;
}
}
void SysKeyUp(KeyCode keyCode)

View file

@ -859,6 +859,8 @@ namespace IDE
public void SetDefaults()
{
Add("Add Cursor Above", "Ctrl+Alt+Up");
Add("Add Cursor Below", "Ctrl+Alt+Down");
Add("Add Selection to Next Find Match", "Ctrl+D");
Add("Autocomplete", "Ctrl+Space");
Add("Bookmark Next", "F2");
@ -1255,7 +1257,7 @@ namespace IDE
{
sd.Add("WakaTimeKey", mWakaTimeKey);
sd.Add("EnableDevMode", mEnableDevMode);
sd.Add("DebugMultiCursor", mEditorSettings.mDebugMultiCursor);
sd.Add("DebugMultiCursor", DarkEditWidgetContent.sDebugMultiCursor);
}
using (sd.CreateObject("TutorialsFinished"))
@ -1356,7 +1358,7 @@ namespace IDE
{
sd.Get("WakaTimeKey", mWakaTimeKey);
sd.Get("EnableDevMode", ref mEnableDevMode);
sd.Get("DebugMultiCursor", ref mEditorSettings.mDebugMultiCursor);
sd.Get("DebugMultiCursor", ref DarkEditWidgetContent.sDebugMultiCursor);
}
using (sd.Open("TutorialsFinished"))

View file

@ -87,12 +87,12 @@ namespace IDE.ui
bool mFoundMatches;
public bool mIsShowingMatches = false;
static String sLastSearchString = new String() ~ delete _;
public List<Range> mFoundRanges = new .() ~ delete _;
public bool mOwnsSelection;
PersistentTextPosition mSelectionStart ~ { Debug.Assert(_ == null); };
PersistentTextPosition mSelectionEnd ~ { Debug.Assert(_ == null); };
public this(Widget parent, EditWidget editWidget, bool isReplace)
{
mPanel = parent as TextPanel;
@ -394,6 +394,7 @@ namespace IDE.ui
mCurFindCount = 0;
//mSearchDidWrap = false;
mFoundRanges.Clear();
ClearFlags(true, true);
if (mSelectionStart != null)
{
@ -404,10 +405,21 @@ namespace IDE.ui
}
}
bool DoFindNext(bool select)
{
if (var range = FindNext(1, select, ErrorReportType.None))
{
mFoundRanges.Add(range);
return true;
}
return false;
}
if (doSelect)
FindNext(1, true, ErrorReportType.None);
DoFindNext(true);
int32 curFindIdx = mCurFindIdx;
while (FindNext(1, false, ErrorReportType.None))
while (DoFindNext(false))
{
}
mCurFindIdx = curFindIdx;
@ -483,7 +495,7 @@ namespace IDE.ui
return;
}
if (FindNext(dir, true, showMessage ? ErrorReportType.MessageBox : ErrorReportType.Sound))
if (FindNext(dir, true, showMessage ? ErrorReportType.MessageBox : ErrorReportType.Sound) case .Ok)
{
ShowCurrentSelection();
}
@ -506,7 +518,7 @@ namespace IDE.ui
}
}
public bool FindNext(int32 dir, bool isSelection, ErrorReportType errorType)
public Result<Range> FindNext(int32 dir, bool isSelection, ErrorReportType errorType)
{
var editContent = mEditWidget.Content;
@ -514,7 +526,7 @@ namespace IDE.ui
mFindEditWidget.GetText(findText);
sLastSearchString.Set(findText);
if (findText.Length == 0)
return false;
return .Err;
String findTextLower = scope String(findText);
findTextLower.ToLower();
@ -610,7 +622,7 @@ namespace IDE.ui
mCurFindIdx = mCurFindStart + 1;
mCurFindCount = 0;
return false;
return .Err;
}
}
else
@ -623,7 +635,7 @@ namespace IDE.ui
mCurFindIdx = mCurFindStart - 1;
mCurFindCount = 0;
return false;
return .Err;
}
}
@ -646,7 +658,7 @@ namespace IDE.ui
}
mCurFindIdx = nextIdx;
return true;
return Range(mCurFindIdx, mCurFindIdx + findText.Length);
}
else
{
@ -668,7 +680,7 @@ namespace IDE.ui
ShowDoneError(errorType);
mCurFindCount = 0;
}
return false;
return .Err;
}
mCurFindIdx = -1;

View file

@ -4622,11 +4622,12 @@ namespace IDE.ui
}
}
/// summary = "Hey This is a summary"
/// param.keyCode = "Keycode of pressed key"
/// param.isRepeat = "Whether the key is repeated"
public override void KeyDown(KeyCode keyCode, bool isRepeat)
public override void HandleKey(KeyCode keyCode, KeyFlags keyFlags, bool isRepeat)
{
bool shiftDown = keyFlags.HasFlag(.Shift);
bool ctrlDown = keyFlags.HasFlag(.Ctrl);
bool altDown = keyFlags.HasFlag(.Alt);
mIgnoreKeyChar = false;
mEmbedSelected = null;
@ -4638,7 +4639,7 @@ namespace IDE.ui
(autoCompleteRequireControl) &&
(!gApp.mSettings.mTutorialsFinished.mCtrlCursor))
{
if (mWidgetWindow.IsKeyDown(.Control))
if (ctrlDown)
{
if ((DarkTooltipManager.sTooltip != null) && (DarkTooltipManager.sTooltip.mAllowMouseOutside))
DarkTooltipManager.CloseTooltip();
@ -4692,7 +4693,7 @@ namespace IDE.ui
if (((keyCode == KeyCode.Up) || (keyCode == KeyCode.Down) || (keyCode == KeyCode.PageUp) || (keyCode == KeyCode.PageDown)))
{
if ((IsPrimaryTextCursor()) && ((!autoCompleteRequireControl) || (mWidgetWindow.IsKeyDown(KeyCode.Control))))
if ((IsPrimaryTextCursor()) && ((!autoCompleteRequireControl) || (ctrlDown)))
{
if ((mAutoComplete != null) && (mAutoComplete.IsShowing()))
{
@ -4732,7 +4733,7 @@ namespace IDE.ui
}
// Disabled window-scroll code for ctrl+up/ctrl+down when autocomplete is not up
if (mWidgetWindow.IsKeyDown(KeyCode.Control))
if (ctrlDown)
return;
}
@ -4765,7 +4766,7 @@ namespace IDE.ui
if (wantCursorPos != -1)
{
if (mWidgetWindow.IsKeyDown(.Shift))
if (shiftDown)
{
if (CurSelection == null)
CurSelection = .(CursorTextPos, wantCursorPos);
@ -4785,7 +4786,7 @@ namespace IDE.ui
int prevCursorPos;
TryGetCursorTextPos(out prevCursorPos);
int prevTextLength = mData.mTextLength;
base.KeyDown(keyCode, isRepeat);
base.HandleKey(keyCode, keyFlags, isRepeat);
if ((IsPrimaryTextCursor()) && (mAutoComplete != null) &&
(keyCode != .Control) &&

View file

@ -188,6 +188,20 @@ namespace IDE.ui
return base.WantsUnfocus();
}
public override void KeyDown(KeyDownEvent keyEvent)
{
if (keyEvent.mKeyCode == .Escape)
{
if (mPanel.mQuickFind.mWidgetWindow != null)
{
mPanel.mQuickFind.Close();
return;
}
}
base.KeyDown(keyEvent);
}
}
public class TrackedTextElementView
@ -7743,5 +7757,58 @@ namespace IDE.ui
mExplicitEmitTypes.Add(new .(typeName));
return true;
}
public void AddSelectionToNextFindMatch(bool createCursor = true, bool exhaustiveSearch = false)
{
var ewc = mEditWidget.mEditWidgetContent as SourceEditWidgetContent;
if (mQuickFind != null)
{
int usedCursorCount = 0;
for (var range in mQuickFind.mFoundRanges)
{
EditWidgetContent.TextCursor cursor = null;
if (@range.Index < ewc.mTextCursors.Count)
{
cursor = ewc.mTextCursors[@range.Index];
}
else
{
cursor = new EditWidgetContent.TextCursor(-1);
ewc.mTextCursors.Add(cursor);
}
usedCursorCount++;
EditSelection wantSel = .(range.Start, range.End);
if (wantSel == cursor.mSelection)
continue;
cursor.mCursorTextPos = (.)range.End;
cursor.mSelection = wantSel;
break;
}
if (usedCursorCount > 0)
{
while (ewc.mTextCursors.Count > usedCursorCount)
{
var cursor = ewc.mTextCursors.PopBack();
delete cursor;
}
}
mEditWidget.SetFocus();
return;
}
ewc.AddSelectionToNextFindMatch(createCursor, exhaustiveSearch);
}
public void MoveLastSelectionToNextFindMatch()
{
var ewc = mEditWidget.mEditWidgetContent as SourceEditWidgetContent;
ewc.MoveLastSelectionToNextFindMatch();
}
}
}