HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
undo_stack.hpp
1// Copyright Take Vos 2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../utility/utility.hpp"
8#include "../macros.hpp"
9#include <vector>
10#include <cstddef>
11
12hi_export_module(hikogui.container.undo_stack);
13
14hi_export namespace hi::inline v1 {
15
16template<typename T>
18public:
19 using value_type = T;
20
21 constexpr undo_stack(undo_stack const &) noexcept = default;
22 constexpr undo_stack(undo_stack &&) noexcept = default;
23 constexpr undo_stack &operator=(undo_stack const &) noexcept = default;
24 constexpr undo_stack &operator=(undo_stack &&) noexcept = default;
25 constexpr undo_stack(size_t max_depth) noexcept : _stack{}, _max_depth(max_depth), _cursor(0) {}
26
27 template<typename... Args>
28 constexpr void emplace(Args &&... args) noexcept
29 {
30 push(value_type{std::forward<Args>(args)...});
31 }
32
33 [[nodiscard]] constexpr bool can_undo() const noexcept
34 {
35 return _cursor != 0;
36 }
37
38 template<typename... Args>
39 [[nodiscard]] constexpr value_type const &undo(Args &&...args) noexcept
40 {
41 hi_assert(can_undo());
42 if (_first_undo) {
43 // On the first undo, we need to emplace the last state. So that redo
44 // will be able to get back to state before the undo.
45 push(value_type{std::forward<Args>(args)...});
46 // The state we just added should be skipped.
47 --_cursor;
48 _first_undo = false;
49 }
50 return _stack[--_cursor];
51 }
52
53 [[nodiscard]] constexpr bool can_redo() const noexcept
54 {
55 return (_cursor + 1) < _stack.size();
56 }
57
58 [[nodiscard]] constexpr value_type const &redo() const noexcept
59 {
60 hi_assert(can_redo());
61 return _stack[++_cursor];
62 }
63
64private:
66 size_t _max_depth;
67 mutable size_t _cursor;
68 mutable bool _first_undo = true;
69
70 template<forward_of<value_type> Value>
71 constexpr void push(Value &&value) noexcept
72 {
73 hi_assert(_cursor <= _stack.size());
74 _stack.erase(_stack.begin() + _cursor, _stack.end());
75
76 if (_stack.size() > _max_depth) {
77 _stack.erase(_stack.begin());
78 }
79
80 _stack.push_back(std::forward<Value>(value));
81 _cursor = _stack.size();
82
83 _first_undo = true;
84 }
85};
86
87
88}
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition undo_stack.hpp:17
T begin(T... args)
T end(T... args)
T erase(T... args)
T push_back(T... args)
T size(T... args)