aboutsummaryrefslogtreecommitdiff
path: root/gcc/text-art/table.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/text-art/table.h')
-rw-r--r--gcc/text-art/table.h261
1 files changed, 261 insertions, 0 deletions
diff --git a/gcc/text-art/table.h b/gcc/text-art/table.h
new file mode 100644
index 0000000..2dc5c3c
--- /dev/null
+++ b/gcc/text-art/table.h
@@ -0,0 +1,261 @@
+/* Support for tabular/grid-based content.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_TEXT_ART_TABLE_H
+#define GCC_TEXT_ART_TABLE_H
+
+#include "text-art/canvas.h"
+#include "text-art/theme.h"
+
+namespace text_art {
+
+class table;
+class table_geometry;
+
+/* A class representing the content of a particular table cell,
+ or of a span of table cells. */
+
+class table_cell_content
+{
+ public:
+ table_cell_content () : m_str (), m_size (0, 0) {}
+ table_cell_content (styled_string &&s);
+
+ bool operator== (const table_cell_content &other) const
+ {
+ return m_str == other.m_str;
+ }
+
+ canvas::size_t get_canvas_size () const { return m_size; }
+
+ void paint_to_canvas (canvas &canvas,
+ canvas::coord_t top_left) const;
+
+ private:
+ styled_string m_str;
+ canvas::size_t m_size;
+};
+
+/* A list of required sizes of table rows or columns
+ in canvas units (row heights or column widths). */
+
+struct table_dimension_sizes
+{
+ table_dimension_sizes (unsigned num);
+
+ void require (unsigned idx, int amount)
+ {
+ m_requirements[idx] = std::max (m_requirements[idx], amount);
+ }
+
+ std::vector<int> m_requirements;
+};
+
+/* A 2D grid of cells. Instances of table_cell_content can be assigned
+ to individual table cells, and to rectangular spans of cells. Such
+ assignments do not have to fully cover the 2D grid, but they must not
+ overlap. */
+
+class table
+{
+ public:
+ typedef size<class table> size_t;
+ typedef coord<class table> coord_t;
+ typedef range<class table> range_t;
+ typedef rect<class table> rect_t;
+
+ /* A record of how a table_cell_content was placed at a table::rect_t
+ with a certain alignment. */
+ class cell_placement
+ {
+ public:
+ cell_placement (rect_t rect,
+ table_cell_content &&content,
+ x_align x_align,
+ y_align y_align)
+ : m_rect (rect),
+ m_content (std::move (content)),
+ m_x_align (x_align),
+ m_y_align (y_align)
+ {
+ }
+
+ bool one_by_one_p () const
+ {
+ return m_rect.m_size.w == 1 && m_rect.m_size.h == 1;
+ }
+
+ canvas::size_t get_min_canvas_size () const
+ {
+ // Doesn't include border
+ return m_content.get_canvas_size ();
+ }
+
+ void paint_cell_contents_to_canvas(canvas &canvas,
+ canvas::coord_t offset,
+ const table_geometry &tg) const;
+
+ const table_cell_content &get_content () const { return m_content; }
+
+ private:
+ friend class table_cell_sizes;
+ rect_t m_rect;
+ table_cell_content m_content;
+ x_align m_x_align;
+ y_align m_y_align;
+ };
+
+ table (size_t size);
+ ~table () = default;
+ table (table &&) = default;
+ table (const table &) = delete;
+ table &operator= (const table &) = delete;
+
+ const size_t &get_size () const { return m_size; }
+
+ int add_row ()
+ {
+ m_size.h++;
+ m_occupancy.add_row (-1);
+ return m_size.h - 1; // return the table_y of the newly-added row
+ }
+
+ void set_cell (coord_t coord,
+ table_cell_content &&content,
+ enum x_align x_align = x_align::CENTER,
+ enum y_align y_align = y_align::CENTER);
+
+ void set_cell_span (rect_t span,
+ table_cell_content &&content,
+ enum x_align x_align = x_align::CENTER,
+ enum y_align y_align = y_align::CENTER);
+
+ canvas to_canvas (const theme &theme, const style_manager &sm) const;
+
+ void paint_to_canvas(canvas &canvas,
+ canvas::coord_t offset,
+ const table_geometry &tg,
+ const theme &theme) const;
+
+ void debug () const;
+
+ /* Self-test support. */
+ const cell_placement *get_placement_at (coord_t coord) const;
+
+ private:
+ int get_occupancy_safe (coord_t coord) const;
+ directions get_connections (int table_x, int table_y) const;
+ void paint_cell_borders_to_canvas(canvas &canvas,
+ canvas::coord_t offset,
+ const table_geometry &tg,
+ const theme &theme) const;
+ void paint_cell_contents_to_canvas(canvas &canvas,
+ canvas::coord_t offset,
+ const table_geometry &tg) const;
+
+ friend class table_cell_sizes;
+
+ size_t m_size;
+ std::vector<cell_placement> m_placements;
+ array2<int, size_t, coord_t> m_occupancy; /* indices into the m_placements vec. */
+};
+
+/* A workspace for computing the row heights and column widths
+ of a table (in canvas units).
+ The col_widths and row_heights could be shared between multiple
+ instances, for aligning multiple tables vertically or horizontally. */
+
+class table_cell_sizes
+{
+ public:
+ table_cell_sizes (table_dimension_sizes &col_widths,
+ table_dimension_sizes &row_heights)
+ : m_col_widths (col_widths),
+ m_row_heights (row_heights)
+ {
+ }
+
+ void pass_1 (const table &table);
+ void pass_2 (const table &table);
+
+ canvas::size_t get_canvas_size (const table::rect_t &rect) const;
+
+ table_dimension_sizes &m_col_widths;
+ table_dimension_sizes &m_row_heights;
+};
+
+/* A class responsible for mapping from table cell coords
+ to canvas coords, handling column widths.
+ It's the result of solving "how big are all the table cells and where
+ do they go?"
+ The cell_sizes are passed in, for handling aligning multiple tables,
+ sharing column widths or row heights. */
+
+class table_geometry
+{
+ public:
+ table_geometry (const table &table, table_cell_sizes &cell_sizes);
+
+ void recalc_coords ();
+
+ const canvas::size_t get_canvas_size () const { return m_canvas_size; }
+
+ canvas::coord_t table_to_canvas (table::coord_t table_coord) const;
+ int table_x_to_canvas_x (int table_x) const;
+ int table_y_to_canvas_y (int table_y) const;
+
+ int get_col_width (int table_x) const
+ {
+ return m_cell_sizes.m_col_widths.m_requirements[table_x];
+ }
+
+ canvas::size_t get_canvas_size (const table::rect_t &rect) const
+ {
+ return m_cell_sizes.get_canvas_size (rect);
+ }
+
+ private:
+ const table &m_table;
+ table_cell_sizes &m_cell_sizes;
+ canvas::size_t m_canvas_size;
+
+ /* Start canvas column of table cell, including leading border. */
+ std::vector<int> m_col_start_x;
+
+ /* Start canvas row of table cell, including leading border. */
+ std::vector<int> m_row_start_y;
+};
+
+/* Helper class for handling the simple case of a single table
+ that doesn't need to be aligned with respect to anything else. */
+
+struct simple_table_geometry
+{
+ simple_table_geometry (const table &table);
+
+ table_dimension_sizes m_col_widths;
+ table_dimension_sizes m_row_heights;
+ table_cell_sizes m_cell_sizes;
+ table_geometry m_tg;
+};
+
+} // namespace text_art
+
+#endif /* GCC_TEXT_ART_TABLE_H */