further improve boxlayout
This commit is contained in:
parent
4f35de353e
commit
2fa09abbf2
4 changed files with 55 additions and 69 deletions
20
src/Box.cpp
20
src/Box.cpp
|
@ -75,4 +75,24 @@ Box Box::min_geometry() {
|
|||
return Box{ m_x, m_y, min_width, min_height };
|
||||
}
|
||||
|
||||
double Box::clamp_for_dimension(Direction direction, double value) {
|
||||
if (direction == Direction::Vertical) {
|
||||
if (m_max_height != -1 && value > m_max_height) {
|
||||
return m_max_height;
|
||||
} else if (m_min_height != -1 && value < m_min_height) {
|
||||
return m_min_height;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
if (m_max_width != -1 && value > m_max_width) {
|
||||
return m_max_width;
|
||||
} else if (m_min_width != -1 && value < m_min_width) {
|
||||
return m_min_width;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,10 @@ public:
|
|||
double min_height() const { return m_min_height; }
|
||||
double max_width() const { return m_max_width; }
|
||||
double max_height() const { return m_max_height; }
|
||||
double dimension_at(Direction direction) { return direction == Direction::Horizontal ? width() : height(); }
|
||||
double max_dimension_at(Direction direction) { return direction == Direction::Horizontal ? max_width() : max_height(); }
|
||||
double min_dimension_at(Direction direction) { return direction == Direction::Horizontal ? min_width() : min_height(); }
|
||||
double clamp_for_dimension(Direction direction, double value);
|
||||
|
||||
void set_x(double x) { m_x = x; }
|
||||
void set_y(double y) { m_y = y; }
|
||||
|
|
|
@ -13,80 +13,48 @@ void BoxLayout::run() {
|
|||
return;
|
||||
}
|
||||
|
||||
double total_space = m_direction == Direction::Horizontal ? m_target->rect().width() : m_target->rect().height();
|
||||
double total_space = m_target->rect().dimension_at(m_direction);
|
||||
double free_space = total_space;
|
||||
Point current_position { 0.0, 0.0 };
|
||||
int unslotted_widgets = 0;
|
||||
std::vector<Slot> working_slots(m_slots);
|
||||
|
||||
for (unsigned int i = 0; i < m_target->children().size(); i++) {
|
||||
auto child = m_target->children()[i];
|
||||
if (i >= working_slots.size()) {
|
||||
auto child = m_target->children()[i];
|
||||
if (m_direction == Direction::Horizontal) {
|
||||
if (child->rect().min_width() != -1 || child->rect().max_width() != -1) {
|
||||
child->rect().update();
|
||||
working_slots.push_back(Slot {
|
||||
0,
|
||||
child->rect().width(),
|
||||
SlotType::Pixel
|
||||
});
|
||||
} else {
|
||||
unslotted_widgets++;
|
||||
working_slots.push_back(Slot {
|
||||
0,
|
||||
0,
|
||||
SlotType::Auto
|
||||
});
|
||||
}
|
||||
// widgets which are outside the pre-defined slot range
|
||||
|
||||
if (child->rect().max_dimension_at(m_direction) != -1 || child->rect().min_dimension_at(m_direction) != -1) {
|
||||
// if the widget has a minimum or maximum size, we'll make a slot for its preferred size
|
||||
child->rect().update();
|
||||
working_slots.push_back(Slot { 0, child->rect().dimension_at(m_direction), SlotType::Pixel });
|
||||
free_space -= child->rect().dimension_at(m_direction);
|
||||
} else {
|
||||
if (child->rect().min_height() != -1 || child->rect().max_height() != -1) {
|
||||
child->rect().update();
|
||||
working_slots.push_back(Slot {
|
||||
0,
|
||||
child->rect().height(),
|
||||
SlotType::Pixel
|
||||
});
|
||||
} else {
|
||||
unslotted_widgets++;
|
||||
working_slots.push_back(Slot {
|
||||
0,
|
||||
0,
|
||||
SlotType::Auto
|
||||
});
|
||||
}
|
||||
// we can consider widgets with no size perference "unslotted". these widgets will be evenly spaced amongst themselves.
|
||||
unslotted_widgets++;
|
||||
working_slots.push_back(Slot{ 0, 0, SlotType::Auto });
|
||||
}
|
||||
} else {
|
||||
// widgets which have a pre-defined slot
|
||||
|
||||
// if the slot is fixed, we can already clamp it and subtract from free_space
|
||||
if (working_slots[i].type == SlotType::Pixel) {
|
||||
working_slots[i].pixel = child->rect().clamp_for_dimension(m_direction, working_slots[i].pixel);
|
||||
free_space -= working_slots[i].pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compute all percentages for slots
|
||||
for (unsigned int i = 0; i < m_target->children().size(); i++) {
|
||||
Slot *slot = &working_slots[i];
|
||||
auto child = m_target->children()[i];
|
||||
|
||||
if (slot->type == SlotType::Auto) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (slot->type == SlotType::Percent) {
|
||||
slot->pixel = ((free_space / 100.0) * slot->percent);
|
||||
slot->pixel = child->rect().clamp_for_dimension(m_direction, slot->pixel);
|
||||
free_space -= slot->pixel;
|
||||
}
|
||||
|
||||
if (m_direction == Direction::Horizontal) {
|
||||
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();
|
||||
}
|
||||
} else {
|
||||
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 -= slot->pixel;
|
||||
}
|
||||
|
||||
double space_per_unslotted_widget = free_space / unslotted_widgets;
|
||||
|
@ -94,6 +62,7 @@ void BoxLayout::run() {
|
|||
for (unsigned int i = 0; i < m_target->children().size(); i++) {
|
||||
auto child = m_target->children()[i];
|
||||
Slot slot = working_slots[i];
|
||||
|
||||
if (slot.type == SlotType::Auto) {
|
||||
slot.pixel = space_per_unslotted_widget;
|
||||
}
|
||||
|
@ -117,19 +86,11 @@ void BoxLayout::run() {
|
|||
};
|
||||
|
||||
void BoxLayout::slot_percent(double percent) {
|
||||
m_slots.push_back(Slot {
|
||||
percent,
|
||||
0,
|
||||
SlotType::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,
|
||||
});
|
||||
m_slots.push_back(Slot { 0, pixel, SlotType::Pixel });
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,14 +22,13 @@ int main() {
|
|||
|
||||
auto main_widget = window.set_main_widget<Raven::Widget>();
|
||||
auto main_layout = main_widget->set_layout<Raven::BoxLayout>(Raven::Direction::Vertical);
|
||||
main_layout->slot_pixel(32); // top bar
|
||||
main_layout->slot_pixel(30); // top bar
|
||||
|
||||
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 scroll_container = main_widget->add<Raven::ScrollContainer>();
|
||||
auto container_widget = scroll_container->make_target();
|
||||
auto container_widget = main_widget->add<Raven::Widget>();
|
||||
container_widget->set_layout<Raven::BoxLayout>(Raven::Direction::Vertical);
|
||||
container_widget->resize(400, 400);
|
||||
|
||||
|
@ -43,7 +42,9 @@ int main() {
|
|||
};
|
||||
auto remove_button = top_bar->add<Raven::Button>("remove");
|
||||
remove_button->on_click = [container_widget]() {
|
||||
container_widget->remove_child(container_widget->children()[0]);
|
||||
if (container_widget->children().size() > 0) {
|
||||
container_widget->remove_child(container_widget->children()[0]);
|
||||
}
|
||||
};
|
||||
auto dummy_button = top_bar->add<Raven::Button>("dummy");
|
||||
dummy_button->rect().set_max_width(60);
|
||||
|
|
Loading…
Reference in a new issue