wxMaxima
Loading...
Searching...
No Matches
CellIterators.h
Go to the documentation of this file.
1// -*- mode: c++; c-file-style: "linux"; c-basic-offset: 2; indent-tabs-mode: nil -*-
2//
3// Copyright (C) 2020 Kuba Ober <kuba@bertec.com>
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15//
16// You should have received a copy of the GNU General Public License
17// along with this program; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19//
20// SPDX-License-Identifier: GPL-2.0+
21
27#ifndef CELLITERATORS_H
28#define CELLITERATORS_H
29
30#include <wx/debug.h>
31#include <memory>
32#include <type_traits>
33#include <iterator>
34#include <vector>
35
36template <typename Cell> class CellListIterator final {
37 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
38 Cell *m_ptr = {};
39
40public:
41 using iterator_category = std::forward_iterator_tag;
42 using value_type = Cell;
43 using difference_type = std::ptrdiff_t;
44 using pointer = Cell *;
45 using reference = Cell &;
46
47 constexpr CellListIterator() = default;
48 constexpr explicit CellListIterator(const std::unique_ptr<Cell> &p)
49 : m_ptr(p.get()) {}
50 constexpr explicit CellListIterator(Cell *p) : m_ptr(p) {}
51 constexpr CellListIterator(const CellListIterator &o) = default;
52 constexpr CellListIterator &operator=(const CellListIterator &o) = default;
53 constexpr CellListIterator operator++(int) {
54 auto ret = *this;
55 return operator++(), ret;
56 }
57 // constexpr fails if wxASSERT contains assembler code, which is true on MinGW
58 CellListIterator &operator++() {
59 if (m_ptr)
60 {
61 const auto *const prev = m_ptr;
62 m_ptr = m_ptr->GetNext();
63 wxASSERT(prev != m_ptr);
64 }
65 return *this;
66 }
67 constexpr bool operator==(const CellListIterator &o) const {
68 return m_ptr == o.m_ptr;
69 }
70 constexpr operator bool() const { return m_ptr; }
71 constexpr operator Cell *() const { return m_ptr; }
72 constexpr Cell *operator->() const { return m_ptr; }
73};
74
75template <typename Cell> class CellListAdapter final {
76 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
77 Cell *m_cell = {};
80
81public:
82 explicit CellListAdapter(Cell *cell) : m_cell(cell) {}
83 constexpr iterator begin() const { return iterator(m_cell); }
84 static constexpr iterator end() { return {}; }
85 constexpr const_iterator cbegin() const { return const_iterator(m_cell); }
86 static constexpr const_iterator cend() { return {}; }
87};
88
104template <typename Cell>
106 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
107 struct Frame {
108 Cell *parent;
109 size_t nextIndex;
110 };
111 Cell *m_ptr = {};
112 std::vector<Frame> m_stack;
113
114public:
115 using iterator_category = std::forward_iterator_tag;
116 using value_type = Cell;
117 using difference_type = std::ptrdiff_t;
118 using pointer = Cell *;
119 using reference = Cell &;
120
121 CellDrawListIterator() = default;
122 explicit CellDrawListIterator(const std::unique_ptr<Cell> &p) : m_ptr(p.get()) {}
123 explicit CellDrawListIterator(Cell *p) : m_ptr(p) {}
124 CellDrawListIterator(const CellDrawListIterator &o) = default;
125 CellDrawListIterator &operator=(const CellDrawListIterator &o) = default;
126 CellDrawListIterator operator++(int) {
127 auto ret = *this;
128 return operator++(), ret;
129 }
130 CellDrawListIterator &operator++()
131 {
132 if (!m_ptr)
133 return *this;
134
135 const auto *const prev = m_ptr;
136 Cell *next = {};
137
138 if (prev->IsBrokenIntoLines() && prev->GetBrokenCellCount() > 0) {
139 // Descend into this cell's broken-form pieces. Once piece 0's own
140 // chain (and anything nested inside it) is exhausted, resume here
141 // at index 1.
142 m_stack.push_back(Frame{const_cast<Cell *>(prev), 1});
143 next = prev->GetBrokenCell(0);
144 } else {
145 next = prev->GetNext();
146 while (!next && !m_stack.empty()) {
147 Frame &frame = m_stack.back();
148 if (frame.nextIndex < frame.parent->GetBrokenCellCount()) {
149 next = frame.parent->GetBrokenCell(frame.nextIndex++);
150 continue;
151 }
152 // This broken cell's pieces are all done: resume with whatever
153 // originally followed it, or -- if it has no successor of its
154 // own -- keep unwinding into whatever enclosing broken cell (if
155 // any) we're nested inside of.
156 Cell *const afterParent = frame.parent->GetNext();
157 m_stack.pop_back();
158 next = afterParent;
159 }
160 }
161
162 m_ptr = next;
163 wxASSERT(prev != m_ptr);
164 return *this;
165 }
166 bool operator==(const CellDrawListIterator &o) const
167 { return m_ptr == o.m_ptr; }
168 operator bool() const { return m_ptr; }
169 operator Cell*() const { return m_ptr; }
170 Cell *operator->() const { return m_ptr; }
171};
172
173template <typename Cell> class CellDrawListAdapter final
174{
175 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
176 Cell *m_cell = {};
179
180public:
181 explicit CellDrawListAdapter(Cell *cell) : m_cell(cell) {}
182 constexpr iterator begin() const { return iterator(m_cell); }
183 static constexpr iterator end() { return {}; }
184 constexpr const_iterator cbegin() const { return const_iterator(m_cell); }
185 static constexpr const_iterator cend() { return {}; }
186};
187
188class Cell;
189
192{
193 enum class Advance { Always, OnlyIfNull };
194 const Cell *m_parentCell = {};
195 Cell *m_innerCell = {};
196 size_t m_index = 0;
197 size_t m_endIndex = 0;
198
199 static size_t GetInnerCellCount(const Cell *cell);
200 static Cell *GetInnerCell(const Cell *cell, size_t index);
201public:
202 using iterator_category = std::forward_iterator_tag;
203 using value_type = Cell;
204 using difference_type = std::ptrdiff_t;
205 using pointer = Cell *;
206 using reference = Cell &;
207
208 InnerCellIterator() = default;
209 explicit InnerCellIterator(Cell *parentCell) :
210 m_parentCell(parentCell),
211 m_endIndex(parentCell ? GetInnerCellCount(parentCell) : 0)
212 {
213 FindFirstInnerCell();
214 }
215 InnerCellIterator(const InnerCellIterator &o) = default;
216 InnerCellIterator &operator=(const InnerCellIterator &o) = default;
217 InnerCellIterator operator++(int)
218 {
219 auto ret = *this;
220 return operator++(), ret;
221 }
222 InnerCellIterator &operator++()
223 {
224 if (m_parentCell)
225 AdvanceLoop(Advance::Always);
226 return *this;
227 }
228 bool operator==(const InnerCellIterator &o) const
229 { return m_innerCell == o.m_innerCell; }
230 operator bool() const { return m_innerCell; }
231 operator Cell*() const { return m_innerCell; }
232 Cell *operator->() const { return m_innerCell; }
233
234private:
235 void FindFirstInnerCell();
236 void AdvanceLoop(Advance mode);
237};
238
239inline void InnerCellIterator::FindFirstInnerCell()
240{
241 if (m_endIndex)
242 {
243 m_innerCell = GetInnerCell(m_parentCell, 0);
244 AdvanceLoop(Advance::OnlyIfNull);
245 }
246}
247
248inline void InnerCellIterator::AdvanceLoop(Advance mode)
249{
250 const Cell *prev = m_innerCell;
251 if (mode == Advance::OnlyIfNull && prev)
252 return;
253 for (;;)
254 {
255 ++m_index;
256 if (m_index == m_endIndex)
257 {
258 m_innerCell = nullptr;
259 break;
260 }
261 m_innerCell = GetInnerCell(m_parentCell, m_index);
262 wxASSERT(!prev || prev != m_innerCell);
263 if (m_innerCell)
264 break;
265 }
266}
267
268class InnerCellAdapter final {
270 iterator const m_iter;
271
272public:
273 explicit InnerCellAdapter(const iterator &) = delete;
274 explicit InnerCellAdapter(Cell *cell) : m_iter(cell) {}
275 iterator begin() const { return m_iter; }
276 static iterator end() { return {}; }
277};
278
279#endif
Definition: CellIterators.h:174
Walks the "draw list": the flattened sequence of cells that make up one displayed line,...
Definition: CellIterators.h:105
Definition: CellIterators.h:75
Definition: CellIterators.h:36
The base class all cell types the worksheet can consist of are derived from.
Definition: Cell.h:148
Cell * GetNext() const
Get the next cell in the list.
Definition: Cell.h:864
virtual Cell * GetBrokenCell(size_t index) const
Retrieve a piece of this cell's broken (linear/1D) display; see GetBrokenCellCount().
Definition: Cell.h:890
Definition: CellIterators.h:268
Iterates the inner cells of a cell.
Definition: CellIterators.h:192