libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / text-art / tree-widget.cc
blob69282e46a44c3b2db771efca667fb836c53b80d9
1 /* Tree diagrams.
2 Copyright (C) 2024 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
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/>. */
21 #include "config.h"
22 #define INCLUDE_MEMORY
23 #define INCLUDE_VECTOR
24 #include "system.h"
25 #include "coretypes.h"
26 #include "pretty-print.h"
27 #include "selftest.h"
28 #include "make-unique.h"
29 #include "text-art/selftests.h"
30 #include "text-art/tree-widget.h"
31 #include "text-art/dump-widget-info.h"
33 using namespace text_art;
35 /* class text_art::tree_widget : public text_art::widget. */
37 static const int margin_width = 3;
39 std::unique_ptr<tree_widget>
40 tree_widget::make (styled_string str, const theme &theme, style::id_t style_id)
42 return ::make_unique <tree_widget>
43 (::make_unique <text_widget> (std::move (str)),
44 theme,
45 style_id);
48 std::unique_ptr<tree_widget>
49 tree_widget::make (const dump_widget_info &dwi, pretty_printer *pp)
51 return tree_widget::make (styled_string (dwi.m_sm, pp_formatted_text (pp)),
52 dwi.m_theme,
53 dwi.get_tree_style_id ());
56 std::unique_ptr<tree_widget>
57 tree_widget::make (const dump_widget_info &dwi, const char *str)
59 return tree_widget::make (styled_string (dwi.m_sm, str),
60 dwi.m_theme,
61 dwi.get_tree_style_id ());
64 std::unique_ptr<tree_widget>
65 tree_widget::from_fmt (const dump_widget_info &dwi,
66 printer_fn format_decoder,
67 const char *fmt, ...)
69 va_list ap;
70 va_start (ap, fmt);
71 styled_string styled_str
72 (styled_string::from_fmt_va (dwi.m_sm, format_decoder, fmt, &ap));
73 va_end (ap);
74 return make (std::move (styled_str), dwi.m_theme, dwi.get_tree_style_id ());
77 const char *
78 tree_widget::get_desc () const
80 return "tree_widget";
83 canvas::size_t
84 tree_widget::calc_req_size ()
86 canvas::size_t result (0, 0);
87 if (m_node)
89 canvas::size_t node_req_size = m_node->get_req_size ();
90 result.h += node_req_size.h;
91 result.w = std::max (result.w, node_req_size.w);
93 for (auto &child : m_children)
95 canvas::size_t child_req_size = child->get_req_size ();
96 result.h += child_req_size.h;
97 result.w = std::max (result.w, child_req_size.w + margin_width);
99 return result;
102 void
103 tree_widget::update_child_alloc_rects ()
105 const int x = get_min_x ();
106 int y = get_min_y ();
107 if (m_node)
109 m_node->set_alloc_rect
110 (canvas::rect_t (canvas::coord_t (x, y),
111 canvas::size_t (get_alloc_w (),
112 m_node->get_req_h ())));
113 y += m_node->get_req_h ();
115 for (auto &child : m_children)
117 child->set_alloc_rect
118 (canvas::rect_t (canvas::coord_t (x + margin_width, y),
119 canvas::size_t (get_alloc_w () - margin_width,
120 child->get_req_h ())));
121 y += child->get_req_h ();
125 void
126 tree_widget::paint_to_canvas (canvas &canvas)
128 if (m_node)
129 m_node->paint_to_canvas (canvas);
130 const int min_x = get_min_x ();
131 const canvas::cell_t cell_child_non_final
132 (m_theme.get_cell (theme::cell_kind::TREE_CHILD_NON_FINAL, m_style_id));
133 const canvas::cell_t cell_child_final
134 (m_theme.get_cell (theme::cell_kind::TREE_CHILD_FINAL, m_style_id));
135 const canvas::cell_t cell_x_connector
136 (m_theme.get_cell (theme::cell_kind::TREE_X_CONNECTOR, m_style_id));
137 const canvas::cell_t cell_y_connector
138 (m_theme.get_cell (theme::cell_kind::TREE_Y_CONNECTOR, m_style_id));
139 size_t idx = 0;
140 for (auto &child : m_children)
142 child->paint_to_canvas (canvas);
144 const bool last_child = (++idx == m_children.size ());
145 canvas.paint (canvas::coord_t (min_x + 1, child->get_min_y ()),
146 cell_x_connector);
147 canvas.paint (canvas::coord_t (min_x, child->get_min_y ()),
148 last_child ? cell_child_final : cell_child_non_final);
149 if (!last_child)
150 for (int y = child->get_min_y () + 1; y <= child ->get_max_y (); y++)
151 canvas.paint (canvas::coord_t (min_x, y), cell_y_connector);
155 #if CHECKING_P
157 namespace selftest {
159 static std::unique_ptr<tree_widget>
160 make_test_tree_widget (const dump_widget_info &dwi)
162 std::unique_ptr<tree_widget> w
163 (tree_widget::from_fmt (dwi, nullptr, "Root"));
164 for (int i = 0; i < 3; i++)
166 std::unique_ptr<tree_widget> c
167 (tree_widget::from_fmt (dwi, nullptr, "Child %i", i));
168 for (int j = 0; j < 3; j++)
169 c->add_child (tree_widget::from_fmt (dwi, nullptr,
170 "Grandchild %i %i", i, j));
171 w->add_child (std::move (c));
173 return w;
176 static void
177 test_tree_widget ()
179 style_manager sm;
181 style::id_t default_style_id (sm.get_or_create_id (style ()));
184 ascii_theme theme;
185 dump_widget_info dwi (sm, theme, default_style_id);
186 canvas c (make_test_tree_widget (dwi)->to_canvas (sm));
187 ASSERT_CANVAS_STREQ
188 (c, false,
189 ("Root\n"
190 "+- Child 0\n"
191 "| +- Grandchild 0 0\n"
192 "| +- Grandchild 0 1\n"
193 "| `- Grandchild 0 2\n"
194 "+- Child 1\n"
195 "| +- Grandchild 1 0\n"
196 "| +- Grandchild 1 1\n"
197 "| `- Grandchild 1 2\n"
198 "`- Child 2\n"
199 " +- Grandchild 2 0\n"
200 " +- Grandchild 2 1\n"
201 " `- Grandchild 2 2\n"));
205 unicode_theme theme;
206 dump_widget_info dwi (sm, theme, default_style_id);
207 canvas c (make_test_tree_widget (dwi)->to_canvas (sm));
208 ASSERT_CANVAS_STREQ
209 (c, false,
210 ("Root\n"
211 "├─ Child 0\n"
212 "│ ├─ Grandchild 0 0\n"
213 "│ ├─ Grandchild 0 1\n"
214 "│ ╰─ Grandchild 0 2\n"
215 "├─ Child 1\n"
216 "│ ├─ Grandchild 1 0\n"
217 "│ ├─ Grandchild 1 1\n"
218 "│ ╰─ Grandchild 1 2\n"
219 "╰─ Child 2\n"
220 " ├─ Grandchild 2 0\n"
221 " ├─ Grandchild 2 1\n"
222 " ╰─ Grandchild 2 2\n"));
226 /* Run all selftests in this file. */
228 void
229 text_art_tree_widget_cc_tests ()
231 test_tree_widget ();
234 } // namespace selftest
237 #endif /* #if CHECKING_P */