diff --git a/example/src/main.cpp b/example/src/main.cpp index 0286b4b..b3815da 100644 --- a/example/src/main.cpp +++ b/example/src/main.cpp @@ -23,8 +23,8 @@ int main(int argc, char* argv[]) { border->set_content(button) .h_alignment(horizontal_alignment::stretch) - .v_alignment(vertical_alignment::bottom) - .margin({ 20 }); + .v_alignment(vertical_alignment::stretch) + .margin({ 10 }); app.run(); return 0; diff --git a/src/geometry/arranged_children.h b/src/geometry/arranged_children.h index 6401234..dcf750a 100644 --- a/src/geometry/arranged_children.h +++ b/src/geometry/arranged_children.h @@ -15,6 +15,11 @@ public: [[nodiscard]] auto& get_geometry() { return geometry_; } [[nodiscard]] const auto& get_geometry() const { return geometry_; } [[nodiscard]] const auto& get_widget() const { return widget_; } + + void set_geometry(const geometry_t& in_geometry) { geometry_ = in_geometry; } + + [[nodiscard]] + auto operator==(const arranged_widget& in_other) const { return widget_ == in_other.widget_; } diff --git a/src/geometry/geometry.h b/src/geometry/geometry.h index 1c3db1e..6ece842 100644 --- a/src/geometry/geometry.h +++ b/src/geometry/geometry.h @@ -45,6 +45,11 @@ public: */ [[nodiscard]] const auto& get_local_size() const { return size_; } + /** + * 设置此几何体的本地大小 + */ + void set_local_size(const Eigen::Vector2f& in_size) { size_ = in_size; } + /** * 获取本地坐标系中的矩形 */ @@ -153,15 +158,14 @@ public: */ [[nodiscard]] auto with_new_offset(const Eigen::Vector2f& in_offset) const { - // 创建一个新的本地到父级变换,使用相同的缩放但新的偏移 - transform2d local_to_parent; - const auto& scale = local_to_parent_.get_scale(); - local_to_parent.set_transform(in_offset, 0.0f, scale); + // 创建一个表示偏移的变换(从缩小后的空间到原始空间) + transform2d offset_transform; + offset_transform.set_transform(in_offset, 0.0f, Eigen::Vector2f(1.0f, 1.0f)); - // 计算新的本地到绝对变换 - const transform2d parent_to_absolute = local_to_absolute_.concatenate(local_to_parent_.inverse()); - - return geometry_t(size_, local_to_parent, parent_to_absolute); + // 更新变换 - 先应用原变换,再应用偏移变换 + auto local_to_parent = local_to_parent_.concatenate(offset_transform); + auto local_to_absolute = local_to_absolute_.concatenate(offset_transform); + return geometry_t(size_, local_to_parent, local_to_absolute); } /** @@ -196,8 +200,9 @@ public: * @param in_margin 要缩小的边距 */ void shrink(const margin_t& in_margin) { + size_ -= in_margin.size(); // 获取左上角偏移 - const Eigen::Vector2f offset = in_margin.left_top(); + const Eigen::Vector2f offset = in_margin.top_left(); // 创建一个表示偏移的变换(从缩小后的空间到原始空间) transform2d offset_transform; diff --git a/src/geometry/margin.h b/src/geometry/margin.h index 9ce5471..285e7c1 100644 --- a/src/geometry/margin.h +++ b/src/geometry/margin.h @@ -15,7 +15,7 @@ struct margin_t { static auto all(float in_uniform) { return margin_t(in_uniform); } static auto symmetric(float in_horizontal, float in_vertical) { return margin_t(in_horizontal, in_vertical); } - auto left_top() const { + auto top_left() const { return Eigen::Vector2f(left, top); } auto right_bottom() const { diff --git a/src/widget/compound_widget/mborder.cpp b/src/widget/compound_widget/mborder.cpp index 6709b36..b86447d 100644 --- a/src/widget/compound_widget/mborder.cpp +++ b/src/widget/compound_widget/mborder.cpp @@ -1,11 +1,77 @@ #include "mborder.h" void mborder::arrange_children(const geometry_t& in_allotted_geometry, arranged_children& in_arranged_children) { - mcompound_widget::arrange_children(in_allotted_geometry, in_arranged_children); - auto& children = in_arranged_children.get_children(); - for (auto& child: children) { - auto& child_geo = child.get_geometry(); - const auto& margin = child_slot_.margin(); - child_geo.shrink(margin); - } + if (const std::shared_ptr child_widget = child_slot_.get()) { + const auto& local_size = in_allotted_geometry.get_local_size(); + Eigen::Vector2f child_desired_size = child_widget->get_desired_size(); + auto margin = child_slot_.margin(); + + // 计算考虑边距后的有效可用空间 + Eigen::Vector2f available_size{ + local_size.x() - margin.horizontal(), + local_size.y() - margin.vertical() + }; + + // 确保可用空间不为负 + available_size = available_size.cwiseMax(Eigen::Vector2f::Zero()); + + auto h_alignment = child_slot_.h_alignment(); + auto v_alignment = child_slot_.v_alignment(); + + // 计算子部件的位置和大小 + Eigen::Vector2f child_size = child_desired_size; // 默认使用期望尺寸 + Eigen::Vector2f child_pos = margin.top_left(); // 初始位置包含左上边距 + + // 水平对齐计算 - 考虑margin后的可用空间 + switch (h_alignment) { + case horizontal_alignment::left: + // 左对齐 - 使用期望宽度,位置在左侧 + 左边距 + // child_pos.x() 已经包含了margin.left() + break; + case horizontal_alignment::center: + // 中心对齐 - 使用期望宽度,位置居中 + 左边距 + child_pos.x() = margin.left + (available_size.x() - child_desired_size.x()) / 2; + break; + case horizontal_alignment::right: + // 右对齐 - 使用期望宽度,位置在右侧,考虑右边距 + child_pos.x() = local_size.x() - child_desired_size.x() - margin.right; + break; + case horizontal_alignment::stretch: + // 拉伸 - 使用全部可用宽度(减去边距) + child_size.x() = available_size.x(); + // child_pos.x() 已经包含了margin.left() + break; + default: + // 默认值已设置为包含左边距 + break; + } + + // 垂直对齐计算 - 考虑margin后的可用空间 + switch (v_alignment) { + case vertical_alignment::top: + // 顶部对齐 - 使用期望高度,位置在顶部 + 上边距 + // child_pos.y() 已经包含了margin.top() + break; + case vertical_alignment::center: + // 中心对齐 - 使用期望高度,位置居中 + 上边距 + child_pos.y() = margin.top + (available_size.y() - child_desired_size.y()) / 2; + break; + case vertical_alignment::bottom: + // 底部对齐 - 使用期望高度,位置在底部,考虑下边距 + child_pos.y() = local_size.y() - child_desired_size.y() - margin.bottom; + break; + case vertical_alignment::stretch: + // 拉伸 - 使用全部可用高度(减去边距) + child_size.y() = available_size.y(); + // child_pos.y() 已经包含了margin.top() + break; + default: + // 默认值已设置为包含上边距 + break; + } + + // 创建子几何体并添加到排列的子元素中 + const auto child_geo = in_allotted_geometry.make_child(child_pos, child_size); + in_arranged_children.add_widget(arranged_widget(child_geo, child_widget)); + } } diff --git a/src/widget/compound_widget/mcompound_widget.h b/src/widget/compound_widget/mcompound_widget.h index 34e911a..cafc3cb 100644 --- a/src/widget/compound_widget/mcompound_widget.h +++ b/src/widget/compound_widget/mcompound_widget.h @@ -49,59 +49,71 @@ uint32_t mcompound_widget::on_paint(render_elements& in_drawer, geomet template void mcompound_widget::arrange_children(const geometry_t& in_allotted_geometry, arranged_children& in_arranged_children) { - if (const std::shared_ptr child_widget = child_slot_.get()) { - const auto& local_size = in_allotted_geometry.get_local_size(); - Eigen::Vector2f child_desired_size = child_widget->get_desired_size(); + if (const std::shared_ptr child_widget = child_slot_.get()) { + const auto& local_size = in_allotted_geometry.get_local_size(); + Eigen::Vector2f child_desired_size = child_widget->get_desired_size(); - auto h_alignment = child_slot_.h_alignment(); - auto v_alignment = child_slot_.v_alignment(); + auto h_alignment = child_slot_.h_alignment(); + auto v_alignment = child_slot_.v_alignment(); - // 计算子部件的位置和大小 - Eigen::Vector2f child_size = {0, 0}; // 局部 - Eigen::Vector2f child_pos = {0, 0}; // 局部 + // 计算子部件的位置和大小 + Eigen::Vector2f child_size = child_desired_size; // 默认使用期望尺寸 + Eigen::Vector2f child_pos = {0, 0}; - switch (h_alignment) { - case horizontal_alignment::left: - child_size.x() = child_desired_size.x(); - child_pos.x() = 0; - break; - case horizontal_alignment::center: - child_size.x() = child_desired_size.x(); - child_pos.x() = local_size.x() / 2 - child_desired_size.x(); - break; - case horizontal_alignment::right: - child_size.x() = local_size.x() - child_desired_size.x(); - child_pos.x() = local_size.x() - child_desired_size.x(); - break; - case horizontal_alignment::stretch: - child_size.x() = local_size.x(); - child_pos.x() = 0; - break; - default:break; - } - switch (v_alignment) { - case vertical_alignment::top: - child_size.y() = child_desired_size.y(); - child_pos.y() = 0; - break; - case vertical_alignment::center: - child_size.y() = child_desired_size.y(); - child_pos.y() = local_size.y() / 2 - child_desired_size.y(); - break; - case vertical_alignment::bottom: - child_size.y() = local_size.y() - child_desired_size.y(); - child_pos.y() = local_size.y() - child_desired_size.y(); - break; - case vertical_alignment::stretch: - child_size.y() = local_size.y(); - child_pos.y() = 0; - break; - default:break; - } + // 水平对齐计算 + switch (h_alignment) { + case horizontal_alignment::left: + // 左对齐 - 使用期望宽度,位置在左侧 + child_pos.x() = 0; + break; + case horizontal_alignment::center: + // 中心对齐 - 使用期望宽度,位置居中 + child_pos.x() = (local_size.x() - child_desired_size.x()) / 2; + break; + case horizontal_alignment::right: + // 右对齐 - 使用期望宽度,位置在右侧 + child_pos.x() = local_size.x() - child_desired_size.x(); + break; + case horizontal_alignment::stretch: + // 拉伸 - 使用全部可用宽度 + child_size.x() = local_size.x(); + child_pos.x() = 0; + break; + default: + // 默认为左对齐 + child_pos.x() = 0; + break; + } - const auto child_geo = in_allotted_geometry.make_child(child_pos, child_size); - in_arranged_children.add_widget(arranged_widget(child_geo, child_widget)); - } + // 垂直对齐计算 + switch (v_alignment) { + case vertical_alignment::top: + // 顶部对齐 - 使用期望高度,位置在顶部 + child_pos.y() = 0; + break; + case vertical_alignment::center: + // 中心对齐 - 使用期望高度,位置居中 + child_pos.y() = (local_size.y() - child_desired_size.y()) / 2; + break; + case vertical_alignment::bottom: + // 底部对齐 - 使用期望高度,位置在底部 + child_pos.y() = local_size.y() - child_desired_size.y(); + break; + case vertical_alignment::stretch: + // 拉伸 - 使用全部可用高度 + child_size.y() = local_size.y(); + child_pos.y() = 0; + break; + default: + // 默认为顶部对齐 + child_pos.y() = 0; + break; + } + + // 创建子几何体并添加到排列的子元素中 + const auto child_geo = in_allotted_geometry.make_child(child_pos, child_size); + in_arranged_children.add_widget(arranged_widget(child_geo, child_widget)); + } } template diff --git a/third_party/msdfgen b/third_party/msdfgen index 0388956..84bfb2a 160000 --- a/third_party/msdfgen +++ b/third_party/msdfgen @@ -1 +1 @@ -Subproject commit 03889564a50452fa2e0b0a60973b5057001b391b +Subproject commit 84bfb2a402a3cffa4b44fb75123b37297ff37477