Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/interface/interface_undo.cc')
-rw-r--r--source/blender/editors/interface/interface_undo.cc113
1 files changed, 113 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_undo.cc b/source/blender/editors/interface/interface_undo.cc
new file mode 100644
index 00000000000..ec54b695cf7
--- /dev/null
+++ b/source/blender/editors/interface/interface_undo.cc
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2020 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup edinterface
+ *
+ * Undo stack to use for UI widgets that manage their own editing state.
+ */
+
+#include <cstring>
+
+#include "BLI_listbase.h"
+
+#include "DNA_listBase.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "interface_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Text Field Undo Stack
+ * \{ */
+
+struct uiUndoStack_Text_State {
+ struct uiUndoStack_Text_State *next, *prev;
+ int cursor_index;
+ char text[0];
+};
+
+struct uiUndoStack_Text {
+ ListBase states;
+ uiUndoStack_Text_State *current;
+};
+
+static const char *ui_textedit_undo_impl(uiUndoStack_Text *stack, int *r_cursor_index)
+{
+ /* Don't undo if no data has been pushed yet. */
+ if (stack->current == nullptr) {
+ return nullptr;
+ }
+
+ /* Travel backwards in the stack and copy information to the caller. */
+ if (stack->current->prev != nullptr) {
+ stack->current = stack->current->prev;
+
+ *r_cursor_index = stack->current->cursor_index;
+ return stack->current->text;
+ }
+ return nullptr;
+}
+
+static const char *ui_textedit_redo_impl(uiUndoStack_Text *stack, int *r_cursor_index)
+{
+ /* Don't redo if no data has been pushed yet. */
+ if (stack->current == nullptr) {
+ return nullptr;
+ }
+
+ /* Only redo if new data has not been entered since the last undo. */
+ if (stack->current->next) {
+ stack->current = stack->current->next;
+
+ *r_cursor_index = stack->current->cursor_index;
+ return stack->current->text;
+ }
+ return nullptr;
+}
+
+const char *ui_textedit_undo(uiUndoStack_Text *stack, int direction, int *r_cursor_index)
+{
+ BLI_assert(ELEM(direction, -1, 1));
+ if (direction < 0) {
+ return ui_textedit_undo_impl(stack, r_cursor_index);
+ }
+ return ui_textedit_redo_impl(stack, r_cursor_index);
+}
+
+void ui_textedit_undo_push(uiUndoStack_Text *stack, const char *text, int cursor_index)
+{
+ /* Clear all redo actions from the current state. */
+ if (stack->current != nullptr) {
+ while (stack->current->next) {
+ uiUndoStack_Text_State *state = stack->current->next;
+ BLI_remlink(&stack->states, state);
+ MEM_freeN(state);
+ }
+ }
+
+ /* Create the new state. */
+ const int text_size = strlen(text) + 1;
+ stack->current = static_cast<uiUndoStack_Text_State *>(
+ MEM_mallocN(sizeof(uiUndoStack_Text_State) + text_size, __func__));
+ stack->current->cursor_index = cursor_index;
+ memcpy(stack->current->text, text, text_size);
+ BLI_addtail(&stack->states, stack->current);
+}
+
+uiUndoStack_Text *ui_textedit_undo_stack_create(void)
+{
+ uiUndoStack_Text *stack = MEM_new<uiUndoStack_Text>(__func__);
+ stack->current = nullptr;
+ BLI_listbase_clear(&stack->states);
+
+ return stack;
+}
+
+void ui_textedit_undo_stack_destroy(uiUndoStack_Text *stack)
+{
+ BLI_freelistN(&stack->states);
+ MEM_freeN(stack);
+}
+
+/** \} */