Branch data Line data Source code
1 : : /* Support for tabular/grid-based content.
2 : : Copyright (C) 2023-2024 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 : 1725 : 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 : 1837 : void require (unsigned idx, int amount)
64 : : {
65 : 3513 : 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 : 9352 : class cell_placement
87 : : {
88 : : public:
89 : 2196 : cell_placement (rect_t rect,
90 : : table_cell_content &&content,
91 : : x_align x_align,
92 : : y_align y_align)
93 : 2196 : : m_rect (rect),
94 : 2196 : m_content (std::move (content)),
95 : 2196 : m_x_align (x_align),
96 : 2196 : m_y_align (y_align)
97 : : {
98 : : }
99 : :
100 : 4722 : bool one_by_one_p () const
101 : : {
102 : 4722 : return m_rect.m_size.w == 1 && m_rect.m_size.h == 1;
103 : : }
104 : :
105 : 4758 : canvas::size_t get_min_canvas_size () const
106 : : {
107 : : // Doesn't include border
108 : 4758 : 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 : 359 : ~table () = default;
128 : 424 : 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 : 262 : int add_rows (unsigned num)
135 : : {
136 : 262 : int topmost_new_row = m_size.h;
137 : 262 : m_size.h += num;
138 : 526 : for (unsigned i = 0; i < num; i++)
139 : 264 : m_occupancy.add_row (-1);
140 : 262 : return topmost_new_row;
141 : : }
142 : :
143 : 247 : int add_row ()
144 : : {
145 : 228 : 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 : 8123 : int get_col_width (int table_x) const
240 : : {
241 : 8123 : return m_cell_sizes.m_col_widths.m_requirements[table_x];
242 : : }
243 : :
244 : 2397 : canvas::size_t get_canvas_size (const table::rect_t &rect) const
245 : : {
246 : 2397 : 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 */
|