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