libyui-ncurses
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 
38 template <class T>
40 {
41 public:
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 
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 
123 private:
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
Definition: CyclicContainer.h:39