add box layout

This commit is contained in:
hippoz 2022-07-07 18:29:35 +03:00
parent 2423645222
commit 43bbc4ddff
Signed by: hippoz
GPG key ID: 7C52899193467641
5 changed files with 144 additions and 10 deletions

View file

@ -16,6 +16,7 @@ executable(
'./src/DocumentLayout.cpp', './src/DocumentLayout.cpp',
'./src/HorizontalBoxLayout.cpp', './src/HorizontalBoxLayout.cpp',
'./src/VerticalBoxLayout.cpp', './src/VerticalBoxLayout.cpp',
'./src/BoxLayout.cpp',
'./src/Label.cpp', './src/Label.cpp',
'./src/main.cpp', './src/main.cpp',
dependencies : [cairomm_dep, xlib_dep, pangocairo_dep] dependencies : [cairomm_dep, xlib_dep, pangocairo_dep]

View file

@ -4,6 +4,11 @@
namespace Raven { namespace Raven {
enum class Direction {
Horizontal,
Vertical
};
class Box { class Box {
private: private:
double m_x {0}; double m_x {0};

90
src/BoxLayout.cpp Normal file
View file

@ -0,0 +1,90 @@
#include "BoxLayout.hpp"
#include "Box.hpp"
#include "Widget.hpp"
#include <vector>
namespace Raven {
void BoxLayout::run() {
if (!m_target) {
return;
}
Box free_space = m_target->rect().max_geometry();
Box total_space = m_target->rect().max_geometry();
Point current_position { 0.0, 0.0 };
int unslotted_widgets = 0;
for (unsigned int i = 0; i < m_target->children().size(); i++) {
if (i >= m_slots.size()) {
unslotted_widgets++;
}
}
double space_per_unslotted_widget = m_direction == Direction::Horizontal ? total_space.width() / unslotted_widgets : total_space.height() / unslotted_widgets;
for (unsigned int i = 0; i < m_target->children().size(); i++) {
auto child = m_target->children()[i];
Slot slot;
if (i >= m_slots.size()) {
slot = Slot {
0.0,
space_per_unslotted_widget,
SlotType::Pixel
};
} else {
slot = m_slots[i];
}
// resolve slot size
if (slot.type == SlotType::Percent) {
if (m_direction == Direction::Horizontal) {
slot.pixel = (free_space.width() / 100.0) * slot.percent;
} else {
slot.pixel = (free_space.height() / 100.0) * slot.percent;
}
}
// justify child geometry, stop looping if free space has been exhausted
child->rect().set_x(current_position.x());
child->rect().set_y(current_position.y());
if (m_direction == Direction::Horizontal) {
child->rect().set_width(slot.pixel);
child->rect().set_height(free_space.height());
current_position.add(slot.pixel, 0);
free_space.set_width(free_space.width() - slot.pixel);
if (free_space.width() <= 0) {
break;
}
} else {
child->rect().set_width(free_space.width());
child->rect().set_height(slot.pixel);
current_position.add(0, slot.pixel);
free_space.set_height(free_space.height() - slot.pixel);
if (free_space.height() <= 0) {
break;
}
}
}
};
void BoxLayout::slot_percent(double percent) {
m_slots.push_back(Slot {
percent,
0,
SlotType::Percent,
});
}
void BoxLayout::slot_pixel(double pixel) {
m_slots.push_back(Slot {
0,
pixel,
SlotType::Pixel,
});
}
}

37
src/BoxLayout.hpp Normal file
View file

@ -0,0 +1,37 @@
#pragma once
#include "src/Layout.hpp"
#include "src/Widget.hpp"
#include "src/Box.hpp"
#include <memory>
#include <vector>
namespace Raven {
class BoxLayout : public Layout {
public:
enum class SlotType {
No,
Percent,
Pixel
};
struct Slot {
double percent, pixel;
SlotType type;
};
public:
BoxLayout(Direction direction)
: Layout()
, m_direction(direction) {}
~BoxLayout() {}
void run();
void slot_percent(double percent);
void slot_pixel(double pixel);
private:
std::vector<Slot> m_slots;
Direction m_direction { Direction::Horizontal };
};
}

View file

@ -8,6 +8,8 @@
#include "RGB.hpp" #include "RGB.hpp"
#include "DocumentLayout.hpp" #include "DocumentLayout.hpp"
#include "Events.hpp" #include "Events.hpp"
#include "src/BoxLayout.hpp"
#include "src/Box.hpp"
#include "src/HorizontalBoxLayout.hpp" #include "src/HorizontalBoxLayout.hpp"
#include "src/ScrollContainer.hpp" #include "src/ScrollContainer.hpp"
#include "src/Styles.hpp" #include "src/Styles.hpp"
@ -21,18 +23,17 @@ int main() {
window.spawn_window(); window.spawn_window();
auto main_widget = window.set_main_widget<Raven::Widget>(); auto main_widget = window.set_main_widget<Raven::Widget>();
main_widget->set_layout<Raven::VerticalBoxLayout>(6.0); main_widget->set_layout<Raven::BoxLayout>(Raven::Direction::Horizontal);
auto scroll = main_widget->add<Raven::ScrollContainer>(); auto inner = main_widget->add<Raven::Widget>();
scroll->set_style(&Raven::accent_widget_style); inner->resize(400, 200);
scroll->resize(200, 200); inner->set_style(&Raven::accent_widget_style);
auto target = scroll->make_target(); auto inner_layout = inner->set_layout<Raven::BoxLayout>(Raven::Direction::Horizontal);
target->set_layout<Raven::VerticalBoxLayout>(8.0); inner_layout->slot_pixel(20);
target->rect().set_max_width(200); inner_layout->slot_percent(50);
for (int i = 0; i < 300; i++) { for (int i = 0; i < 4; i++) {
auto button = target->add<Raven::Button>(std::to_string(i)); auto button = inner->add<Raven::Button>("h");
button->set_style(&Raven::accent_button_style);
} }
window.run(true); window.run(true);