respect slotted widget rectangle extents in boxlayout

currently thinking of a way to make unslotted widgets respect minimum
and maximum extents.
This commit is contained in:
hippoz 2022-07-09 20:19:09 +03:00
parent 3ab3e74cd1
commit 1ceb227165
Signed by: hippoz
GPG key ID: 7C52899193467641
9 changed files with 50 additions and 154 deletions

View file

@ -1,23 +1,27 @@
project('raven', 'cpp')
project(
'raven',
'cpp',
default_options : ['cpp_std=c++17']
)
cairomm_dep = dependency('cairomm-1.0')
pangocairo_dep = dependency('pangocairo')
xlib_dep = dependency('x11')
executable(
'ravenapp',
'./src/Box.cpp',
'./src/Styles.cpp',
'./src/Painter.cpp',
'./src/Window.cpp',
'./src/Widget.cpp',
'./src/ScrollContainer.cpp',
'./src/Button.cpp',
'./src/DocumentLayout.cpp',
'./src/HorizontalBoxLayout.cpp',
'./src/VerticalBoxLayout.cpp',
'./src/BoxLayout.cpp',
'./src/Label.cpp',
'./src/main.cpp',
dependencies : [cairomm_dep, xlib_dep, pangocairo_dep]
'ravenapp',
'./src/Box.cpp',
'./src/Styles.cpp',
'./src/Painter.cpp',
'./src/Window.cpp',
'./src/Widget.cpp',
'./src/ScrollContainer.cpp',
'./src/Button.cpp',
'./src/DocumentLayout.cpp',
'./src/RowLayout.cpp',
'./src/ColumnLayout.cpp',
'./src/BoxLayout.cpp',
'./src/Label.cpp',
'./src/main.cpp',
dependencies : [cairomm_dep, xlib_dep, pangocairo_dep]
)

View file

@ -69,4 +69,10 @@ Box Box::max_geometry() {
return Box{ m_x, m_y, max_width, max_height };
}
Box Box::min_geometry() {
auto min_width = m_min_width == -1 ? m_width : m_min_width;
auto min_height = m_min_height == -1 ? m_height : m_min_height;
return Box{ m_x, m_y, min_width, min_height };
}
}

View file

@ -32,6 +32,7 @@ public:
}
Box max_geometry();
Box min_geometry();
double x() { return m_x; }
double y() { return m_y; }

View file

