From 5d672e9eec43672188ed83c1e2d209130827165c Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Sun, 8 May 2022 19:31:31 +0300 Subject: [PATCH] add sizing based on text size --- src/Box.cpp | 27 +++++++++++++++++++++++++++ src/Box.hpp | 24 ++++++++++++++++++++++-- src/Button.cpp | 8 ++++++-- src/DocumentLayout.cpp | 5 +++-- src/Label.cpp | 7 ++++++- src/Painter.cpp | 15 ++++++++++----- src/Painter.hpp | 2 +- src/Widget.cpp | 23 +++++++++++++++++++++-- src/Widget.hpp | 9 +++++++-- src/main.cpp | 4 ---- 10 files changed, 103 insertions(+), 21 deletions(-) diff --git a/src/Box.cpp b/src/Box.cpp index 1bb054a..3fe7452 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -1,5 +1,6 @@ #include "Box.hpp" #include "Point.hpp" +#include namespace Raven { @@ -28,4 +29,30 @@ bool Box::contains_box(const Box &other) const { return boxes_overlap; } +void Box::set_width(double width) { + if (m_max_width != -1 && width > m_max_width) { + m_width = m_max_width; + } else if (m_min_width != -1 && width < m_min_width) { + m_width = m_min_width; + } else { + m_width = width; + } +} + +void Box::set_height(double height) { + if (m_max_height != -1 && height > m_max_height) { + m_height = m_max_height; + } else if (m_min_height != -1 && height < m_min_height) { + m_height = m_min_height; + } else { + m_height = height; + } +} + +Box Box::max_geometry() { + auto max_width = m_max_width == -1 ? m_width : m_max_width; + auto max_height = m_max_height == -1 ? m_height : m_max_height; + return Box{ m_x, m_y, max_width, max_height }; +} + } diff --git a/src/Box.hpp b/src/Box.hpp index 4a6e92a..68e3b5f 100644 --- a/src/Box.hpp +++ b/src/Box.hpp @@ -10,6 +10,11 @@ private: double m_y {0}; double m_width {0}; double m_height {0}; + + double m_max_width {-1}; + double m_max_height {-1}; + double m_min_width {-1}; + double m_min_height {-1}; public: Box() {} Box(double x, double y, double width, double height) @@ -21,20 +26,35 @@ public: } + Box max_geometry(); + double x() { return m_x; } double y() { return m_y; } double width() { return m_width; } double height() { return m_height; } + double min_width() { return m_min_width; } + double min_height() { return m_min_height; } + double max_width() { return m_max_width; } + double max_height() { return m_max_height; } double x() const { return m_x; } double y() const { return m_y; } double width() const { return m_width; } double height() const { return m_height; } + double min_width() const { return m_min_width; } + double min_height() const { return m_min_height; } + double max_width() const { return m_max_width; } + double max_height() const { return m_max_height; } void set_x(double x) { m_x = x; } void set_y(double y) { m_y = y; } - void set_width(double width) { m_width = width; } - void set_height(double height) { m_height = height; } + void set_width(double width); + void set_height(double height); + + void set_max_width(double max_width) { m_max_width = max_width; set_width(m_width); } + void set_max_height(double max_height) { m_max_height = max_height; set_height(m_height); } + void set_min_width(double min_width) { m_min_width = min_width; set_width(m_width); } + void set_min_height(double min_height) { m_min_height = min_height; set_height(m_height); } bool contains_point(double x, double y) const; bool contains_point(const Point &point) const; diff --git a/src/Button.cpp b/src/Button.cpp index c32283e..e26be46 100644 --- a/src/Button.cpp +++ b/src/Button.cpp @@ -26,12 +26,16 @@ void Button::update_color() { } void Button::on_paint() { - auto painter = window()->painter(); + do_generic_paint(); + auto painter = window()->painter(); auto text_color = styles()->button_text_color(); + auto max_geometry = current_geometry().max_geometry(); + painter.source_rgb(text_color); painter.set_pango_font_description(styles()->controls_font_description()); - painter.text(current_geometry(), m_text, PaintTextAlign::Center, PANGO_ELLIPSIZE_END); + auto point = painter.text(max_geometry, m_text, PaintTextAlign::Center, PANGO_ELLIPSIZE_END); + resize(point); painter.fill(); } diff --git a/src/DocumentLayout.cpp b/src/DocumentLayout.cpp index cd3d44b..852758e 100644 --- a/src/DocumentLayout.cpp +++ b/src/DocumentLayout.cpp @@ -1,6 +1,7 @@ #include "DocumentLayout.hpp" #include "Point.hpp" #include "Widget.hpp" +#include namespace Raven { @@ -21,8 +22,8 @@ void DocumentLayout::run() { if (c->current_geometry().height() > row_largest_height) { row_largest_height = c->current_geometry().height(); } - auto new_geometry = Box{ point.x(), point.y(), c->current_geometry().width(), c->current_geometry().height() }; - c->set_current_geometry(std::move(new_geometry), true); + c->current_geometry().set_x(point.x()); + c->current_geometry().set_y(point.y()); point.add(c->current_geometry().width() + m_margin, 0); } } diff --git a/src/Label.cpp b/src/Label.cpp index 39e921d..7961fc6 100644 --- a/src/Label.cpp +++ b/src/Label.cpp @@ -1,6 +1,7 @@ #include "Label.hpp" #include "Window.hpp" #include "pango/pango-layout.h" +#include namespace Raven { @@ -14,12 +15,16 @@ void Label::on_init() { } void Label::on_paint() { + do_generic_paint(); + auto painter = window()->painter(); auto text_color = styles()->label_text_color(); + auto text_geometry = current_geometry().max_geometry(); painter.source_rgb(text_color); painter.set_pango_font_description(styles()->controls_font_description()); - painter.text(current_geometry(), m_text, PaintTextAlign::Left, PANGO_ELLIPSIZE_NONE); + auto point = painter.text(text_geometry, m_text, PaintTextAlign::Left, PANGO_ELLIPSIZE_NONE); + resize(point); painter.fill(); } diff --git a/src/Painter.cpp b/src/Painter.cpp index 330e392..4c56834 100644 --- a/src/Painter.cpp +++ b/src/Painter.cpp @@ -39,22 +39,27 @@ bool Painter::text(Point &where, std::string &text) { return true; } -bool Painter::text(Box &geometry, std::string &text, PaintTextAlign align, PangoEllipsizeMode ellipsize) { +Point Painter::text(Box &geometry, std::string &text, PaintTextAlign align, PangoEllipsizeMode ellipsize) { if (m_pango_font_description == nullptr) - return false; + return {-1,-1}; PangoLayout *layout = pango_cairo_create_layout(m_cairo->cobj()); int font_width; int font_height; + int pango_width; + int pango_height; pango_layout_set_font_description(layout, m_pango_font_description); - pango_layout_set_width(layout, pango_units_from_double(geometry.width())); - pango_layout_set_height(layout, pango_units_from_double(geometry.height())); + if (geometry.width() > 0) + pango_layout_set_width(layout, pango_units_from_double(geometry.width())); + if (geometry.height() > 0) + pango_layout_set_height(layout, pango_units_from_double(geometry.height())); pango_layout_set_ellipsize(layout, ellipsize); pango_layout_set_text(layout, text.c_str(), -1); pango_layout_get_pixel_size(layout, &font_width, &font_height); + pango_layout_get_size(layout, &pango_width, &pango_height); double x = -1; double y = geometry.y() + ((geometry.height() - font_height) / 2); @@ -70,7 +75,7 @@ bool Painter::text(Box &geometry, std::string &text, PaintTextAlign align, Pango g_object_unref(layout); - return true; + return {pango_units_to_double(pango_width), pango_units_to_double(pango_height)}; } void Painter::source_rgb(RGB &source_rgb) { diff --git a/src/Painter.hpp b/src/Painter.hpp index ecbae09..9e6c097 100644 --- a/src/Painter.hpp +++ b/src/Painter.hpp @@ -29,7 +29,7 @@ public: void rounded_rectangle(Box &geometry, double border_radius); bool text(Point &where, std::string &text); - bool text(Box &geometry, std::string &text, PaintTextAlign align, PangoEllipsizeMode ellipsize); + Point text(Box &geometry, std::string &text, PaintTextAlign align, PangoEllipsizeMode ellipsize); bool can_paint() { if (m_cairo) return true; else return false; } diff --git a/src/Widget.cpp b/src/Widget.cpp index 93577c9..d3277c7 100644 --- a/src/Widget.cpp +++ b/src/Widget.cpp @@ -9,6 +9,27 @@ namespace Raven { +void Widget::resize(double width, double height) { + if (m_current_geometry.width() == width && m_current_geometry.height() == height) + return; + + if (width < 0 || height < 0) + return; + + m_current_geometry.set_width(width); + m_current_geometry.set_height(height); + wants_full_relayout(); +} + +void Widget::move_to(double x, double y) { + if (m_current_geometry.x() == x && m_current_geometry.y() == y) + return; + + m_current_geometry.set_x(x); + m_current_geometry.set_y(y); + wants_full_relayout(); +} + void Widget::do_layout() { if (m_layout) { m_layout->run(); @@ -112,8 +133,6 @@ void Widget::handle_repaint(WidgetRepaintRequestedEvent &event) { painter.begin_paint_group(); } - do_generic_paint(); - cr->save(); on_paint(); cr->restore(); diff --git a/src/Widget.hpp b/src/Widget.hpp index 4b73d13..2675932 100644 --- a/src/Widget.hpp +++ b/src/Widget.hpp @@ -59,6 +59,10 @@ public: void set_current_geometry(Box current_geometry) { m_current_geometry = current_geometry; wants_full_relayout(); } void set_current_geometry(Box current_geometry, bool is_pure) { m_current_geometry = current_geometry; if (!is_pure) { wants_full_relayout(); } } + void move_to(double x, double y); + void resize(double width, double height); + void resize(Point &point) { resize(point.x(), point.y()); } + std::vector> &children() { return m_children; } bool add_child(std::shared_ptr child); void remove_child(std::shared_ptr child); @@ -118,13 +122,14 @@ protected: virtual void on_mouse_move(MouseMoveEvent &event) {} virtual void on_focus_update(FocusUpdateEvent &event) {} virtual void on_activation_update(ActivationUpdateEvent &event) {} - virtual void on_paint() {} + virtual void on_paint() { do_generic_paint(); } + + void do_generic_paint(); private: void wants_full_repaint(); void wants_full_relayout(); void do_layout(); void handle_repaint(WidgetRepaintRequestedEvent& event); - void do_generic_paint(); void handle_mouse_move_event(MouseMoveEvent &event); void handle_mouse_button_event(MouseButtonEvent &event); }; diff --git a/src/main.cpp b/src/main.cpp index 389e659..3005a01 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,10 +22,6 @@ int main() { window.spawn_window(); - add_button->set_current_geometry(Raven::Box(0, 0, 100, 30)); - subtract_button->set_current_geometry(Raven::Box(0, 0, 100, 30)); - label->set_current_geometry(Raven::Box(0, 0, 100, 20)); - add_button->on_click = [&]() { number++; label->set_text(std::to_string(number));