diff --git a/libs/ui/source/screen.cpp b/libs/ui/source/screen.cpp index ecf144e1..e57c359d 100644 --- a/libs/ui/source/screen.cpp +++ b/libs/ui/source/screen.cpp @@ -40,66 +40,87 @@ namespace psemek::ui void screen::reshape(geom::box const & bbox) { shape_.box = bbox; + auto const m = bbox.center(); + auto cs = children(); for (std::size_t i = 0; i < cs.size(); ++i) { auto c = cs[i]; if (!c) continue; - auto sc = c->size_constraints(); - auto size = bbox.dimensions(); - size[0] = std::min(size[0], sc[0].min); - size[1] = std::min(size[1], sc[1].min); - auto m = bbox.center(); + auto sc = c->size_constraints(); geom::box cbox = c->shape().bbox(); - switch (policies_[i].x) + auto update_width = [&](float width) { - case x_policy::left: - cbox[0] = {bbox[0].min, bbox[0].min + size[0]}; - break; - case x_policy::center: - cbox[0] = {m[0] - size[0] / 2.f, m[0] + size[0] / 2.f}; - break; - case x_policy::right: - cbox[0] = {bbox[0].max - size[0], bbox[0].max}; - break; - case x_policy::fill: - cbox[0] = bbox[0]; - break; - case x_policy::floating: - cbox[0] = geom::expand(cbox[0], (size[0] - cbox[0].length()) / 2.f); + width = std::min(bbox[0].length(), width); - if (cbox[0].min < bbox[0].min) - cbox[0] += (bbox[0].min - cbox[0].min); - else if (cbox[0].max > bbox[0].max) - cbox[0] -= (cbox[0].max - bbox[0].max); - break; + switch (policies_[i].x) + { + case x_policy::left: + cbox[0] = {bbox[0].min, bbox[0].min + width}; + break; + case x_policy::center: + cbox[0] = {m[0] - width / 2.f, m[0] + width / 2.f}; + break; + case x_policy::right: + cbox[0] = {bbox[0].max - width, bbox[0].max}; + break; + case x_policy::fill: + cbox[0] = bbox[0]; + break; + case x_policy::floating: + cbox[0] = geom::expand(cbox[0], (width - cbox[0].length()) / 2.f); + + if (cbox[0].min < bbox[0].min) + cbox[0] += (bbox[0].min - cbox[0].min); + else if (cbox[0].max > bbox[0].max) + cbox[0] -= (cbox[0].max - bbox[0].max); + break; + } + }; + + auto update_height = [&](float height) + { + height = std::min(bbox[1].length(), height); + + switch (policies_[i].y) + { + case y_policy::top: + cbox[1] = {bbox[1].min, bbox[1].min + height}; + break; + case y_policy::center: + cbox[1] = {m[1] - height / 2.f, m[1] + height / 2.f}; + break; + case y_policy::bottom: + cbox[1] = {bbox[1].max - height, bbox[1].max}; + break; + case y_policy::fill: + cbox[1] = bbox[1]; + break; + case y_policy::floating: + cbox[1] = geom::expand(cbox[1], (height - cbox[1].length()) / 2.f); + + if (cbox[1].min < bbox[1].min) + cbox[1] += (bbox[1].min - cbox[1].min); + else if (cbox[1].max > bbox[1].max) + cbox[1] -= (cbox[1].max - bbox[1].max); + break; + } + }; + + if (width_first()) + { + update_width(sc[0].min); + auto hc = c->height_constraints(cbox[0].length()); + update_height(hc.min); } - - switch (policies_[i].y) + else { - case y_policy::top: - cbox[1] = {bbox[1].min, bbox[1].min + size[1]}; - break; - case y_policy::center: - cbox[1] = {m[1] - size[1] / 2.f, m[1] + size[1] / 2.f}; - break; - case y_policy::bottom: - cbox[1] = {bbox[1].max - size[1], bbox[1].max}; - break; - case y_policy::fill: - cbox[1] = bbox[1]; - break; - case y_policy::floating: - cbox[1] = geom::expand(cbox[1], (size[1] - cbox[1].length()) / 2.f); - - if (cbox[1].min < bbox[1].min) - cbox[1] += (bbox[1].min - cbox[1].min); - else if (cbox[1].max > bbox[1].max) - cbox[1] -= (cbox[1].max - bbox[1].max); - break; + update_height(sc[1].min); + auto wc = c->width_constraints(cbox[1].length()); + update_width(wc.min); } c->reshape(cbox);