libyui-ncurses
 
Loading...
Searching...
No Matches
CyclicContainer.h
1/*
2 Copyright (C) 2020 SUSE LLC
3 This library is free software; you can redistribute it and/or modify
4 it under the terms of the GNU Lesser General Public License as
5 published by the Free Software Foundation; either version 2.1 of the
6 License, or (at your option) version 3.0 of the License. This library
7 is distributed in the hope that it will be useful, but WITHOUT ANY
8 WARRANTY; without even the implied warranty of MERCHANTABILITY or
9 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10 License for more details. You should have received a copy of the GNU
11 Lesser General Public License along with this library; if not, write
12 to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13 Floor, Boston, MA 02110-1301 USA
14*/
15
16
17/*-/
18
19 File: CyclicContainer.h
20
21 Author: Jose Iván López <jlopez@suse.de>
22
23/-*/
24
25
26#ifndef CyclicContainer_h
27#define CyclicContainer_h
28
29#include <algorithm>
30#include <iterator>
31#include <vector>
32
38template <class T>
39class CyclicContainer
40{
41public:
42
43 using Iterator = typename std::vector<T *>::iterator;
44 using ReverseIterator = std::reverse_iterator<Iterator>;
45
46 Iterator begin() { return _elements.begin(); }
47 Iterator end() { return _elements.end(); }
48
49 CyclicContainer() : _elements(), _current( nullptr )
50 {}
51
52
53 ~CyclicContainer()
54 {
55 clear();
56 }
57
58
59 void clear()
60 {
61 _elements.clear();
62 _current = nullptr;
63 }
64
65
66 void add( T * element )
67 {
68 _elements.push_back(element);
69 }
70
71
72 void setCurrent(Iterator element)
73 {
74 if ( element != _elements.end() )
75 _current = *element;
76 }
77
78
79 Iterator current()
80 {
81 return std::find( _elements.begin(), _elements.end(), _current );
82 }
83
84
85 Iterator next()
86 {
87 Iterator current = this->current();
88
89 if ( current == _elements.end() )
90 return findNext( _elements.begin() );
91
92 Iterator next = findNext( std::next( current, 1 ) );
93
94 if ( next == _elements.end() )
95 return findNext( _elements.begin() );
96
97 return next;
98 }
99
100
101 Iterator previous()
102 {
103 Iterator current = this->current();
104
105 ReverseIterator rbegin;
106
107 if ( current == _elements.end() )
108 rbegin = _elements.rbegin();
109 else
110 rbegin = ReverseIterator( current );
111
112 ReverseIterator previous = findPrevious( rbegin );
113
114 if ( previous == _elements.rend() && rbegin != _elements.rbegin() )
115 previous = findPrevious( _elements.rbegin() );
116
117 if ( previous == _elements.rend() )
118 return _elements.end();
119
120 return find( _elements.begin(), _elements.end(), *previous );
121 }
122
123private:
124
125 Iterator findNext( Iterator begin )
126 {
127 return find_if( begin, _elements.end(), [](const T * element) {
128 return element->isSelectable();
129 });
130 }
131
132
133 ReverseIterator findPrevious( ReverseIterator rbegin )
134 {
135 return find_if( rbegin, _elements.rend(), [](const T * element) {
136 return element->isSelectable();
137 });
138 }
139
140
141 std::vector<T *> _elements;
142
143 T * _current;
144};
145
146#endif // CyclicContainer_h