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