cycle.hh (4445B)
1 #ifndef __CYCLE_H_GUARD__ 2 #define __CYCLE_H_GUARD__ 3 4 #include "../winsys/common.hh" 5 #include "../winsys/geometry.hh" 6 7 #include <cstdlib> 8 #include <deque> 9 #include <vector> 10 #include <optional> 11 #include <unordered_map> 12 #include <variant> 13 14 enum class StackAction 15 { 16 Insert, 17 Remove 18 }; 19 20 template <typename T> 21 class HistoryStack final 22 { 23 static_assert(std::is_pointer<T>::value, 24 "Only pointer types may be stored in a history stack."); 25 26 public: 27 HistoryStack(); 28 ~HistoryStack(); 29 30 void clear(); 31 void push_back(T); 32 void replace(T, T); 33 std::optional<T> peek_back() const; 34 std::optional<T> pop_back(); 35 void remove(T); 36 37 std::vector<T> const& as_vector() const; 38 39 private: 40 std::vector<T> m_stack; 41 42 }; 43 44 template <typename T> 45 class Cycle final 46 { 47 static_assert(std::is_pointer<T>::value, 48 "Only pointer types may be stored in a cycle."); 49 50 public: 51 Cycle(std::vector<T>, bool); 52 Cycle(std::initializer_list<T>, bool); 53 ~Cycle(); 54 55 bool next_will_wrap(winsys::Direction) const; 56 bool empty() const; 57 bool contains(T) const; 58 bool is_active_element(T) const; 59 bool is_active_index(Index) const; 60 61 std::size_t size() const; 62 std::size_t length() const; 63 64 std::optional<Index> index() const; 65 Index active_index() const; 66 Index last_index() const; 67 Index next_index(winsys::Direction) const; 68 Index next_index_from(Index, winsys::Direction) const; 69 70 std::optional<Index> index_of_element(const T) const; 71 72 std::optional<T> next_element(winsys::Direction) const; 73 std::optional<T> active_element() const; 74 std::optional<T> prev_active_element() const; 75 std::optional<T> element_at_index(Index) const; 76 std::optional<T> element_at_front(T) const; 77 std::optional<T> element_at_back(T) const; 78 79 void activate_first(); 80 void activate_last(); 81 void activate_at_index(Index); 82 void activate_element(T); 83 84 template<typename UnaryPredicate> 85 void activate_for_condition(UnaryPredicate predicate) 86 { 87 auto it = std::find_if( 88 m_elements.begin(), 89 m_elements.end(), 90 predicate 91 ); 92 93 if (it != m_elements.end()) 94 activate_element(*it); 95 } 96 97 bool remove_first(); 98 bool remove_last(); 99 bool remove_at_index(Index); 100 bool remove_element(T); 101 102 template<typename UnaryPredicate> 103 bool remove_for_condition(UnaryPredicate predicate) 104 { 105 auto it = std::find_if( 106 m_elements.begin(), 107 m_elements.end(), 108 predicate 109 ); 110 111 if (it != m_elements.end()) 112 return remove_element(*it); 113 114 return false; 115 } 116 117 std::optional<T> pop_back(); 118 119 void replace_element(T, T); 120 void swap_elements(T, T); 121 void swap_indices(Index, Index); 122 123 void reverse(); 124 void rotate(winsys::Direction); 125 void rotate_range(winsys::Direction, Index, Index); 126 std::optional<T> cycle_active(winsys::Direction); 127 std::optional<T> drag_active(winsys::Direction); 128 129 void insert_at_front(T); 130 void insert_at_back(T); 131 void insert_before_index(Index, T); 132 void insert_after_index(Index, T); 133 void insert_before_element(T, T); 134 void insert_after_element(T, T); 135 136 void clear(); 137 138 std::deque<T> const& as_deque() const; 139 std::vector<T> const& stack() const; 140 141 typename std::deque<T>::iterator 142 begin() 143 { 144 return m_elements.begin(); 145 } 146 147 typename std::deque<T>::const_iterator 148 begin() const 149 { 150 return m_elements.begin(); 151 } 152 153 typename std::deque<T>::const_iterator 154 cbegin() const 155 { 156 return m_elements.cbegin(); 157 } 158 159 typename std::deque<T>::iterator 160 end() 161 { 162 return m_elements.end(); 163 } 164 165 typename std::deque<T>::const_iterator 166 end() const 167 { 168 return m_elements.end(); 169 } 170 171 typename std::deque<T>::const_iterator 172 cend() const 173 { 174 return m_elements.cend(); 175 } 176 177 T operator[](std::size_t index) 178 { 179 return m_elements[index]; 180 } 181 182 const T operator[](std::size_t index) const 183 { 184 return m_elements[index]; 185 } 186 187 private: 188 Index m_index; 189 190 std::deque<T> m_elements; 191 192 bool m_unwindable; 193 HistoryStack<T> m_stack; 194 195 void sync_active(); 196 197 void push_index_to_stack(std::optional<Index>); 198 void push_active_to_stack(); 199 std::optional<T> get_active_from_stack(); 200 201 }; 202 203 #endif//__CYCLE_H_GUARD__