Line data Source code
1 : /* Support for tabular/grid-based content.
2 : Copyright (C) 2023-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #ifndef GCC_TEXT_ART_TABLE_H
22 : #define GCC_TEXT_ART_TABLE_H
23 :
24 : #include "text-art/canvas.h"
25 : #include "text-art/theme.h"
26 :
27 : namespace text_art {
28 :
29 : class table;
30 : class table_geometry;
31 :
32 : /* A class representing the content of a particular table cell,
33 : or of a span of table cells. */
34 :
35 1653 : class table_cell_content
36 : {
37 : public:
38 : table_cell_content () : m_str (), m_size (0, 0) {}
39 : table_cell_content (styled_string &&s);
40 :
41 120 : bool operator== (const table_cell_content &other) const
42 : {
43 120 : return m_str == other.m_str;
44 : }
45 :
46 8 : canvas::size_t get_canvas_size () const { return m_size; }
47 :
48 : void paint_to_canvas (canvas &canvas,
49 : canvas::coord_t top_left) const;
50 :
51 : private:
52 : styled_string m_str;
53 : canvas::size_t m_size;
54 : };
55 :
56 : /* A list of required sizes of table rows or columns
57 : in canvas units (row heights or column widths). */
58 :
59 144 : struct table_dimension_sizes
60 : {
61 : table_dimension_sizes (unsigned num);
62 :
63 1783 : void require (unsigned idx, int amount)
64 : {
65 3420 : m_requirements[idx] = std::max (m_requirements[idx], amount);
66 : }
67 :
68 : std::vector<int> m_requirements;
69 : };
70 :
71 : /* A 2D grid of cells. Instances of table_cell_content can be assigned
72 : to individual table cells, and to rectangular spans of cells. Such
73 : assignments do not have to fully cover the 2D grid, but they must not
74 : overlap. */
75 :
76 : class table
77 : {
78 : public:
79 : typedef size<class table> size_t;
80 : typedef coord<class table> coord_t;
81 : typedef range<class table> range_t;
82 : typedef rect<class table> rect_t;
83 :
84 : /* A record of how a table_cell_content was placed at a table::rect_t
85 : with a certain alignment. */
86 8892 : class cell_placement
87 : {
88 : public:
89 2090 : cell_placement (rect_t rect,
90 : table_cell_content &&content,
91 : x_align x_align,
92 : y_align y_align)
93 2090 : : m_rect (rect),
94 2090 : m_content (std::move (content)),
95 2090 : m_x_align (x_align),
96 2090 : m_y_align (y_align)
97 : {
98 : }
99 :
100 4582 : bool one_by_one_p () const
101 : {
102 4582 : return m_rect.m_size.w == 1 && m_rect.m_size.h == 1;
103 : }
104 :
105 4618 : canvas::size_t get_min_canvas_size () const
106 : {
107 : // Doesn't include border
108 4618 : return m_content.get_canvas_size ();
109 : }
110 :
111 : void paint_cell_contents_to_canvas(canvas &canvas,
112 : canvas::coord_t offset,
113 : const table_geometry &tg) const;
114 :
115 120 : const table_cell_content &get_content () const { return m_content; }
116 :
117 : private:
118 : friend class table;
119 : friend class table_cell_sizes;
120 : rect_t m_rect;
121 : table_cell_content m_content;
122 : x_align m_x_align;
123 : y_align m_y_align;
124 : };
125 :
126 : table (size_t size);
127 353 : ~table () = default;
128 422 : table (table &&) = default;
129 : table (const table &) = delete;
130 : table &operator= (const table &) = delete;
131 :
132 358 : const size_t &get_size () const { return m_size; }
133 :
134 248 : int add_rows (unsigned num)
135 : {
136 248 : int topmost_new_row = m_size.h;
137 248 : m_size.h += num;
138 498 : for (unsigned i = 0; i < num; i++)
139 250 : m_occupancy.add_row (-1);
140 248 : return topmost_new_row;
141 : }
142 :
143 235 : int add_row ()
144 : {
145 218 : return add_rows (1);
146 : }
147 :
148 : void set_cell (coord_t coord,
149 : table_cell_content &&content,
150 : enum x_align x_align = x_align::CENTER,
151 : enum y_align y_align = y_align::CENTER);
152 :
153 : void set_cell_span (rect_t span,
154 : table_cell_content &&content,
155 : enum x_align x_align = x_align::CENTER,
156 : enum y_align y_align = y_align::CENTER);
157 :
158 : void maybe_set_cell_span (rect_t span,
159 : table_cell_content &&content,
160 : enum x_align x_align = x_align::CENTER,
161 : enum y_align y_align = y_align::CENTER);
162 :
163 : canvas to_canvas (const theme &theme, const style_manager &sm) const;
164 :
165 : void paint_to_canvas(canvas &canvas,
166 : canvas::coord_t offset,
167 : const table_geometry &tg,
168 : const theme &theme) const;
169 :
170 : void debug () const;
171 :
172 : void add_other_table (table &&other, table::coord_t offset);
173 :
174 : /* Self-test support. */
175 : const cell_placement *get_placement_at (coord_t coord) const;
176 :
177 : private:
178 : int get_occupancy_safe (coord_t coord) const;
179 : directions get_connections (int table_x, int table_y) const;
180 : void paint_cell_borders_to_canvas(canvas &canvas,
181 : canvas::coord_t offset,
182 : const table_geometry &tg,
183 : const theme &theme) const;
184 : void paint_cell_contents_to_canvas(canvas &canvas,
185 : canvas::coord_t offset,
186 : const table_geometry &tg) const;
187 :
188 : friend class table_cell_sizes;
189 :
190 : size_t m_size;
191 : std::vector<cell_placement> m_placements;
192 : array2<int, size_t, coord_t> m_occupancy; /* indices into the m_placements vec. */
193 : };
194 :
195 : /* A workspace for computing the row heights and column widths
196 : of a table (in canvas units).
197 : The col_widths and row_heights could be shared between multiple
198 : instances, for aligning multiple tables vertically or horizontally. */
199 :
200 : class table_cell_sizes
201 : {
202 : public:
203 217 : table_cell_sizes (table_dimension_sizes &col_widths,
204 : table_dimension_sizes &row_heights)
205 217 : : m_col_widths (col_widths),
206 217 : m_row_heights (row_heights)
207 : {
208 : }
209 :
210 : void pass_1 (const table &table);
211 : void pass_2 (const table &table);
212 :
213 : canvas::size_t get_canvas_size (const table::rect_t &rect) const;
214 :
215 : table_dimension_sizes &m_col_widths;
216 : table_dimension_sizes &m_row_heights;
217 : };
218 :
219 : /* A class responsible for mapping from table cell coords
220 : to canvas coords, handling column widths.
221 : It's the result of solving "how big are all the table cells and where
222 : do they go?"
223 : The cell_sizes are passed in, for handling aligning multiple tables,
224 : sharing column widths or row heights. */
225 :
226 76 : class table_geometry
227 : {
228 : public:
229 : table_geometry (const table &table, table_cell_sizes &cell_sizes);
230 :
231 : void recalc_coords ();
232 :
233 659 : const canvas::size_t get_canvas_size () const { return m_canvas_size; }
234 :
235 : canvas::coord_t table_to_canvas (table::coord_t table_coord) const;
236 : int table_x_to_canvas_x (int table_x) const;
237 : int table_y_to_canvas_y (int table_y) const;
238 :
239 7855 : int get_col_width (int table_x) const
240 : {
241 7855 : return m_cell_sizes.m_col_widths.m_requirements[table_x];
242 : }
243 :
244 2327 : canvas::size_t get_canvas_size (const table::rect_t &rect) const
245 : {
246 2327 : return m_cell_sizes.get_canvas_size (rect);
247 : }
248 :
249 : private:
250 : table_cell_sizes &m_cell_sizes;
251 : canvas::size_t m_canvas_size;
252 :
253 : /* Start canvas column of table cell, including leading border. */
254 : std::vector<int> m_col_start_x;
255 :
256 : /* Start canvas row of table cell, including leading border. */
257 : std::vector<int> m_row_start_y;
258 : };
259 :
260 : /* Helper class for handling the simple case of a single table
261 : that doesn't need to be aligned with respect to anything else. */
262 :
263 : struct simple_table_geometry
264 : {
265 : simple_table_geometry (const table &table);
266 :
267 : table_dimension_sizes m_col_widths;
268 : table_dimension_sizes m_row_heights;
269 : table_cell_sizes m_cell_sizes;
270 : table_geometry m_tg;
271 : };
272 :
273 : } // namespace text_art
274 :
275 : #endif /* GCC_TEXT_ART_TABLE_H */
|