Skip to content

Commit

Permalink
feat: undo now remebers cursor position
Browse files Browse the repository at this point in the history
  • Loading branch information
PocketMiner82 committed Apr 16, 2024
1 parent a5f74be commit 6091016
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 21 deletions.
37 changes: 21 additions & 16 deletions pseudocodeIde/PseudocodeIDEForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -84,8 +83,8 @@ public string Code
private int _lastCursorPosition = 0;

// undo and redo stacks
private Stack<string> _undoStack = new Stack<string>();
private readonly Stack<string> _redoStack = new Stack<string>();
private Stack<UndoPoint> _undoStack = new Stack<UndoPoint>();
private readonly Stack<UndoPoint> _redoStack = new Stack<UndoPoint>();

/// <summary>
/// the path where this file is saved
Expand Down Expand Up @@ -355,6 +354,7 @@ private void CodeTextBox_KeyDown(object sender, KeyEventArgs e)
{
IgnoreTextChange = true;
UpdateUndoStack(true);
TryHandleSelectionChange();
e.SuppressKeyPress = false;
return;
}
Expand Down Expand Up @@ -407,7 +407,7 @@ public void AddTabSelectionIndicators(List<(int selectionStart, int selectionEnd
codeTextBox.IndicatorFillRange(selectionStart, selectionEnd - selectionStart);
}

UpdateUndoStack(true);
TryHandleSelectionChange();
}

/// <summary>
Expand All @@ -425,6 +425,7 @@ private bool TrySelectNextTabIndicator()
codeTextBox.IndicatorClearRange(selectionStart, selectionEnd - selectionStart);
codeTextBox.SelectionStart = selectionStart;
codeTextBox.SelectionEnd = selectionEnd;
UserChangedSelection();
return true;
}
return false;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
}

Expand All @@ -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;
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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
// ---------------------------------------------
Expand Down
1 change: 0 additions & 1 deletion pseudocodeIde/SetClipboardHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
// but WITHOUT ANY WARRANTY

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;

Expand Down
48 changes: 48 additions & 0 deletions pseudocodeIde/UndoPoint.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// 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.
/// </summary>
public class UndoPoint
{
/// <summary>
/// Gets or sets the code (text) at this point in the undo/redo stack.
/// </summary>
public string Code { get; set; }

/// <summary>
/// Gets or sets the starting index of the selection in the text at this point in the undo/redo stack.
/// </summary>
public int SelectionStart { get; set; }

/// <summary>
/// Gets or sets the ending index of the selection in the text at this point in the undo/redo stack.
/// </summary>
public int SelectionEnd { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="UndoPoint"/> class with the specified code, selection start, and selection end.
/// </summary>
/// <param name="code">The code (text) at this point in the undo/redo stack.</param>
/// <param name="selectionStart">The starting index of the selection in the text.</param>
/// <param name="selectionEnd">The ending index of the selection in the text.</param>
public UndoPoint(string code, int selectionStart, int selectionEnd)
{
Code = code;
SelectionStart = selectionStart;
SelectionEnd = selectionEnd;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
using pseudocode_ide.interpreter.pseudocode;
using ScintillaNET;
using System;
using System.Diagnostics;

namespace pseudocode_ide.interpreter.scanner
{
Expand Down

0 comments on commit 6091016

Please sign in to comment.