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 "concepts.hpp"
8#include <vector>
9#include <cstddef>
10
11namespace hi::inline v1 {
12
13template<typename T>
15public:
16 using value_type = T;
17
18 constexpr undo_stack(undo_stack const &) noexcept = default;
19 constexpr undo_stack(undo_stack &&) noexcept = default;
20 constexpr undo_stack &operator=(undo_stack const &) noexcept = default;
21 constexpr undo_stack &operator=(undo_stack &&) noexcept = default;
22 constexpr undo_stack(size_t max_depth) noexcept : _stack{}, _max_depth(max_depth), _cursor(0) {}
23
24 template<typename... Args>
25 constexpr void emplace(Args &&... args) noexcept
26 {
27 push(value_type{std::forward<Args>(args)...});
28 }
29
30 [[nodiscard]] constexpr bool can_undo() const noexcept
31 {
32 return _cursor != 0;
33 }
34
35 template<typename... Args>
36 [[nodiscard]] constexpr value_type const &undo(Args &&...args) noexcept
37 {
38 hi_axiom(can_undo());
39 if (_first_undo) {
40 // On the first undo, we need to emplace the last state. So that redo
41 // will be able to get back to state before the undo.
42 push(value_type{std::forward<Args>(args)...});
43 // The state we just added should be skipped.
44 --_cursor;
45 _first_undo = false;
46 }
47 return _stack[--_cursor];
48 }
49
50 [[nodiscard]] constexpr bool can_redo() const noexcept
51 {
52 return (_cursor + 1) < _stack.size();
53 }
54
55 [[nodiscard]] constexpr value_type const &redo() const noexcept
56 {
57 hi_axiom(can_redo());
58 return _stack[++_cursor];
59 }
60
61private:
63 size_t _max_depth;
64 mutable size_t _cursor;
65 mutable bool _first_undo = true;
66
67 template<forward_of<value_type> Value>
68 constexpr void push(Value &&value) noexcept
69 {
70 hi_axiom(_cursor <= _stack.size());
71 _stack.erase(_stack.begin() + _cursor, _stack.end());
72
73 if (_stack.size() > _max_depth) {
74 _stack.erase(_stack.begin());
75 }
76
77 _stack.push_back(std::forward<Value>(value));
78 _cursor = _stack.size();
79
80 _first_undo = true;
81 }
82};
83
84
85}
DOXYGEN BUG.
Definition algorithm.hpp:15
Definition undo_stack.hpp:14
T begin(T... args)
T end(T... args)
T erase(T... args)
T push_back(T... args)
T size(T... args)