[PR target/115123] Fix testsuite fallout from sinking heuristic change
[official-gcc.git] / gcc / text-art / tree-widget.cc
blob597374fdd41f6b04d0a0442a8c0ab46eeeaf3c5a
1 /* Tree diagrams.
2 Copyright (C) 2024-2025 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_VECTOR
23 #include "system.h"
24 #include "coretypes.h"
25 #include "pretty-print.h"
26 #include "selftest.h"
27 #include "make-unique.h"
28 #include "text-art/selftests.h"
29 #include "text-art/tree-widget.h"
30 #include "text-art/dump-widget-info.h"
32 using namespace text_art;
34 /* class text_art::tree_widget : public text_art::widget. */
36 static const int margin_width = 3;
38 std::unique_ptr<tree_widget>
39 tree_widget::make (styled_string str, const theme &theme, style::id_t style_id)
41 return ::make_unique <tree_widget>
42 (::make_unique <text_widget> (std::move (str)),
43 theme,
44 style_id);
47 std::unique_ptr<tree_widget>
48 tree_widget::make (const dump_widget_info &dwi, pretty_printer *pp)
50 return tree_widget::make (styled_string (dwi.m_sm, pp_formatted_text (pp)),
51 dwi.m_theme,
52 dwi.get_tree_style_id ());
55 std::unique_ptr<tree_widget>
56 tree_widget::make (const dump_widget_info &dwi, const char *str)
58 return tree_widget::make (styled_string (dwi.m_sm, str),
59 dwi.m_theme,
60 dwi.get_tree_style_id ());
63 std::unique_ptr<tree_widget>
64 tree_widget::from_fmt (const dump_widget_info &dwi,
65 printer_fn format_decoder,
66 const char *fmt, ...)
68 va_list ap;
69 va_start (ap, fmt);
70 styled_string styled_str
71 (styled_string::from_fmt_va (dwi.m_sm, format_decoder, fmt, &ap));
72 va_end (ap);
73 return make (std::move (styled_str), dwi.m_theme, dwi.get_tree_style_id ());
76 const char *
77 tree_widget::get_desc () const
79 return "tree_widget";
82 canvas::size_t
83 tree_widget::calc_req_size ()
85 canvas::size_t result (0, 0);
86 if (m_node)
88 canvas::size_t node_req_size = m_node->get_req_size ();
89 result.h += node_req_size.h;
90 result.w = std::max (result.w, node_req_size.w);
92 for (auto &child : m_children)
94 canvas::size_t child_req_size = child->get_req_size ();
95 result.h += child_req_size.h;
96 result.w = std::max (result.w, child_req_size.w + margin_width);
98 return result;
101 void
102 tree_widget::update_child_alloc_rects ()
104 const int x = get_min_x ();
105 int y = get_min_y ();
106 if (m_node)
108 m_node->set_alloc_rect
109 (canvas::rect_t (canvas::coord_t (x, y),
110 canvas::size_t (get_alloc_w (),
111 m_node->get_req_h ())));
112 y += m_node->get_req_h ();
114 for (auto &child : m_children)
116 child->set_alloc_rect
117 (canvas::rect_t (canvas::coord_t (x + margin_width, y),
118 canvas::size_t (get_alloc_w () - margin_width,
119 child->get_req_h ())));
120 y += child->get_req_h ();
124 void
125 tree_widget::paint_to_canvas (canvas &canvas)
127 if (m_node)
128 m_node->paint_to_canvas (canvas);
129 const int min_x = get_min_x ();
130 const canvas::cell_t cell_child_non_final
131 (m_theme.get_cell (theme::cell_kind::TREE_CHILD_NON_FINAL, m_style_id));
132 const canvas::cell_t cell_child_final
133 (m_theme.get_cell (theme::cell_kind::TREE_CHILD_FINAL, m_style_id));
134 const canvas::cell_t cell_x_connector
135 (m_theme.get_cell (theme::cell_kind::TREE_X_CONNECTOR, m_style_id));
136 const canvas::cell_t cell_y_connector
137 (m_theme.get_cell (theme::cell_kind::TREE_Y_CONNECTOR, m_style_id));
138 size_t idx = 0;
139 for (auto &child : m_children)
141 child->paint_to_canvas (canvas);
143 const bool last_child = (++idx == m_children.size ());
144 canvas.paint (canvas::coord_t (min_x + 1, child->get_min_y ()),
145 cell_x_connector);
146 canvas.paint (canvas::coord_t (min_x, child->get_min_y ()),
147 last_child ? cell_child_final : cell_child_non_final);
148 if (!last_child)
149 for (int y = child->get_min_y () + 1; y <= child ->get_max_y (); y++)
150 canvas.paint (canvas::coord_t (min_x, y), cell_y_connector);
154 #if CHECKING_P
156 namespace selftest {
158 static std::unique_ptr<tree_widget>
159 make_test_tree_widget (const dump_widget_info &dwi)
161 std::unique_ptr<tree_widget> w
162 (tree_widget::from_fmt (dwi, nullptr, "Root"));
163 for (int i = 0; i < 3; i++)
165 std::unique_ptr<tree_widget> c
166 (tree_widget::from_fmt (dwi, nullptr, "Child %i", i));
167 for (int j = 0; j < 3; j++)
168 c->add_child (tree_widget::from_fmt (dwi, nullptr,
169 "Grandchild %i %i", i, j));
170 w->add_child (std::move (c));
172 return w;
175 static void
176 test_tree_widget ()
178 style_manager sm;
180 style::id_t default_style_id (sm.get_or_create_id (style ()));
183 ascii_theme theme;
184 dump_widget_info dwi (sm, theme, default_style_id);
185 canvas c (make_test_tree_widget (dwi)->to_canvas (sm));
186 ASSERT_CANVAS_STREQ
187 (c, false,
188 ("Root\n"
189 "+- Child 0\n"
190 "| +- Grandchild 0 0\n"
191 "| +- Grandchild 0 1\n"
192 "| `- Grandchild 0 2\n"
193 "+- Child 1\n"
194 "| +- Grandchild 1 0\n"
195 "| +- Grandchild 1 1\n"
196 "| `- Grandchild 1 2\n"
197 "`- Child 2\n"
198 " +- Grandchild 2 0\n"
199 " +- Grandchild 2 1\n"
200 " `- Grandchild 2 2\n"));
204 unicode_theme theme;
205 dump_widget_info dwi (sm, theme, default_style_id);
206 canvas c (make_test_tree_widget (dwi)->to_canvas (sm));
207 ASSERT_CANVAS_STREQ
208 (c, false,
209 ("Root\n"
210 "├─ Child 0\n"
211 "│ ├─ Grandchild 0 0\n"
212 "│ ├─ Grandchild 0 1\n"
213 "│ ╰─ Grandchild 0 2\n"
214 "├─ Child 1\n"
215 "│ ├─ Grandchild 1 0\n"
216 "│ ├─ Grandchild 1 1\n"
217 "│ ╰─ Grandchild 1 2\n"
218 "╰─ Child 2\n"
219 " ├─ Grandchild 2 0\n"
220 " ├─ Grandchild 2 1\n"
221 " ╰─ Grandchild 2 2\n"));
225 /* Run all selftests in this file. */
227 void
228 text_art_tree_widget_cc_tests ()
230 test_tree_widget ();
233 } // namespace selftest
236 #endif /* #if CHECKING_P */