Redo working
This commit is contained in:
@@ -20,7 +20,8 @@ struct HistoryEntry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct History {
|
struct History {
|
||||||
Array<HistoryEntry> entries;
|
Array<HistoryEntry> undo_stack;
|
||||||
|
Array<HistoryEntry> redo_stack;
|
||||||
int debug_edit_phase;
|
int debug_edit_phase;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -287,49 +288,19 @@ void MergeCursors(Window *window) {
|
|||||||
new_cursors.add(it);
|
new_cursors.add(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Assert(new_cursors.len <= window->cursors.len);
|
||||||
window->cursors.dealloc();
|
window->cursors.dealloc();
|
||||||
window->cursors = new_cursors;
|
window->cursors = new_cursors;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UndoEdit(Window *window) {
|
void SaveHistoryBeforeMergeCursor(Window *window, Array<HistoryEntry> *stack) {
|
||||||
if (window->history.entries.len <= 0) return;
|
HistoryEntry *entry = stack->alloc();
|
||||||
|
|
||||||
HistoryEntry entry = window->history.entries.pop();
|
|
||||||
_ApplyEdits(&window->buffer, entry.edits);
|
|
||||||
|
|
||||||
window->cursors.dealloc();
|
|
||||||
window->cursors = entry.cursors;
|
|
||||||
|
|
||||||
Allocator sys_allocator = GetSystemAllocator();
|
Allocator sys_allocator = GetSystemAllocator();
|
||||||
For(entry.edits) Dealloc(sys_allocator, &it.string.data);
|
|
||||||
entry.edits.dealloc();
|
|
||||||
|
|
||||||
// Generate layout
|
|
||||||
Clear(&window->layout_arena);
|
|
||||||
window->layout = CalculateLayout(&window->layout_arena, window->buffer, window->font, window->font_size, window->font_spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BeforeEdit(Window *window) {
|
|
||||||
Assert(window->history.debug_edit_phase == 0);
|
|
||||||
window->history.debug_edit_phase += 1;
|
|
||||||
|
|
||||||
{
|
|
||||||
History &h = window->history;
|
|
||||||
HistoryEntry *entry = h.entries.alloc();
|
|
||||||
Allocator sys_allocator = GetSystemAllocator();
|
|
||||||
Assert(window->cursors.len);
|
|
||||||
entry->cursors = window->cursors.tight_copy(sys_allocator);
|
entry->cursors = window->cursors.tight_copy(sys_allocator);
|
||||||
}
|
|
||||||
|
|
||||||
MergeCursors(window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyEdits(Window *window, Array<Edit> edits) {
|
void SaveHistoryBeforeApplyEdits(Window *window, Array<HistoryEntry> *stack, Array<Edit> edits) {
|
||||||
Assert(window->history.debug_edit_phase == 1);
|
HistoryEntry *entry = stack->last();
|
||||||
window->history.debug_edit_phase += 1;
|
|
||||||
|
|
||||||
{
|
|
||||||
HistoryEntry *entry = window->history.entries.last();
|
|
||||||
Allocator sys_allocator = GetSystemAllocator();
|
Allocator sys_allocator = GetSystemAllocator();
|
||||||
entry->edits = edits.tight_copy(sys_allocator);
|
entry->edits = edits.tight_copy(sys_allocator);
|
||||||
|
|
||||||
@@ -359,8 +330,68 @@ void ApplyEdits(Window *window, Array<Edit> edits) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RedoEdit(Window *window) {
|
||||||
|
if (window->history.redo_stack.len <= 0) return;
|
||||||
|
|
||||||
|
HistoryEntry entry = window->history.redo_stack.pop();
|
||||||
|
|
||||||
|
SaveHistoryBeforeMergeCursor(window, &window->history.undo_stack);
|
||||||
|
SaveHistoryBeforeApplyEdits(window, &window->history.undo_stack, entry.edits);
|
||||||
|
_ApplyEdits(&window->buffer, entry.edits);
|
||||||
|
|
||||||
|
window->cursors.dealloc();
|
||||||
|
window->cursors = entry.cursors;
|
||||||
|
|
||||||
|
Allocator sys_allocator = GetSystemAllocator();
|
||||||
|
For(entry.edits) Dealloc(sys_allocator, &it.string.data);
|
||||||
|
entry.edits.dealloc();
|
||||||
|
|
||||||
|
// Generate layout
|
||||||
|
Clear(&window->layout_arena);
|
||||||
|
window->layout = CalculateLayout(&window->layout_arena, window->buffer, window->font, window->font_size, window->font_spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UndoEdit(Window *window) {
|
||||||
|
if (window->history.undo_stack.len <= 0) return;
|
||||||
|
|
||||||
|
HistoryEntry entry = window->history.undo_stack.pop();
|
||||||
|
|
||||||
|
SaveHistoryBeforeMergeCursor(window, &window->history.redo_stack);
|
||||||
|
SaveHistoryBeforeApplyEdits(window, &window->history.redo_stack, entry.edits);
|
||||||
|
_ApplyEdits(&window->buffer, entry.edits);
|
||||||
|
|
||||||
|
window->cursors.dealloc();
|
||||||
|
window->cursors = entry.cursors;
|
||||||
|
|
||||||
|
Allocator sys_allocator = GetSystemAllocator();
|
||||||
|
For(entry.edits) Dealloc(sys_allocator, &it.string.data);
|
||||||
|
entry.edits.dealloc();
|
||||||
|
|
||||||
|
// Generate layout
|
||||||
|
Clear(&window->layout_arena);
|
||||||
|
window->layout = CalculateLayout(&window->layout_arena, window->buffer, window->font, window->font_size, window->font_spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BeforeEdit(Window *window) {
|
||||||
|
Assert(window->history.debug_edit_phase == 0);
|
||||||
|
window->history.debug_edit_phase += 1;
|
||||||
|
Assert(window->cursors.len);
|
||||||
|
SaveHistoryBeforeMergeCursor(window, &window->history.undo_stack);
|
||||||
|
For(window->history.redo_stack) {
|
||||||
|
it.cursors.dealloc();
|
||||||
|
ForItem(edit, it.edits) Dealloc(it.edits.allocator, &edit.string.data);
|
||||||
|
it.edits.dealloc();
|
||||||
|
}
|
||||||
|
window->history.redo_stack.dealloc();
|
||||||
|
MergeCursors(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyEdits(Window *window, Array<Edit> edits) {
|
||||||
|
Assert(window->history.debug_edit_phase == 1);
|
||||||
|
window->history.debug_edit_phase += 1;
|
||||||
|
SaveHistoryBeforeApplyEdits(window, &window->history.undo_stack, edits);
|
||||||
_ApplyEdits(&window->buffer, edits);
|
_ApplyEdits(&window->buffer, edits);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,7 +399,7 @@ void AfterEdit(Window *window, Array<Edit> edits) {
|
|||||||
Assert(window->history.debug_edit_phase == 2);
|
Assert(window->history.debug_edit_phase == 2);
|
||||||
window->history.debug_edit_phase -= 2;
|
window->history.debug_edit_phase -= 2;
|
||||||
|
|
||||||
HistoryEntry *entry = window->history.entries.last();
|
HistoryEntry *entry = window->history.undo_stack.last();
|
||||||
Assert(entry->cursors.len);
|
Assert(entry->cursors.len);
|
||||||
Assert(entry->edits.len);
|
Assert(entry->edits.len);
|
||||||
|
|
||||||
|
|||||||
@@ -316,9 +316,15 @@ int main() {
|
|||||||
AfterEdit(focused_window, edits);
|
AfterEdit(focused_window, edits);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_Z) || IsKeyPressedRepeat(KEY_Z))) {
|
if ((IsKeyPressed(KEY_Z) || IsKeyPressedRepeat(KEY_Z))) {
|
||||||
|
if (IsKeyDown(KEY_LEFT_CONTROL)) {
|
||||||
|
if (IsKeyDown(KEY_LEFT_SHIFT)) {
|
||||||
|
RedoEdit(focused_window);
|
||||||
|
} else {
|
||||||
UndoEdit(focused_window);
|
UndoEdit(focused_window);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_DELETE) || IsKeyPressedRepeat(KEY_DELETE)) {
|
if (IsKeyPressed(KEY_DELETE) || IsKeyPressedRepeat(KEY_DELETE)) {
|
||||||
// Select things to delete
|
// Select things to delete
|
||||||
|
|||||||
Reference in New Issue
Block a user