Branch data Line data Source code
1 : : /* Hierarchical diagram elements.
2 : : Copyright (C) 2023-2025 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 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.
11 : :
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.
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 : : #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 "text-art/selftests.h"
28 : : #include "text-art/widget.h"
29 : :
30 : : using namespace text_art;
31 : :
32 : : /* class text_art::widget. */
33 : :
34 : : canvas
35 : 112 : widget::to_canvas (const style_manager &style_mgr)
36 : : {
37 : 112 : const canvas::size_t req_size = get_req_size ();
38 : :
39 : : /* For now we don't constrain the allocation; we give
40 : : the widget the full size it requested, and widgets
41 : : assume they got their full size request. */
42 : 112 : const canvas::size_t alloc_size = req_size;
43 : :
44 : 112 : set_alloc_rect (canvas::rect_t (canvas::coord_t (0, 0), alloc_size));
45 : 112 : canvas c (alloc_size, style_mgr);
46 : 112 : paint_to_canvas (c);
47 : 112 : return c;
48 : : }
49 : :
50 : : /* class text_art::vbox_widget : public text_art::container_widget. */
51 : :
52 : : const char *
53 : 0 : vbox_widget::get_desc () const
54 : : {
55 : 0 : return "vbox_widget";
56 : : }
57 : :
58 : : canvas::size_t
59 : 76 : vbox_widget::calc_req_size ()
60 : : {
61 : 76 : canvas::size_t result (0, 0);
62 : 381 : for (auto &child : m_children)
63 : : {
64 : 305 : canvas::size_t child_req_size = child->get_req_size();
65 : 305 : result.h += child_req_size.h;
66 : 305 : result.w = std::max (result.w, child_req_size.w);
67 : : }
68 : 76 : return result;
69 : : }
70 : :
71 : : void
72 : 80 : vbox_widget::update_child_alloc_rects ()
73 : : {
74 : 80 : const int x = get_min_x ();
75 : 80 : int y = get_min_y ();
76 : 385 : for (auto &child : m_children)
77 : : {
78 : 305 : child->set_alloc_rect
79 : 610 : (canvas::rect_t (canvas::coord_t (x, y),
80 : : canvas::size_t (get_alloc_w (),
81 : 305 : child->get_req_h ())));
82 : 305 : y += child->get_req_h ();
83 : : }
84 : 80 : }
85 : :
86 : : /* class text_art::text_widget : public text_art::leaf_widget. */
87 : :
88 : : const char *
89 : 0 : text_widget::get_desc () const
90 : : {
91 : 0 : return "text_widget";
92 : : }
93 : :
94 : : canvas::size_t
95 : 140 : text_widget::calc_req_size ()
96 : : {
97 : 140 : return canvas::size_t (m_str.size (), 1);
98 : : }
99 : :
100 : : void
101 : 140 : text_widget::paint_to_canvas (canvas &canvas)
102 : : {
103 : 140 : canvas.paint_text (get_top_left (), m_str);
104 : 140 : }
105 : :
106 : : /* class text_art::canvas_widget : public text_art::leaf_widget. */
107 : :
108 : : const char *
109 : 0 : canvas_widget::get_desc () const
110 : : {
111 : 0 : return "canvas_widget";
112 : : }
113 : :
114 : : canvas::size_t
115 : 4 : canvas_widget::calc_req_size ()
116 : : {
117 : 4 : return m_canvas.get_size ();
118 : : }
119 : :
120 : : void
121 : 4 : canvas_widget::paint_to_canvas (canvas &canvas)
122 : : {
123 : 16 : for (int y = 0; y < m_canvas.get_size ().h; y++)
124 : 72 : for (int x = 0; x < m_canvas.get_size ().w; x++)
125 : : {
126 : 60 : canvas::coord_t rel_xy (x, y);
127 : 60 : canvas.paint (get_top_left () + rel_xy,
128 : 60 : m_canvas.get (rel_xy));
129 : : }
130 : 4 : }
131 : :
132 : : #if CHECKING_P
133 : :
134 : : namespace selftest {
135 : :
136 : : /* Concrete widget subclass for writing selftests.
137 : : Requests a hard-coded size, and fills its allocated rectangle
138 : : with a specific character. */
139 : :
140 : 4 : class test_widget : public leaf_widget
141 : : {
142 : : public:
143 : 20 : test_widget (canvas::size_t size, char ch)
144 : 4 : : m_test_size (size), m_ch (ch)
145 : : {}
146 : :
147 : 0 : const char *get_desc () const final override
148 : : {
149 : 0 : return "test_widget";
150 : : }
151 : 20 : canvas::size_t calc_req_size () final override
152 : : {
153 : 20 : return m_test_size;
154 : : }
155 : 20 : void paint_to_canvas (canvas &canvas) final override
156 : : {
157 : 20 : canvas.fill (get_alloc_rect (), canvas::cell_t (m_ch));
158 : 20 : }
159 : :
160 : : private:
161 : : canvas::size_t m_test_size;
162 : : char m_ch;
163 : : };
164 : :
165 : : static void
166 : 4 : test_test_widget ()
167 : : {
168 : 4 : style_manager sm;
169 : 4 : test_widget w (canvas::size_t (3, 3), 'A');
170 : 4 : canvas c (w.to_canvas (sm));
171 : 4 : ASSERT_CANVAS_STREQ
172 : : (c, false,
173 : : ("AAA\n"
174 : : "AAA\n"
175 : : "AAA\n"));
176 : 4 : }
177 : :
178 : : static void
179 : 4 : test_text_widget ()
180 : : {
181 : 4 : style_manager sm;
182 : 4 : text_widget w (styled_string (sm, "hello world"));
183 : 4 : canvas c (w.to_canvas (sm));
184 : 4 : ASSERT_CANVAS_STREQ
185 : : (c, false,
186 : : ("hello world\n"));
187 : 4 : }
188 : :
189 : : static void
190 : 4 : test_wrapper_widget ()
191 : : {
192 : 4 : style_manager sm;
193 : 4 : wrapper_widget w (std::make_unique<test_widget> (canvas::size_t (3, 3), 'B'));
194 : 4 : canvas c (w.to_canvas (sm));
195 : 4 : ASSERT_CANVAS_STREQ
196 : : (c, false,
197 : : ("BBB\n"
198 : : "BBB\n"
199 : : "BBB\n"));
200 : 4 : }
201 : :
202 : : static void
203 : 4 : test_empty_wrapper_widget ()
204 : : {
205 : 4 : style_manager sm;
206 : 4 : wrapper_widget w (nullptr);
207 : 4 : canvas c (w.to_canvas (sm));
208 : 4 : ASSERT_CANVAS_STREQ (c, false, "");
209 : 4 : }
210 : :
211 : : static void
212 : 4 : test_vbox_1 ()
213 : : {
214 : 4 : style_manager sm;
215 : 4 : vbox_widget w;
216 : 24 : for (int i = 0; i < 5; i++)
217 : 20 : w.add_child
218 : 20 : (std::make_unique <text_widget>
219 : 20 : (styled_string::from_fmt (sm, nullptr,
220 : : "this is line %i", i)));
221 : 4 : canvas c (w.to_canvas (sm));
222 : 4 : ASSERT_CANVAS_STREQ
223 : : (c, false,
224 : : ("this is line 0\n"
225 : : "this is line 1\n"
226 : : "this is line 2\n"
227 : : "this is line 3\n"
228 : : "this is line 4\n"));
229 : 4 : }
230 : :
231 : : static void
232 : 4 : test_vbox_2 ()
233 : : {
234 : 4 : style_manager sm;
235 : 4 : vbox_widget w;
236 : 4 : w.add_child (std::make_unique<test_widget> (canvas::size_t (1, 3), 'A'));
237 : 4 : w.add_child (std::make_unique<test_widget> (canvas::size_t (4, 1), 'B'));
238 : 4 : w.add_child (std::make_unique<test_widget> (canvas::size_t (1, 2), 'C'));
239 : 4 : canvas c (w.to_canvas (sm));
240 : 4 : ASSERT_CANVAS_STREQ
241 : : (c, false,
242 : : ("AAAA\n"
243 : : "AAAA\n"
244 : : "AAAA\n"
245 : : "BBBB\n"
246 : : "CCCC\n"
247 : : "CCCC\n"));
248 : 4 : }
249 : :
250 : : static void
251 : 4 : test_canvas_widget ()
252 : : {
253 : 4 : style_manager sm;
254 : 4 : canvas inner_canvas (canvas::size_t (5, 3), sm);
255 : 4 : inner_canvas.fill (canvas::rect_t (canvas::coord_t (0, 0),
256 : 4 : canvas::size_t (5, 3)),
257 : 4 : canvas::cell_t ('a'));
258 : 4 : canvas_widget cw (std::move (inner_canvas));
259 : 4 : canvas c (cw.to_canvas (sm));
260 : 4 : ASSERT_CANVAS_STREQ
261 : : (c, false,
262 : : ("aaaaa\n"
263 : : "aaaaa\n"
264 : : "aaaaa\n"));
265 : 4 : }
266 : :
267 : : /* Run all selftests in this file. */
268 : :
269 : : void
270 : 4 : text_art_widget_cc_tests ()
271 : : {
272 : 4 : test_test_widget ();
273 : 4 : test_text_widget ();
274 : 4 : test_wrapper_widget ();
275 : 4 : test_empty_wrapper_widget ();
276 : 4 : test_vbox_1 ();
277 : 4 : test_vbox_2 ();
278 : 4 : test_canvas_widget ();
279 : 4 : }
280 : :
281 : : } // namespace selftest
282 : :
283 : :
284 : : #endif /* #if CHECKING_P */
|