aboutsummaryrefslogtreecommitdiff
path: root/gcc/text-art/widget.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/text-art/widget.cc')
-rw-r--r--gcc/text-art/widget.cc276
1 files changed, 276 insertions, 0 deletions
diff --git a/gcc/text-art/widget.cc b/gcc/text-art/widget.cc
new file mode 100644
index 0000000..b64a623
--- /dev/null
+++ b/gcc/text-art/widget.cc
@@ -0,0 +1,276 @@
+/* Hierarchical diagram elements.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#define INCLUDE_MEMORY
+#define INCLUDE_VECTOR
+#include "system.h"
+#include "coretypes.h"
+#include "pretty-print.h"
+#include "selftest.h"
+#include "make-unique.h"
+#include "text-art/selftests.h"
+#include "text-art/widget.h"
+
+using namespace text_art;
+
+/* class text_art::widget. */
+
+canvas
+widget::to_canvas (const style_manager &style_mgr)
+{
+ const canvas::size_t req_size = get_req_size ();
+
+ /* For now we don't constrain the allocation; we give
+ the widget the full size it requested, and widgets
+ assume they got their full size request. */
+ const canvas::size_t alloc_size = req_size;
+
+ set_alloc_rect (canvas::rect_t (canvas::coord_t (0, 0), alloc_size));
+ canvas c (alloc_size, style_mgr);
+ paint_to_canvas (c);
+ return c;
+}
+
+/* class text_art::vbox_widget : public text_art::container_widget. */
+
+const char *
+vbox_widget::get_desc () const
+{
+ return "vbox_widget";
+}
+
+canvas::size_t
+vbox_widget::calc_req_size ()
+{
+ canvas::size_t result (0, 0);
+ for (auto &child : m_children)
+ {
+ canvas::size_t child_req_size = child->get_req_size();
+ result.h += child_req_size.h;
+ result.w = std::max (result.w, child_req_size.w);
+ }
+ return result;
+}
+
+void
+vbox_widget::update_child_alloc_rects ()
+{
+ const int x = get_min_x ();
+ int y = get_min_y ();
+ for (auto &child : m_children)
+ {
+ child->set_alloc_rect
+ (canvas::rect_t (canvas::coord_t (x, y),
+ canvas::size_t (get_alloc_w (),
+ child->get_req_h ())));
+ y += child->get_req_h ();
+ }
+}
+
+/* class text_art::text_widget : public text_art::leaf_widget. */
+
+const char *
+text_widget::get_desc () const
+{
+ return "text_widget";
+}
+
+canvas::size_t
+text_widget::calc_req_size ()
+{
+ return canvas::size_t (m_str.size (), 1);
+}
+
+void
+text_widget::paint_to_canvas (canvas &canvas)
+{
+ canvas.paint_text (get_top_left (), m_str);
+}
+
+/* class text_art::canvas_widget : public text_art::leaf_widget. */
+
+const char *
+canvas_widget::get_desc () const
+{
+ return "canvas_widget";
+}
+
+canvas::size_t
+canvas_widget::calc_req_size ()
+{
+ return m_canvas.get_size ();
+}
+
+void
+canvas_widget::paint_to_canvas (canvas &canvas)
+{
+ for (int y = 0; y < m_canvas.get_size ().h; y++)
+ for (int x = 0; x < m_canvas.get_size ().w; x++)
+ {
+ canvas::coord_t rel_xy (x, y);
+ canvas.paint (get_top_left () + rel_xy,
+ m_canvas.get (rel_xy));
+ }
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Concrete widget subclass for writing selftests.
+ Requests a hard-coded size, and fills its allocated rectangle
+ with a specific character. */
+
+class test_widget : public leaf_widget
+{
+public:
+ test_widget (canvas::size_t size, char ch)
+ : m_test_size (size), m_ch (ch)
+ {}
+
+ const char *get_desc () const final override
+ {
+ return "test_widget";
+ }
+ canvas::size_t calc_req_size () final override
+ {
+ return m_test_size;
+ }
+ void paint_to_canvas (canvas &canvas) final override
+ {
+ canvas.fill (get_alloc_rect (), canvas::cell_t (m_ch));
+ }
+
+private:
+ canvas::size_t m_test_size;
+ char m_ch;
+};
+
+static void
+test_test_widget ()
+{
+ style_manager sm;
+ test_widget w (canvas::size_t (3, 3), 'A');
+ canvas c (w.to_canvas (sm));
+ ASSERT_CANVAS_STREQ
+ (c, false,
+ ("AAA\n"
+ "AAA\n"
+ "AAA\n"));
+}
+
+static void
+test_text_widget ()
+{
+ style_manager sm;
+ text_widget w (styled_string (sm, "hello world"));
+ canvas c (w.to_canvas (sm));
+ ASSERT_CANVAS_STREQ
+ (c, false,
+ ("hello world\n"));
+}
+
+static void
+test_wrapper_widget ()
+{
+ style_manager sm;
+ wrapper_widget w (::make_unique<test_widget> (canvas::size_t (3, 3), 'B'));
+ canvas c (w.to_canvas (sm));
+ ASSERT_CANVAS_STREQ
+ (c, false,
+ ("BBB\n"
+ "BBB\n"
+ "BBB\n"));
+}
+
+static void
+test_vbox_1 ()
+{
+ style_manager sm;
+ vbox_widget w;
+ for (int i = 0; i < 5; i++)
+ w.add_child
+ (::make_unique <text_widget>
+ (styled_string::from_fmt (sm, nullptr,
+ "this is line %i", i)));
+ canvas c (w.to_canvas (sm));
+ ASSERT_CANVAS_STREQ
+ (c, false,
+ ("this is line 0\n"
+ "this is line 1\n"
+ "this is line 2\n"
+ "this is line 3\n"
+ "this is line 4\n"));
+}
+
+static void
+test_vbox_2 ()
+{
+ style_manager sm;
+ vbox_widget w;
+ w.add_child (::make_unique<test_widget> (canvas::size_t (1, 3), 'A'));
+ w.add_child (::make_unique<test_widget> (canvas::size_t (4, 1), 'B'));
+ w.add_child (::make_unique<test_widget> (canvas::size_t (1, 2), 'C'));
+ canvas c (w.to_canvas (sm));
+ ASSERT_CANVAS_STREQ
+ (c, false,
+ ("AAAA\n"
+ "AAAA\n"
+ "AAAA\n"
+ "BBBB\n"
+ "CCCC\n"
+ "CCCC\n"));
+}
+
+static void
+test_canvas_widget ()
+{
+ style_manager sm;
+ canvas inner_canvas (canvas::size_t (5, 3), sm);
+ inner_canvas.fill (canvas::rect_t (canvas::coord_t (0, 0),
+ canvas::size_t (5, 3)),
+ canvas::cell_t ('a'));
+ canvas_widget cw (std::move (inner_canvas));
+ canvas c (cw.to_canvas (sm));
+ ASSERT_CANVAS_STREQ
+ (c, false,
+ ("aaaaa\n"
+ "aaaaa\n"
+ "aaaaa\n"));
+}
+
+/* Run all selftests in this file. */
+
+void
+text_art_widget_cc_tests ()
+{
+ test_test_widget ();
+ test_text_widget ();
+ test_wrapper_widget ();
+ test_vbox_1 ();
+ test_vbox_2 ();
+ test_canvas_widget ();
+}
+
+} // namespace selftest
+
+
+#endif /* #if CHECKING_P */