fix(app-iced): M102 页面几何 —— 正文块贴左吃满页宽、列表末行不再被裁半行、日志按词断行
① 正文列与页头不对齐(下载 / 日志):根因是 `frame::single_column` 把**行宽上限 424** 当成**整页块宽度**并水平居中(1180 下 1044 里只摆 424,左缘 422 对页头标题 112)。 现在两个量分开:`layout` 的 `column` 只管成段散文(≤424),页面块宽走新的 `frame::body_width`(= available / main_pane)。新增 `frame::body`(贴左吃满)与 `frame::prose`(散文锁 424)。1180×760 下下载 / 日志的块左缘 = 112 = 页头标题左缘。 ② 实例列表末行被裁半行:页级行距 `Space::X1`(4) 让行节奏变成 64、与可视高度除不尽, 且滚动区直贴卡片 1px 圆角描边。行距归零(下载页同改)+ 滚动区底部内缩 `Space::X2`(8) ⇒ 可视区 580−32−8 = 540 = 9×60,Redstone Lab 及其副标题完整可见,第 10 行整体在裁切线外。 ③ 日志断行把单词劈开(`graphics.gl_o` / `peration_failure`):新增 `layout::wrap::breakable`,在 `.` `_` `:` `/` `\` 后插零宽空格(U+200B 软断点), 日志行正文与一行摘要都过它;悬挂缩进不变(前缀仍是独立文本控件), `Line::text` 与 `Logs::summary()`(剪贴板)仍是原文。工具函数放 `pages/layout/`: 断点是「列宽之后」的另一半排版判据,纯函数、可单测、不碰控件树。 护栏:`body_block_starts_at_the_header_title_and_fills_the_page`、 `list_viewport_fits_whole_rows_and_still_overflow`(把 580/32/8/540/60 五个数钉住)、 `wrap::tests`(断点位置 / 不重复插 / 可还原 / 幂等)、`log_text_carries_soft_breaks_but_keeps_the_original`。 `download/tests.rs` 的「宽窗留白」口径按新分工改成「宽度归块、不归散文列」。
This commit is contained in:
1 parent
8574d6ba2d
commit
89d98184c1
15 files changed
+466
-53
No files matched your search
@@ -4,8 +4,8 @@
|
||||
//!
|
||||
//! | 版面 | 结构 | 退化行为 |
|
||||
//! |---|---|---|
|
||||
//! | `ListDetail`(窗口 ≥840) | 左列 336 固定、**独立滚动**;右列详情,正文列 ≤424 | — |
|
||||
//! | `SingleColumn`(<840) | 列表与详情**整页切换**:本页只渲染详情列(≤424,居中) | 顶部给「Back to instances」,列表退成上一屏 |
|
||||
//! | `ListDetail`(窗口 ≥840) | 左列 336 固定、**独立滚动**;右列详情,散文 ≤424 | — |
|
||||
//! | `SingleColumn`(<840) | 列表与详情**整页切换**:本页只渲染详情列(块贴左吃满页宽,散文 ≤424) | 顶部给「Back to instances」,列表退成上一屏 |
|
||||
//!
|
||||
//! 为什么窄窗不是「上下堆」:官方 compact 下 list-detail 的口径是一次只显示一个 pane(列表 → 详情,
|
||||
//! 整页切换)。上下堆会把详情挤到折叠线以下,等于详情不存在。
|
||||
@@ -27,6 +27,21 @@
|
||||
//! M84 的行高是「`row_height` 44 + `Space::X3` 12 = 56」的手工值;真 `ListItem` 的两行档是
|
||||
//! **60**(令牌 `row_height` 44 + 每多一行 16,A1 是 72)。差异来自组件自己的几何真源,
|
||||
//! 页面不许覆盖——这正是「接真组件」的应有结果。列表仍高于可视区,独立滚动条照样可见。
|
||||
//!
|
||||
//! ## 行距归零 + 底部内缩(M102,视觉复审 ②)
|
||||
//!
|
||||
//! 视觉复审在 1180×760 的截图里抓到「末行 Redstone Lab 被卡片底边切掉半行(副标题消失)」。
|
||||
//! 根因是**两道页级附加量**:`Space::X1` 的行距让行节奏变成 64,与可视高度除不尽;
|
||||
//! 列表滚动区贴到卡片的 1px 圆角描边上,切点正好落在描边线上。修法两件:
|
||||
//!
|
||||
//! | 改什么 | 值 | 结果 |
|
||||
//! |---|---|---|
|
||||
//! | 页级行距 | 4 → **0**(见 `download/rows.rs` 同一条) | 行节奏回到组件的 60 |
|
||||
//! | 滚动区底部内缩 | 0 → **`Space::X2` 8** | 切点落在卡片的内边距带里,不压描边 |
|
||||
//!
|
||||
//! 于是可视区 = 580 − 列头 32 − 内缩 8 = **540 = 9 × 60**,正好 9 整行:末行完整可见,
|
||||
//! 第 10 行整体落在裁切线之外(`instances/tests.rs::list_viewport_fits_whole_rows_and_still_overflow`
|
||||
//! 把这四个数钉住)。列表内容 12×60 = 720 仍高过可视区,独立滚动条照样可见。
|
||||
|
||||
mod data;
|
||||
mod demo;
|
||||
@@ -60,8 +75,11 @@ use super::layout::{FrameMetrics, PageLayout};
|
||||
use super::model::{Instances, Model, Row};
|
||||
use super::{Action, Message};
|
||||
|
||||
/// 列表行的间距(`Space::X1`;与 M84 同值,行高差异全部来自 `ListItem` 自己的几何)。
|
||||
const ROW_GAP: Space = Space::X1;
|
||||
/// 列表滚动区的**底部内缩**(`Space::X2`):让裁切线落在卡片的内边距带里,而不是压在 1px 描边上。
|
||||
///
|
||||
/// 行距归零(`list()` 不写 `.spacing(…)`)与这条内缩是一对,理由见模块文档「行距归零(M102)」
|
||||
/// 与本页 `instances.rs` 的同名条目。
|
||||
const LIST_BOTTOM_INSET: Space = Space::X2;
|
||||
|
||||
/// 整页(`block.detail = None` 时详情区显示空态)。
|
||||
pub fn view<'a>(ui: &'a Ui, metrics: FrameMetrics, model: &'a Model) -> Element<'a, Message> {
|
||||
@@ -95,7 +113,7 @@ pub fn view<'a>(ui: &'a Ui, metrics: FrameMetrics, model: &'a Model) -> Element<
|
||||
),
|
||||
_ => match &block.detail {
|
||||
Some(detail) => detail::narrow_detail(ui, metrics, detail, forced),
|
||||
None => frame::single_column(metrics, detail::detail_empty(ui)),
|
||||
None => frame::body(metrics, detail::detail_empty(ui)),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -146,7 +164,6 @@ fn list_column<'a>(
|
||||
.map(|entry| list_row(ui, entry, is_selected(block, entry), forced))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.spacing(ui.space(ROW_GAP))
|
||||
.padding(Padding::from([0.0, ui.space(Space::X2)]))
|
||||
.width(Length::Fill);
|
||||
|
||||
@@ -161,9 +178,11 @@ fn list_column<'a>(
|
||||
.height(Length::Fill)
|
||||
.style(frame::scroll_style(ui));
|
||||
|
||||
// 底部内缩:裁切线落在卡片的内边距带里,而不是压在圆角描边上(M102 / 视觉复审 ②)。
|
||||
container(column![head, scroller].height(Length::Fill))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.padding(Padding::default().bottom(ui.space(LIST_BOTTOM_INSET)))
|
||||
.style(move |_theme| container::Style {
|
||||
background: Some(Background::Color(ui.layer(MaterialLayer::Card))),
|
||||
border: Border {
|
||||
|
||||
Reference in new issue
Block a user