From f0acf9522da510fea1a9dbf843e50cc75deab654 Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Tue, 18 Oct 2022 23:28:48 +0300 Subject: [PATCH] silly boxlayout automatic sizing --- src/Box.cpp | 10 +++++++++- src/Box.hpp | 1 + src/BoxLayout.cpp | 37 +++++++++++++++++++++++++++++++++---- src/BoxLayout.hpp | 8 +++++++- src/Button.cpp | 4 ++-- src/Button.hpp | 4 ++++ src/ColumnLayout.cpp | 6 ++++-- src/ColumnLayout.hpp | 2 +- src/DocumentLayout.cpp | 6 ++++-- src/DocumentLayout.hpp | 2 +- src/Layout.hpp | 4 +++- src/RowLayout.cpp | 6 ++++-- src/RowLayout.hpp | 2 +- src/Widget.cpp | 14 +++++++++----- src/Widget.hpp | 2 +- src/main.cpp | 6 ++++-- 16 files changed, 88 insertions(+), 26 deletions(-) diff --git a/src/Box.cpp b/src/Box.cpp index c38d91c..a9a1bdf 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -95,6 +95,14 @@ double Box::clamp_for_dimension(Direction direction, double value) { } } +void Box::set_dimension(Direction direction, double value) { + if (direction == Direction::Horizontal) { + set_width(value); + } else { + set_height(value); + } +} + Box Box::united(const Box &other) { if (is_null()) { return other; @@ -112,7 +120,7 @@ Box Box::united(const Box &other) { } bool Box::is_null() const { - return !(m_x && m_y && m_width && m_height); + return !(m_x || m_y || m_width || m_height); } std::string Box::debug() { diff --git a/src/Box.hpp b/src/Box.hpp index d99c5ca..a1dcb47 100644 --- a/src/Box.hpp +++ b/src/Box.hpp @@ -70,6 +70,7 @@ public: void set_bottom(double bottom) { set_height(bottom - y() + 1); } void set_right(double right) { set_width(right - x() + 1); } void set_left(double left) { set_x(left); } + void set_dimension(Direction direction, double value); 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); } diff --git a/src/BoxLayout.cpp b/src/BoxLayout.cpp index 45850bf..4b854e0 100644 --- a/src/BoxLayout.cpp +++ b/src/BoxLayout.cpp @@ -1,6 +1,7 @@ #include "BoxLayout.hpp" #include "Box.hpp" #include "Widget.hpp" +#include "src/Events.hpp" #include #include #include @@ -8,19 +9,32 @@ namespace Raven { -void BoxLayout::run() { +bool BoxLayout::run() { if (!m_target) { - return; + return false; } double total_space = m_target->rect().dimension_at(m_direction) - 2 * m_margin; double free_space = total_space; + double maximum_secondary_dimension = 0.0; + Direction secondary_direction = m_direction == Direction::Horizontal ? Direction::Vertical : Direction::Horizontal; Point current_position { m_margin, m_margin }; int unslotted_widgets = 0; std::vector working_slots(m_slots); for (unsigned int i = 0; i < m_target->children().size(); i++) { auto child = m_target->children()[i]; + + if (child->layout() && child->layout()->dynamically_sizes_target()) { + auto event = RelayoutSubtreeEvent(); + child->dispatch_event(event); + } + + auto child_secondary_dimension = child->rect().dimension_at(secondary_direction); + if (child_secondary_dimension > maximum_secondary_dimension) { + maximum_secondary_dimension = child_secondary_dimension; + } + if (i >= working_slots.size()) { // widgets which are outside the pre-defined slot range @@ -49,6 +63,8 @@ void BoxLayout::run() { } } + maximum_secondary_dimension = m_target->rect().clamp_for_dimension(secondary_direction, maximum_secondary_dimension); + // compute all percentages for slots for (unsigned int i = 0; i < m_target->children().size(); i++) { Slot *slot = &working_slots[i]; @@ -85,14 +101,27 @@ void BoxLayout::run() { child->rect().set_y(current_position.y()); if (m_direction == Direction::Horizontal) { child->rect().set_width(slot.pixel); - child->rect().set_height(m_target->rect().max_geometry().height() - 2 * m_margin); + child->rect().set_height(m_justify_secondary_dimension ? maximum_secondary_dimension - 2 * m_margin : m_target->rect().max_geometry().height() - 2 * m_margin); current_position.add(slot.pixel + m_spacing, 0); } else { - child->rect().set_width(m_target->rect().max_geometry().width() - 2 * m_margin); + child->rect().set_width(m_justify_secondary_dimension ? maximum_secondary_dimension - 2 * m_margin : m_target->rect().max_geometry().width() - 2 * m_margin); child->rect().set_height(slot.pixel); current_position.add(0, slot.pixel + m_spacing); } } + + if (m_justify_secondary_dimension) { + m_target->rect().set_dimension(secondary_direction, maximum_secondary_dimension); + } + + for (unsigned int i = 0; i < m_target->children().size(); i++) { + auto child = m_target->children()[i]; + + auto event = RelayoutSubtreeEvent(); + child->dispatch_event(event); + } + + return true; }; void BoxLayout::slot_percent(double percent) { diff --git a/src/BoxLayout.hpp b/src/BoxLayout.hpp index 0a60146..3ae99cf 100644 --- a/src/BoxLayout.hpp +++ b/src/BoxLayout.hpp @@ -26,7 +26,7 @@ public: , m_direction(direction) {} ~BoxLayout() {} - void run(); + bool run() override; void slot_percent(double percent); void slot_pixel(double pixel); void slot_pixel(double pixel, double times); @@ -36,9 +36,15 @@ public: void set_spacing(double spacing) { m_spacing = spacing; } double &spacing() { return m_spacing; } + + bool justify_secondary_dimension() { return m_justify_secondary_dimension; } + void set_justify_secondary_dimension(bool justify_secondary_dimension) { m_justify_secondary_dimension = justify_secondary_dimension; } + + bool dynamically_sizes_target() override { return m_justify_secondary_dimension; } private: double m_margin { 0.0 }; double m_spacing { 0.0 }; + bool m_justify_secondary_dimension { false }; std::vector m_slots; Direction m_direction { Direction::Horizontal }; }; diff --git a/src/Button.cpp b/src/Button.cpp index 8bff785..ac54851 100644 --- a/src/Button.cpp +++ b/src/Button.cpp @@ -12,7 +12,7 @@ namespace Raven { void Button::set_text(std::string text) { m_text = text; - if (!fit_text(text)) { + if (!fit_text(text, m_padding)) { repaint(); } } @@ -25,7 +25,7 @@ void Button::on_init() { } set_did_init(true); - if (!fit_text(m_text)) { + if (!fit_text(m_text, m_padding)) { reflow(); } } diff --git a/src/Button.hpp b/src/Button.hpp index 348cac7..7e7e3ae 100644 --- a/src/Button.hpp +++ b/src/Button.hpp @@ -23,12 +23,16 @@ public: void set_text(std::string text); std::string &text() { return m_text; } + + double padding() { return m_padding; } + void set_padding(double padding) { m_padding = padding; reflow(); } protected: void on_paint(); void on_init(); private: std::string m_text; ButtonType m_button_type; + double m_padding { 10 }; }; } diff --git a/src/ColumnLayout.cpp b/src/ColumnLayout.cpp index 2c40a9b..ede1397 100644 --- a/src/ColumnLayout.cpp +++ b/src/ColumnLayout.cpp @@ -4,9 +4,9 @@ namespace Raven { -void ColumnLayout::run() { +bool ColumnLayout::run() { if (!m_target) { - return; + return false; } Point current_point { m_margin, m_margin }; @@ -33,6 +33,8 @@ void ColumnLayout::run() { m_target->rect().set_height(requested_height + m_margin); m_target->rect().set_width(max_width_so_far + m_margin * 2); + + return false; } } diff --git a/src/ColumnLayout.hpp b/src/ColumnLayout.hpp index 681c491..b78bc09 100644 --- a/src/ColumnLayout.hpp +++ b/src/ColumnLayout.hpp @@ -15,7 +15,7 @@ public: : Layout() , m_margin(margin) {} - void run(); + bool run() override; double margin() { return m_margin; } void set_margin(double margin) { m_margin = margin; run(); } diff --git a/src/DocumentLayout.cpp b/src/DocumentLayout.cpp index ba9b83c..f401993 100644 --- a/src/DocumentLayout.cpp +++ b/src/DocumentLayout.cpp @@ -5,9 +5,9 @@ namespace Raven { -void DocumentLayout::run() { +bool DocumentLayout::run() { if (!m_target) - return; + return false; Point bound { m_margin + m_target->rect().max_geometry().width(), m_margin }; Point current_position { m_margin, m_margin }; @@ -44,6 +44,8 @@ void DocumentLayout::run() { m_target->rect().set_width(bound.x()); m_target->rect().set_height(bound.y()); + + return false; } } diff --git a/src/DocumentLayout.hpp b/src/DocumentLayout.hpp index 87e9dcf..5a03a23 100644 --- a/src/DocumentLayout.hpp +++ b/src/DocumentLayout.hpp @@ -15,7 +15,7 @@ public: : Layout() , m_margin(margin) {} - void run(); + bool run(); double margin() { return m_margin; } void set_margin(double margin) { m_margin = margin; run(); } diff --git a/src/Layout.hpp b/src/Layout.hpp index 50cf7a6..2c10d40 100644 --- a/src/Layout.hpp +++ b/src/Layout.hpp @@ -10,11 +10,13 @@ protected: public: Layout() {} - virtual void run() {}; + virtual bool run() {return false;} void bind_to(Widget *target) { m_target = target; } Widget *target() { return m_target; } + virtual bool dynamically_sizes_target() { return false; } + virtual ~Layout() {} }; diff --git a/src/RowLayout.cpp b/src/RowLayout.cpp index d00ce36..f6343a0 100644 --- a/src/RowLayout.cpp +++ b/src/RowLayout.cpp @@ -4,9 +4,9 @@ namespace Raven { -void RowLayout::run() { +bool RowLayout::run() { if (!m_target) { - return; + return false; } Point current_point { m_margin, m_margin }; @@ -33,6 +33,8 @@ void RowLayout::run() { m_target->rect().set_width(requested_width + m_margin); m_target->rect().set_height(max_height_so_far + m_margin * 2); + + return false; } } diff --git a/src/RowLayout.hpp b/src/RowLayout.hpp index 673099d..e0df646 100644 --- a/src/RowLayout.hpp +++ b/src/RowLayout.hpp @@ -15,7 +15,7 @@ public: : Layout() , m_margin(margin) {} - void run(); + bool run() override; double margin() { return m_margin; } void set_margin(double margin) { m_margin = margin; run(); } diff --git a/src/Widget.cpp b/src/Widget.cpp index 256a7e0..6541310 100644 --- a/src/Widget.cpp +++ b/src/Widget.cpp @@ -25,11 +25,12 @@ Point Widget::compute_window_relative() { return point; } -bool Widget::fit_text(std::string &text) { +bool Widget::fit_text(std::string &text, double padding) { if (!window()) return false; auto size = window()->painter().compute_text_size(rect(), text, style()->font_description()); + size.add(padding * 2, padding * 2); return resize(size); } @@ -198,10 +199,10 @@ void Widget::handle_relayout_subtree(RelayoutSubtreeEvent &event) { if (m_layout) { m_layout->run(); - } - - for (auto child : m_children) { - child->dispatch_event(event); + } else { + for (auto child : m_children) { + child->dispatch_event(event); + } } on_after_layout(); @@ -221,10 +222,13 @@ void Widget::handle_mouse_move_event(MouseMoveEvent &event) { if (m_is_focused && m_window) m_window->set_focused_widget(this); + std::cout << "update focus: " << update_focus_to << std::endl; + auto focus_update_event = FocusUpdateEvent(update_focus_to); on_focus_update(focus_update_event); if (m_style->update_background()) { + std::cout << "should repaint because of focus change" << std::endl; repaint(); } } diff --git a/src/Widget.hpp b/src/Widget.hpp index 956a194..39a1488 100644 --- a/src/Widget.hpp +++ b/src/Widget.hpp @@ -46,7 +46,7 @@ public: std::function on_event { [](Event&){} }; std::function on_click { [](){} }; - bool fit_text(std::string &text); + bool fit_text(std::string &text, double padding = 0); void move_to(double x, double y); bool resize(double width, double height); diff --git a/src/main.cpp b/src/main.cpp index f11642c..87f8ab9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,9 +43,10 @@ int main() { auto control_row = content->add(); control_row->set_style(&Raven::raised_widget_style); - control_row->rect().set_min_height(28.0); + //control_row->rect().set_min_height(28.0); auto control_row_layout = control_row->set_layout(Raven::Direction::Horizontal); control_row_layout->set_spacing(6.0); + control_row_layout->set_justify_secondary_dimension(true); auto next_button = control_row->add("Next Item", Raven::Button::Accent); next_button->set_grows(true); @@ -58,9 +59,10 @@ int main() { auto edit_row = content->add(); edit_row->set_style(&Raven::raised_widget_style); - edit_row->rect().set_min_height(28.0); + //edit_row->rect().set_min_height(28.0); auto edit_row_layout = edit_row->set_layout(Raven::Direction::Horizontal); edit_row_layout->set_spacing(6.0); + edit_row_layout->set_justify_secondary_dimension(true); auto edit_input = edit_row->add(); edit_input->set_style(&Raven::raised_textinput_style);