From 6091016b1495949c8fdf5aa96b627ac70bd41a21 Mon Sep 17 00:00:00 2001 From: PocketMiner82 Date: Tue, 16 Apr 2024 18:55:27 +0200 Subject: [PATCH] feat: undo now remebers cursor position --- pseudocodeIde/PseudocodeIDEForm.cs | 37 +++++++------- pseudocodeIde/SetClipboardHelper.cs | 1 - pseudocodeIde/UndoPoint.cs | 48 +++++++++++++++++++ .../pseudocode/PseudocodeAutocompleteItem.cs | 3 -- .../scanner/SyntaxHighlightingScanner.cs | 1 - 5 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 pseudocodeIde/UndoPoint.cs diff --git a/pseudocodeIde/PseudocodeIDEForm.cs b/pseudocodeIde/PseudocodeIDEForm.cs index 9a8eff2..6020895 100644 --- a/pseudocodeIde/PseudocodeIDEForm.cs +++ b/pseudocodeIde/PseudocodeIDEForm.cs @@ -24,7 +24,6 @@ using System.Drawing; using System.IO; using System.Linq; -using System.Net; using System.Reflection; using System.Text.RegularExpressions; using System.Windows.Forms; @@ -84,8 +83,8 @@ public string Code private int _lastCursorPosition = 0; // undo and redo stacks - private Stack _undoStack = new Stack(); - private readonly Stack _redoStack = new Stack(); + private Stack _undoStack = new Stack(); + private readonly Stack _redoStack = new Stack(); /// /// the path where this file is saved @@ -355,6 +354,7 @@ private void CodeTextBox_KeyDown(object sender, KeyEventArgs e) { IgnoreTextChange = true; UpdateUndoStack(true); + TryHandleSelectionChange(); e.SuppressKeyPress = false; return; } @@ -407,7 +407,7 @@ public void AddTabSelectionIndicators(List<(int selectionStart, int selectionEnd codeTextBox.IndicatorFillRange(selectionStart, selectionEnd - selectionStart); } - UpdateUndoStack(true); + TryHandleSelectionChange(); } /// @@ -425,6 +425,7 @@ private bool TrySelectNextTabIndicator() codeTextBox.IndicatorClearRange(selectionStart, selectionEnd - selectionStart); codeTextBox.SelectionStart = selectionStart; codeTextBox.SelectionEnd = selectionEnd; + UserChangedSelection(); return true; } return false; @@ -803,7 +804,7 @@ private void ResetUndoRedo() { _undoStack.Clear(); _redoStack.Clear(); - _undoStack.Push(codeTextBox.Text); + _undoStack.Push(new UndoPoint(codeTextBox.Text, codeTextBox.SelectionStart, codeTextBox.SelectionEnd)); undoToolStripMenuItem.Enabled = false; redoToolStripMenuItem.Enabled = false; } @@ -847,7 +848,7 @@ public void UpdateUndoStack(bool forceUpdate) // don't update when the last char matches the NO_UPDATE_AFTER regex and the update is caused by text change. // also don't update, when the new undo text is already in the stack if ((codeTextBox.SelectionStart > 1 && !forceUpdate && _noUpdateAfter.IsMatch(undoText.ElementAt(codeTextBox.SelectionStart - 2).ToString())) - || _undoStack.Peek().Equals(undoText)) + || _undoStack.Peek().Code == undoText) { return; } @@ -856,7 +857,7 @@ public void UpdateUndoStack(bool forceUpdate) _redoStack.Clear(); // and update the undo stack, limit max undo size - _undoStack.Push(undoText); + _undoStack.Push(new UndoPoint(undoText, codeTextBox.SelectionStart, codeTextBox.SelectionEnd)); _undoStack = _undoStack.Trim(MAX_UNDO_SIZE); } @@ -865,17 +866,16 @@ private void UndoToolStripMenuItem_Click(object sender, EventArgs e) // put current text in redo if not already in there if (_redoStack.Count == 0 || !_redoStack.Peek().Equals(codeTextBox.Text)) { - _redoStack.Push(codeTextBox.Text); + _redoStack.Push(new UndoPoint(codeTextBox.Text, codeTextBox.SelectionStart, codeTextBox.SelectionEnd)); redoToolStripMenuItem.Enabled = true; } - int oldSelectionStart = codeTextBox.SelectionStart; // the undo stack always has at least one item in it if (_undoStack.Count <= 1) { // set the textbox text to the item without removing it from the stack IgnoreTextChange = true; - codeTextBox.Text = _undoStack.Peek(); + UpdateCodeTextBox(_undoStack.Peek()); // no more things to undo undoToolStripMenuItem.Enabled = false; @@ -888,10 +888,9 @@ private void UndoToolStripMenuItem_Click(object sender, EventArgs e) do { IgnoreTextChange = true; - codeTextBox.Text = _undoStack.Peek(); + UpdateCodeTextBox(_undoStack.Peek()); } while (_undoStack.Count > 1 && currentText.Equals(_undoStack.Pop())); } - codeTextBox.SelectionStart = oldSelectionStart; } private void RedoToolStripMenuItem_Click(object sender, EventArgs e) @@ -900,16 +899,14 @@ private void RedoToolStripMenuItem_Click(object sender, EventArgs e) // put current text in undo if not already in there if (!_undoStack.Peek().Equals(codeTextBox.Text)) { - _undoStack.Push(codeTextBox.Text); + _undoStack.Push(new UndoPoint(codeTextBox.Text, codeTextBox.SelectionStart, codeTextBox.SelectionEnd)); } // set the textbox text to the top item of the redo stack. also remove it from the stack if (_redoStack.Count > 0) { IgnoreTextChange = true; - int oldSelectionStart = codeTextBox.SelectionStart; - codeTextBox.Text = _redoStack.Pop(); - codeTextBox.SelectionStart = Math.Min(oldSelectionStart, codeTextBox.TextLength); + UpdateCodeTextBox(_redoStack.Pop()); } // no more things to redo @@ -919,6 +916,14 @@ private void RedoToolStripMenuItem_Click(object sender, EventArgs e) } } + private void UpdateCodeTextBox(UndoPoint point) + { + codeTextBox.Text = point.Code; + codeTextBox.SelectionStart = point.SelectionStart; + codeTextBox.SelectionEnd = point.SelectionEnd; + UserChangedSelection(); + } + // --------------------------------------------- // FIND/REPLACE // --------------------------------------------- diff --git a/pseudocodeIde/SetClipboardHelper.cs b/pseudocodeIde/SetClipboardHelper.cs index 44ec2ab..606c20f 100644 --- a/pseudocodeIde/SetClipboardHelper.cs +++ b/pseudocodeIde/SetClipboardHelper.cs @@ -10,7 +10,6 @@ // but WITHOUT ANY WARRANTY using System; -using System.Diagnostics; using System.Threading; using System.Windows.Forms; diff --git a/pseudocodeIde/UndoPoint.cs b/pseudocodeIde/UndoPoint.cs new file mode 100644 index 0000000..3d020c5 --- /dev/null +++ b/pseudocodeIde/UndoPoint.cs @@ -0,0 +1,48 @@ +// Pseudocode IDE - Execute Pseudocode for the German (BW) 2024 Abitur +// Copyright (C) 2024 PocketMiner82 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY + +namespace pseudocode_ide +{ + /// + /// Represents a point in the undo/redo stack for the code textbox. + /// Each instance captures the state of the text and selection at a specific point in time. + /// + public class UndoPoint + { + /// + /// Gets or sets the code (text) at this point in the undo/redo stack. + /// + public string Code { get; set; } + + /// + /// Gets or sets the starting index of the selection in the text at this point in the undo/redo stack. + /// + public int SelectionStart { get; set; } + + /// + /// Gets or sets the ending index of the selection in the text at this point in the undo/redo stack. + /// + public int SelectionEnd { get; set; } + + /// + /// Initializes a new instance of the class with the specified code, selection start, and selection end. + /// + /// The code (text) at this point in the undo/redo stack. + /// The starting index of the selection in the text. + /// The ending index of the selection in the text. + public UndoPoint(string code, int selectionStart, int selectionEnd) + { + Code = code; + SelectionStart = selectionStart; + SelectionEnd = selectionEnd; + } + } +} diff --git a/pseudocodeIde/interpreter/pseudocode/PseudocodeAutocompleteItem.cs b/pseudocodeIde/interpreter/pseudocode/PseudocodeAutocompleteItem.cs index 7fd04ae..bb3b0a3 100644 --- a/pseudocodeIde/interpreter/pseudocode/PseudocodeAutocompleteItem.cs +++ b/pseudocodeIde/interpreter/pseudocode/PseudocodeAutocompleteItem.cs @@ -12,11 +12,8 @@ using AutocompleteMenuNS; using pseudocodeIde; using ScintillaNET; -using System; using System.Collections.Generic; -using System.Drawing; using System.Linq; -using static System.Net.Mime.MediaTypeNames; namespace pseudocode_ide.interpreter.pseudocode { diff --git a/pseudocodeIde/interpreter/scanner/SyntaxHighlightingScanner.cs b/pseudocodeIde/interpreter/scanner/SyntaxHighlightingScanner.cs index 21e3c3d..bbabef2 100644 --- a/pseudocodeIde/interpreter/scanner/SyntaxHighlightingScanner.cs +++ b/pseudocodeIde/interpreter/scanner/SyntaxHighlightingScanner.cs @@ -12,7 +12,6 @@ using pseudocode_ide.interpreter.pseudocode; using ScintillaNET; using System; -using System.Diagnostics; namespace pseudocode_ide.interpreter.scanner {