@ -3,6 +3,7 @@
#include "Widget.hpp"
#include <cmath>
#include <vector>
#include <algorithm>
namespace Raven {
@ -24,16 +25,31 @@ void BoxLayout::run() {
unslotted_widgets++;
} else {
Slot *slot = &m_slots[i];
auto child = m_target->children()[i];
if (m_direction == Direction::Horizontal) {
if (slot->type == SlotType::Percent) {
slot->pixel = (free_space.width() / 100.0) * slot->percent;
slot->pixel = ((free_space.width() / 100.0) * slot->percent);
}
if (child->rect().max_width() != -1 && slot->pixel > child->rect().max_width()) {
slot->pixel = child->rect().max_width();
}
if (child->rect().min_width() != -1 && slot->pixel < child->rect().min_width()) {
slot->pixel = child->rect().min_width();
}
free_space.set_width(free_space.width() - slot->pixel);
} else {
if (slot->type == SlotType::Percent) {
slot->pixel = (free_space.height() / 100.0) * slot->percent;
slot->pixel = ((free_space.height() / 100.0) * slot->percent);
}
if (child->rect().max_height() != -1 && slot->pixel > child->rect().max_height()) {
slot->pixel = child->rect().max_height();
}
if (child->rect().min_height() != -1 && slot->pixel < child->rect().min_height()) {
slot->pixel = child->rect().min_height();
}
free_space.set_height(free_space.height() - slot->pixel);
}
}

View file

@ -1,39 +0,0 @@
#include "HorizontalBoxLayout.hpp"
#include "Point.hpp"
#include "Widget.hpp"
namespace Raven {
void HorizontalBoxLayout::run() {
if (!m_target) {
return;
}
Point current_point { m_margin, m_margin };
double max_height_so_far = 0;
double requested_width = 0;
auto& children = m_target->children();
for (auto child : children) {
if (child->absolute()) {
continue;
}
if (child->rect().height() > max_height_so_far) {
max_height_so_far = child->rect().height();
}
requested_width += child->rect().width() + m_margin;
child->rect().set_x(current_point.x());
child->rect().set_y(current_point.y());
current_point.add(child->rect().width() + m_margin, 0);
}
m_target->rect().set_width(requested_width + m_margin);
m_target->rect().set_height(max_height_so_far + m_margin * 2);
}
}

View file

@ -1,27 +0,0 @@
#pragma once
#include "Layout.hpp"
namespace Raven {
class HorizontalBoxLayout : public Layout {
private:
double m_margin { 0.0 };
public:
HorizontalBoxLayout()
: Layout() {}
HorizontalBoxLayout(double margin)
: Layout()
, m_margin(margin) {}
void run();
double margin() { return m_margin; }
void set_margin(double margin) { m_margin = margin; run(); }
virtual ~HorizontalBoxLayout() {}
};
}

View file

@ -1,39 +0,0 @@
#include "VerticalBoxLayout.hpp"
#include "Point.hpp"
#include "Widget.hpp"
namespace Raven {
void VerticalBoxLayout::run() {
if (!m_target) {
return;
}
Point current_point { m_margin, m_margin };
double max_width_so_far = 0;
double requested_height = 0;
auto& children = m_target->children();
for (auto child : children) {
if (child->absolute()) {
continue;
}
if (child->rect().width() > max_width_so_far) {
max_width_so_far = child->rect().height();
}
requested_height += child->rect().height() + m_margin;
child->rect().set_x(current_point.x());
child->rect().set_y(current_point.y());
current_point.add(0, child->rect().height() + m_margin);
}
m_target->rect().set_height(requested_height + m_margin);
m_target->rect().set_width(max_width_so_far + m_margin * 2);
}
}

View file

@ -1,27 +0,0 @@
#pragma once
#include "Layout.hpp"
namespace Raven {
class VerticalBoxLayout : public Layout {
private:
double m_margin { 0.0 };
public:
VerticalBoxLayout()
: Layout() {}
VerticalBoxLayout(double margin)
: Layout()
, m_margin(margin) {}
void run();
double margin() { return m_margin; }
void set_margin(double margin) { m_margin = margin; run(); }
virtual ~VerticalBoxLayout() {}
};
}

View file

@ -10,10 +10,8 @@
#include "Events.hpp"
#include "src/BoxLayout.hpp"
#include "src/Box.hpp"
#include "src/HorizontalBoxLayout.hpp"
#include "src/ScrollContainer.hpp"
#include "src/Styles.hpp"
#include "src/VerticalBoxLayout.hpp"
#include <iostream>
#include <memory>
#include <string>
@ -28,14 +26,17 @@ int main() {
auto top_bar = main_widget->add<Raven::Widget>();
top_bar->set_style(&Raven::accent_widget_style);
top_bar->set_layout<Raven::BoxLayout>(Raven::Direction::Horizontal);
auto top_layout = top_bar->set_layout<Raven::BoxLayout>(Raven::Direction::Horizontal);
top_layout->slot_percent(50);
top_layout->slot_percent(100);
auto scroll_container = main_widget->add<Raven::ScrollContainer>();
auto container_widget = scroll_container->make_target();
container_widget->set_layout<Raven::BoxLayout>(Raven::Direction::Vertical);
container_widget->resize(400, 400);
auto new_button = top_bar->add<Raven::Button>("add");
new_button->rect().set_max_width(50);
new_button->on_click = [container_widget]() {
auto button = container_widget->add<Raven::Button>("button");
button->on_click = [button]() {