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