From d46383216858b8268b73eb47ed8728f63c850daa Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 13 Jun 2020 15:55:08 -0700 Subject: [PATCH] Added more editor keys and commands --- BeefLibs/Beefy2D/src/widgets/EditWidget.bf | 212 +++++++++++++++------ IDE/src/Commands.bf | 3 + IDE/src/IDEApp.bf | 24 +++ IDE/src/Settings.bf | 3 + IDE/src/ui/SourceEditWidgetContent.bf | 62 +++--- 5 files changed, 217 insertions(+), 87 deletions(-) diff --git a/BeefLibs/Beefy2D/src/widgets/EditWidget.bf b/BeefLibs/Beefy2D/src/widgets/EditWidget.bf index 393446ee..91d86a5e 100644 --- a/BeefLibs/Beefy2D/src/widgets/EditWidget.bf +++ b/BeefLibs/Beefy2D/src/widgets/EditWidget.bf @@ -1668,10 +1668,30 @@ namespace Beefy.widgets return (int32)Math.Round(mTabSize / mCharWidth); } - public override void KeyChar(char32 theChar) + public override void KeyChar(char32 keyChar) { - base.KeyChar(theChar); - char32 useChar = theChar; + base.KeyChar(keyChar); + + if (keyChar == '\x7F') // Ctrl+Backspace + { + int line; + int lineChar; + GetCursorLineChar(out line, out lineChar); + + int startIdx = CursorTextPos; + SelectLeft(line, lineChar, true, false); + mSelection = EditSelection(CursorTextPos, startIdx); + + var action = new DeleteSelectionAction(this); + action.mMoveCursor = true; + mData.mUndoManager.Add(action); + action.mCursorTextPos = (.)startIdx; + PhysDeleteSelection(true); + + return; + } + + char32 useChar = keyChar; mCursorBlinkTicks = 0; @@ -2043,6 +2063,65 @@ namespace Beefy.widgets } } + protected void SelectRight(int lineIdx, int lineChar, bool isChunkMove, bool isWordMove) + { + var lineIdx; + var lineChar; + + int anIndex = GetTextIdx(lineIdx, lineChar); + char8 prevC = 0; + CharType prevCharType = (anIndex < mData.mTextLength) ? GetCharType((char8)mData.mText[anIndex].mChar) : .Unknown; + while (true) + { + int lineStart; + int lineEnd; + GetLinePosition(lineIdx, out lineStart, out lineEnd); + int lineLen = lineEnd - lineStart; + + int nextLineChar = lineChar + 1; + bool isWithinLine = nextLineChar < lineLen; + if (nextLineChar == lineLen) + { + GetTextData(); + if ((mData.mTextFlags == null) || ((mData.mTextFlags[lineEnd] & (int32)TextFlags.Wrap) == 0)) + { + isWithinLine = true; + } + } + + if (isWithinLine) + MoveCursorTo(lineIdx, lineChar + 1, false, 1); + else if (lineIdx < GetLineCount() - 1) + MoveCursorTo(lineIdx + 1, 0); + + if (!mWidgetWindow.IsKeyDown(KeyCode.Control)) + break; + + GetLineCharAtIdx(CursorTextPos, out lineIdx, out lineChar); + anIndex = GetTextIdx(lineIdx, lineChar); + if (anIndex == mData.mTextLength) + break; + + char8 c = (char8)mData.mText[anIndex].mChar; + CharType char8Type = GetCharType(c); + if (char8Type == .Opening) + break; + if (char8Type != prevCharType) + { + if ((char8Type != .WhiteSpace) && (prevCharType == .WhiteSpace)) + break; + if ((char8Type == .NewLine) || (char8Type == .NonBreaking) || (char8Type == .Other)) + break; + } + + if ((isWordMove) && (c.IsUpper) && (prevC.IsLower)) + break; + + prevCharType = char8Type; + prevC = c; + } + } + public override void KeyDown(KeyCode keyCode, bool isRepeat) { base.KeyDown(keyCode, isRepeat); @@ -2062,21 +2141,21 @@ namespace Beefy.widgets int prevCursorPos; bool gotCursorPos = TryGetCursorTextPos(out prevCursorPos); - if (mWidgetWindow.GetKeyFlags() == KeyFlags.Ctrl) + if (mWidgetWindow.GetKeyFlags() == .Ctrl) { switch (keyCode) { - case (KeyCode)'A': + case (.)'A': SelectAll(); - case (KeyCode)'C': + case (.)'C': CopyText(); - case (KeyCode)'X': + case (.)'X': CutText(); - case (KeyCode)'V': + case (.)'V': PasteText(); - case (KeyCode)'Z': + case (.)'Z': Undo(); - case (KeyCode)'Y': + case (.)'Y': Redo(); case .Return: if (mIsMultiline) @@ -2085,6 +2164,16 @@ namespace Beefy.widgets } } + if (mWidgetWindow.GetKeyFlags() == .Ctrl | .Shift) + { + switch (keyCode) + { + case (.)'Z': + Redo(); + default: + } + } + switch (keyCode) { case .Return: @@ -2175,60 +2264,8 @@ namespace Beefy.widgets } } - bool isWordMove = mWidgetWindow.IsKeyDown(.Alt); wasMoveKey = true; - int anIndex = GetTextIdx(lineIdx, lineChar); - char8 prevC = 0; - CharType prevCharType = (anIndex < mData.mTextLength) ? GetCharType((char8)mData.mText[anIndex].mChar) : .Unknown; - while (true) - { - int lineStart; - int lineEnd; - GetLinePosition(lineIdx, out lineStart, out lineEnd); - int lineLen = lineEnd - lineStart; - - int nextLineChar = lineChar + 1; - bool isWithinLine = nextLineChar < lineLen; - if (nextLineChar == lineLen) - { - GetTextData(); - if ((mData.mTextFlags == null) || ((mData.mTextFlags[lineEnd] & (int32)TextFlags.Wrap) == 0)) - { - isWithinLine = true; - } - } - - if (isWithinLine) - MoveCursorTo(lineIdx, lineChar + 1, false, 1); - else if (lineIdx < GetLineCount() - 1) - MoveCursorTo(lineIdx + 1, 0); - - if (!mWidgetWindow.IsKeyDown(KeyCode.Control)) - break; - - GetLineCharAtIdx(CursorTextPos, out lineIdx, out lineChar); - anIndex = GetTextIdx(lineIdx, lineChar); - if (anIndex == mData.mTextLength) - break; - - char8 c = (char8)mData.mText[anIndex].mChar; - CharType char8Type = GetCharType(c); - if (char8Type == .Opening) - break; - if (char8Type != prevCharType) - { - if ((char8Type != .WhiteSpace) && (prevCharType == .WhiteSpace)) - break; - if ((char8Type == .NewLine) || (char8Type == .NonBreaking) || (char8Type == .Other)) - break; - } - - if ((isWordMove) && (c.IsUpper) && (prevC.IsLower)) - break; - - prevCharType = char8Type; - prevC = c; - } + SelectRight(lineIdx, lineChar, mWidgetWindow.IsKeyDown(KeyCode.Control), mWidgetWindow.IsKeyDown(KeyCode.Alt)); } } break; @@ -2371,9 +2408,58 @@ namespace Beefy.widgets } break; case KeyCode.Insert: + if ((mWidgetWindow.IsKeyDown(.Control)) && (mWidgetWindow.IsKeyDown(.Shift))) + break; + if (mWidgetWindow.IsKeyDown(.Control)) + { + CopyText(); + break; + } + if (mWidgetWindow.IsKeyDown(.Shift)) + { + PasteText(); + break; + } mOverTypeMode = !mOverTypeMode; break; case KeyCode.Delete: + if (mWidgetWindow.IsKeyDown(.Control)) + { + if (mWidgetWindow.IsKeyDown(.Shift)) + { + int startIdx = CursorTextPos; + CursorToLineEnd(); + mSelection = EditSelection(CursorTextPos, startIdx); + var action = new DeleteSelectionAction(this); + action.mMoveCursor = true; + mData.mUndoManager.Add(action); + action.mCursorTextPos = (.)startIdx; + PhysDeleteSelection(true); + break; + } + + int line; + int lineChar2; + GetCursorLineChar(out line, out lineChar2); + + int startIdx = CursorTextPos; + SelectRight(line, lineChar, true, false); + mSelection = EditSelection(CursorTextPos, startIdx); + + var action = new DeleteSelectionAction(this); + action.mMoveCursor = true; + mData.mUndoManager.Add(action); + action.mCursorTextPos = (.)startIdx; + PhysDeleteSelection(true); + break; + } + + if (mWidgetWindow.IsKeyDown(.Shift)) + { + CutText(); + break; + } + if (!CheckReadOnly()) DeleteChar(); mCursorImplicitlyMoved = true; diff --git a/IDE/src/Commands.bf b/IDE/src/Commands.bf index 63fc9b07..10b04751 100644 --- a/IDE/src/Commands.bf +++ b/IDE/src/Commands.bf @@ -191,9 +191,11 @@ namespace IDE Add("Close All Windows", new () => { gApp.[Friend]TryCloseAllDocuments(); }); Add("Close Window", new () => { gApp.[Friend]TryCloseCurrentDocument(); }); Add("Close Workspace", new => gApp.[Friend]Cmd_CloseWorkspaceAndSetupNew); + Add("Comment Selection", new => gApp.[Friend]CommentSelection); Add("Compile File", new => gApp.Cmd_CompileFile); Add("Debug All Tests", new () => { gApp.[Friend]RunTests(true, true); }); Add("Debug Normal Tests", new () => { gApp.[Friend]RunTests(false, true); }); + Add("Duplicate Line", new () => { gApp.[Friend]DuplicateLine(); }); Add("Exit", new => gApp.[Friend]Cmd_Exit); Add("Find All References", new => gApp.Cmd_FindAllReferences); Add("Find Class", new => gApp.Cmd_FindClass); @@ -276,6 +278,7 @@ namespace IDE Add("Tab Last", new => gApp.[Friend]TabLast); Add("Tab Next", new => gApp.[Friend]TabNext); Add("Tab Prev", new => gApp.[Friend]TabPrev); + Add("Uncomment Selection", new => gApp.[Friend]UncommentSelection); Add("View New", new => gApp.Cmd_ViewNew); Add("View Split", new => gApp.[Friend]ViewSplit); Add("View White Space", new => gApp.Cmd_ViewWhiteSpace); diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 30277e86..40130e95 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -2291,6 +2291,30 @@ namespace IDE //FinishShowingNewWorkspace(); } + [IDECommand] + void DuplicateLine() + { + var sewc = GetActiveSourceEditWidgetContent(); + if (sewc != null) + sewc.DuplicateLine(); + } + + [IDECommand] + void CommentSelection() + { + var sewc = GetActiveSourceEditWidgetContent(); + if (sewc != null) + sewc.ToggleComment(true); + } + + [IDECommand] + void UncommentSelection() + { + var sewc = GetActiveSourceEditWidgetContent(); + if (sewc != null) + sewc.ToggleComment(false); + } + public Result StructuredLoad(StructuredData data, StringView filePath) { if (mWorkspace.IsSingleFileWorkspace) diff --git a/IDE/src/Settings.bf b/IDE/src/Settings.bf index 394c0d4d..bbe9cec6 100644 --- a/IDE/src/Settings.bf +++ b/IDE/src/Settings.bf @@ -448,6 +448,8 @@ namespace IDE Add("Cancel Build", "Ctrl+Break"); Add("Close Window", "Ctrl+W"); Add("Compile File", "Ctrl+F7"); + Add("Comment Selection", "Ctrl+K, Ctrl+C"); + Add("Duplicate Line", "Ctrl+D"); Add("Find Class", "Alt+Shift+L"); Add("Find in Document", "Ctrl+F"); Add("Find in Files", "Ctrl+Shift+F"); @@ -512,6 +514,7 @@ namespace IDE Add("Tab Last", "Ctrl+Alt+End"); Add("Tab Next", "Ctrl+Alt+PageDown"); Add("Tab Prev", "Ctrl+Alt+PageUp"); + Add("Uncomment Selection", "Ctrl+K, Ctrl+U"); Add("Zoom In", "Ctrl+Equals"); Add("Zoom Out", "Ctrl+Minus"); Add("Zoom Reset", "Ctrl+0"); diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index 955bf0fe..defa5810 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -1984,18 +1984,20 @@ namespace IDE.ui return true; } - public bool ToggleComment() + public bool ToggleComment(bool? doComment = null) { if (CheckReadOnly()) return false; if ((HasSelection()) && (mSelection.Value.Length > 1)) { - var startLineAndCol = CursorLineAndColumn ; + var startLineAndCol = CursorLineAndColumn; UndoBatchStart undoBatchStart = new UndoBatchStart("embeddedToggleComment"); mData.mUndoManager.Add(undoBatchStart); + mData.mUndoManager.Add(new SetCursorAction(this)); + int minPos = mSelection.GetValueOrDefault().MinPos; int maxPos = mSelection.GetValueOrDefault().MaxPos; mSelection = null; @@ -2014,7 +2016,7 @@ namespace IDE.ui int firstCharPos = minPos + (startLen - afterTrimStart); int lastCharPos = maxPos - (afterTrimStart - afterTrimEnd); - if (trimmedStr.StartsWith("/*")) + if ((doComment != true) && (trimmedStr.StartsWith("/*"))) { if (trimmedStr.EndsWith("*/")) { @@ -2022,28 +2024,57 @@ namespace IDE.ui DeleteChar(); mSelection = EditSelection(lastCharPos - 4, lastCharPos - 2); DeleteChar(); + + if (doComment != null) + mSelection = EditSelection(firstCharPos, lastCharPos - 4); } } - else + else if (doComment != false) { CursorTextPos = firstCharPos; InsertAtCursor("/*"); CursorTextPos = lastCharPos + 2; InsertAtCursor("*/"); + + if (doComment != null) + mSelection = EditSelection(firstCharPos, lastCharPos + 4); } - + if (undoBatchStart != null) mData.mUndoManager.Add(undoBatchStart.mBatchEnd); CursorLineAndColumn = startLineAndCol; - mSelection = null; + if (doComment == null) + mSelection = null; + return true; } return false; } + public void DuplicateLine() + { + UndoBatchStart undoBatchStart = new UndoBatchStart("embeddedToggleComment"); + mData.mUndoManager.Add(undoBatchStart); + + mData.mUndoManager.Add(new SetCursorAction(this)); + + var prevCursorLineAndColumn = CursorLineAndColumn; + int lineNum = CursorLineAndColumn.mLine; + GetLinePosition(lineNum, var lineStart, var lineEnd); + var str = scope String(); + GetLineText(lineNum, str); + mSelection = null; + str.Append("\n"); + CursorLineAndColumn = LineAndColumn(lineNum, 0); + InsertAtCursor(str); + CursorLineAndColumn = LineAndColumn(prevCursorLineAndColumn.mLine + 1, prevCursorLineAndColumn.mColumn); + + mData.mUndoManager.Add(undoBatchStart.mBatchEnd); + } + public override void ContentChanged() { base.ContentChanged(); @@ -2064,24 +2095,7 @@ namespace IDE.ui scope AutoBeefPerf("SEWC.KeyChar"); var keyChar; - if (keyChar == '\x7F') // Ctrl+Backspace - { - int line; - int lineChar; - GetCursorLineChar(out line, out lineChar); - - int startIdx = CursorTextPos; - SelectLeft(line, lineChar, true, false); - mSelection = EditSelection(CursorTextPos, startIdx); - - var action = new DeleteSelectionAction(this); - action.mMoveCursor = true; - mData.mUndoManager.Add(action); - action.mCursorTextPos = (.)startIdx; - PhysDeleteSelection(true); - - return; - } + if (mIgnoreKeyChar) {