#include "Layout.h" #include #include "3rd/magic_enum/export.h" #include "Core/Base/global_include.h" #include "Core/spdlog/export.h" namespace Psc { struct Horizontal_Traits { static int get_main(const Layout_Item* i) { return i->x(); } static void set_main(Layout_Item* i, int v) { i->set_x(v); } static int get_cros(const Layout_Item* i) { return i->y(); } static void set_cros(Layout_Item* i, int v) { i->set_y(v); } static int get_main_len(const Layout_Item* i) { return i->w(); } static void set_main_len(Layout_Item* i, int v) { i->set_w(v); } static int get_cros_len(const Layout_Item* i) { return i->h(); } static void set_cros_len(Layout_Item* i, int v) { i->set_h(v); } static int main_prefix(const QMargins& m) { return m.left(); } static int main_suffix(const QMargins& m) { return m.right(); } static int cros_prefix(const QMargins& m) { return m.top(); } static int cros_suffix(const QMargins& m) { return m.bottom(); } static int main_length(const Layout* l) { return l->w(); } static int cros_length(const Layout* l) { return l->h(); } }; struct Vertical_Traits { static int get_main(const Layout_Item* i) { return i->y(); } static void set_main(Layout_Item* i, int v) { i->set_y(v); } static int get_cros(const Layout_Item* i) { return i->x(); } static void set_cros(Layout_Item* i, int v) { i->set_x(v); } static int get_main_len(const Layout_Item* i) { return i->h(); } static void set_main_len(Layout_Item* i, int v) { i->set_h(v); } static int get_cros_len(const Layout_Item* i) { return i->w(); } static void set_cros_len(Layout_Item* i, int v) { i->set_w(v); } static int main_prefix(const QMargins& m) { return m.top(); } static int main_suffix(const QMargins& m) { return m.bottom(); } static int cros_prefix(const QMargins& m) { return m.left(); } static int cros_suffix(const QMargins& m) { return m.right(); } static int main_length(const Layout* l) { return l->h(); } static int cros_length(const Layout* l) { return l->w(); } }; // TODO: maxsize mainsize 不知道怎么和 grow shrink 合并处理 template void Layout::layout_impl() { int main_prefix = T::main_prefix(margins); int main_suffix = T::main_suffix(margins); int cros_prefix = T::cros_prefix(margins); int cros_suffix = T::cros_suffix(margins); int main_length = T::main_length(this); int cros_length = T::cros_length(this); int cros_max = cros_length - cros_prefix - cros_suffix; int total_main = main_prefix + main_suffix; std::vector grow_items; std::vector shrink_items; // ---------- 第一遍:初始化尺寸 & 收集 grow / shrink ---------- for (auto* item : items) { auto size = item->sizeHint(); auto& flags = item->size_policy; item->set_size(size); if (flags.testFlag(Cross_Expand)) { T::set_cros_len(item, cros_max); } if (flags.testFlag(Get_Main_By_Cross)) { int cros_len = T::get_cros_len(item); int main_len = item->get_main_by_cros(cros_len); T::set_main_len(item, main_len); } total_main += T::get_main_len(item); // 明确语义:Grow / Shrink 不允许同时生效 if (flags.testFlag(Grow) && !flags.testFlag(Shrink)) { grow_items.push_back(item); } else if (flags.testFlag(Shrink)) { shrink_items.push_back(item); } } int available = main_length - total_main; // ---------- Grow ---------- if (available > 0 && !grow_items.empty()) { int count = grow_items.size(); int each = available / count; int remain = available % count; for (int i = 0; i < grow_items.size(); ++i) { auto* item = grow_items[i]; int delta = each + (i < remain ? 1 : 0); int len = T::get_main_len(item); T::set_main_len(item, len + delta); } available = 0; } // ---------- Shrink(按比例,修正版本) ---------- if (available < 0 && !shrink_items.empty()) { int deficit = -available; int shrink_cap = 0; for (auto* item : shrink_items) { shrink_cap += T::get_main_len(item); } if (shrink_cap > 0) { int actual_shrink = std::min(deficit, shrink_cap); int remain = actual_shrink; for (int i = 0; i < shrink_items.size(); ++i) { auto* item = shrink_items[i]; int cur = T::get_main_len(item); int delta = actual_shrink * cur / shrink_cap; if (i == shrink_items.size() - 1) delta = remain; // 吃掉误差 delta = std::min(delta, cur); T::set_main_len(item, cur - delta); remain -= delta; } available += actual_shrink; } } // ---------- 最后一步:设置每个 item 的位置 ---------- int main_pos = main_prefix; for (Layout_Item* item : items) { auto dr = item->direction; if (dr == Direction::Default) { dr = direction; if (dr == Direction::Default) { dr = Direction::Middle; } } if (dr == Direction::Middle) { int cur = T::get_cros_len(item); auto middle = cros_prefix + (cros_length - cros_prefix - cros_suffix) / 2; auto pos = middle - cur / 2; T::set_cros(item, pos); } else if (dr == Direction::First) { T::set_cros(item, cros_prefix); } else if (dr == Direction::Last) { int cur = T::get_cros_len(item); auto last = cros_length - cros_suffix; auto pos = last - cur; T::set_cros(item, pos); } else { std::cout << "未知的类型 " << VAR_STR_1(dr) << LOG_POS << std::endl; std::terminate(); } T::set_main(item, main_pos); main_pos += T::get_main_len(item) + space; } } void Layout::layout() { if (orientation == Qt::Horizontal) layout_impl(); else layout_impl(); } } // namespace Psc