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
34template <typename Cell> class CellListIterator final {
35 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
36 Cell *m_ptr = {};
37
38public:
39 constexpr CellListIterator() = default;
40 constexpr explicit CellListIterator(const std::unique_ptr<Cell> &p)
41 : m_ptr(p.get()) {}
42 constexpr explicit CellListIterator(Cell *p) : m_ptr(p) {}
43 constexpr CellListIterator(const CellListIterator &o) = default;
44 constexpr CellListIterator &operator=(const CellListIterator &o) = default;
45 constexpr CellListIterator operator++(int) {
46 auto ret = *this;
47 return operator++(), ret;
48 }
49 // constexpr fails if wxASSERT contains assembler code, which is true on MinGW
50 CellListIterator &operator++() {
51 if (m_ptr)
52 {
53 const auto *const prev = m_ptr;
54 m_ptr = m_ptr->GetNext();
55 wxASSERT(prev != m_ptr);
56 }
57 return *this;
58 }
59 constexpr bool operator==(const CellListIterator &o) const {
60 return m_ptr == o.m_ptr;
61 }
62 constexpr bool operator!=(const CellListIterator &o) const {
63 return m_ptr != o.m_ptr;
64 }
65 constexpr operator bool() const { return m_ptr; }
66 constexpr operator Cell *() const { return m_ptr; }
67 constexpr Cell *operator->() const { return m_ptr; }
68};
69
70template <typename Cell> class CellListAdapter final {
71 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
72 Cell *m_cell = {};
75
76public:
77 explicit CellListAdapter(Cell *cell) : m_cell(cell) {}
78 constexpr iterator begin() const { return iterator(m_cell); }
79 static constexpr iterator end() { return {}; }
80 constexpr const_iterator cbegin() const { return const_iterator(m_cell); }
81 static constexpr const_iterator cend() { return {}; }
82};
83
84template <typename Cell>
86 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
87 Cell *m_ptr = {};
88
89public:
90 constexpr CellDrawListIterator() = default;
91 constexpr explicit CellDrawListIterator(const std::unique_ptr<Cell> &p) : m_ptr(p.get()) {}
92 constexpr explicit CellDrawListIterator(Cell *p) : m_ptr(p) {}
93 constexpr CellDrawListIterator(const CellDrawListIterator &o) = default;
94 constexpr CellDrawListIterator &operator=(const CellDrawListIterator &o) = default;
95 constexpr CellDrawListIterator operator++(int) {
96 auto ret = *this;
97 return operator++(), ret;
98 }
99 // constexpr fails if wxASSERT contains assembler code, which is true on MinGW
100 CellDrawListIterator &operator++()
101 {
102 if (m_ptr)
103 {
104 const auto *const prev = m_ptr;
105 m_ptr = m_ptr->GetNextToDraw();
106 wxASSERT(prev != m_ptr);
107 }
108 return *this;
109 }
110 constexpr bool operator==(const CellDrawListIterator &o) const
111 { return m_ptr == o.m_ptr; }
112 constexpr bool operator!=(const CellDrawListIterator &o) const
113 { return m_ptr != o.m_ptr; }
114 constexpr operator bool() const { return m_ptr; }
115 constexpr operator Cell*() const { return m_ptr; }
116 constexpr Cell *operator->() const { return m_ptr; }
117};
118
119template <typename Cell> class CellDrawListAdapter final
120{
121 static_assert(std::is_class<Cell>::value, "The type argument must be a class");
122 Cell *m_cell = {};
125
126public:
127 explicit CellDrawListAdapter(Cell *cell) : m_cell(cell) {}
128 constexpr iterator begin() const { return iterator(m_cell); }
129 static constexpr iterator end() { return {}; }
130 constexpr const_iterator cbegin() const { return const_iterator(m_cell); }
131 static constexpr const_iterator cend() { return {}; }
132};
133
134class Cell;
135
138{
139 enum class Advance { Always, OnlyIfNull };
140 const Cell *m_parentCell = {};
141 Cell *m_innerCell = {};
142 size_t m_index = 0;
143 size_t m_endIndex = 0;
144
145 static size_t GetInnerCellCount(const Cell *cell);
146 static Cell *GetInnerCell(const Cell *cell, size_t index);
147public:
148 InnerCellIterator() = default;
149 explicit InnerCellIterator(Cell *parentCell) :
150 m_parentCell(parentCell),
151 m_endIndex(parentCell ? GetInnerCellCount(parentCell) : 0)
152 {
153 FindFirstInnerCell();
154 }
155 InnerCellIterator(const InnerCellIterator &o) = default;
156 InnerCellIterator &operator=(const InnerCellIterator &o) = default;
157 InnerCellIterator operator++(int)
158 {
159 auto ret = *this;
160 return operator++(), ret;
161 }
162 InnerCellIterator &operator++()
163 {
164 if (m_parentCell)
165 AdvanceLoop(Advance::Always);
166 return *this;
167 }
168 bool operator==(const InnerCellIterator &o) const
169 { return m_innerCell == o.m_innerCell; }
170 bool operator!=(const InnerCellIterator &o) const
171 { return m_innerCell != o.m_innerCell; }
172 operator bool() const { return m_innerCell; }
173 operator Cell*() const { return m_innerCell; }
174 Cell *operator->() const { return m_innerCell; }
175
176private:
177 void FindFirstInnerCell();
178 void AdvanceLoop(Advance mode);
179};
180
181inline void InnerCellIterator::FindFirstInnerCell()
182{
183 if (m_endIndex)
184 {
185 m_innerCell = GetInnerCell(m_parentCell, 0);
186 AdvanceLoop(Advance::OnlyIfNull);
187 }
188}
189
190inline void InnerCellIterator::AdvanceLoop(Advance mode)
191{
192 const Cell *prev = m_innerCell;
193 if (mode == Advance::OnlyIfNull && prev)
194 return;
195 for (;;)
196 {
197 ++m_index;
198 if (m_index == m_endIndex)
199 {
200 m_innerCell = nullptr;
201 break;
202 }
203 m_innerCell = GetInnerCell(m_parentCell, m_index);
204 wxASSERT(!prev || prev != m_innerCell);
205 if (m_innerCell)
206 break;
207 }
208}
209
210class InnerCellAdapter final {
212 iterator const m_iter;
213
214public:
215 explicit InnerCellAdapter(const iterator &) = delete;
216 explicit InnerCellAdapter(Cell *cell) : m_iter(cell) {}
217 iterator begin() const { return m_iter; }
218 static iterator end() { return {}; }
219};
220
221#endif
Definition: CellIterators.h:120
Definition: CellIterators.h:85
Definition: CellIterators.h:70
Definition: CellIterators.h:34
The base class all cell types the worksheet can consist of are derived from.
Definition: Cell.h:142
Cell * GetNextToDraw() const
Get the next cell that needs to be drawn.
Definition: Cell.h:701
Cell * GetNext() const
Get the next cell in the list.
Definition: Cell.h:694
Definition: CellIterators.h:210
Iterates the inner cells of a cell.
Definition: CellIterators.h:138