Files
endorphin-tessera-gui/examples/layout-negotiation.endor
T

48 lines
2.9 KiB
Plaintext

// 测量/排列协商示例:arrange 指定子宽后需重新换行测量,高度变化继续影响父容器和后继位置,直到整树稳定。
// paragraph 被两个容器共享;每个 Mount 使用独立约束,不能把新宽度写回共享文字状态。
// 保存第一个段落出现位置的分配宽度,按钮只改策略值。
class Policy {
width: Number
// 选择 280 逻辑像素宽度,段落变高,后继文字下移。
function narrow(self: Policy, event: Event): Unit { self.width = 280 }
// 选择 560 逻辑像素宽度,段落变矮;另一个容器宽度不跟着改变。
function wide(self: Policy, event: Event): Unit { self.width = 560 }
}
// 在原生 Column 排列基础上覆盖第一个稳定子槽的宽度。
class ArrangedColumn: Column {
policy: Policy
// 先取得包含全部子槽的 Arrangement,仅改第一子项分配;保留其他槽使排列验证完整。
function arrange(self: ArrangedColumn, mount: Mount, geometry: Bounds): Arrangement {
result = Column.arrange(self, mount, geometry)
result.children.at(0).width = self.policy.width
return result
}
}
// 通过源 measure 改整个容器的期望宽度,以对比 arrange 分配路径。
class MeasuredColumn: Column {
width: Number
// 调用原生测量后修改新结果 width;这个新结果不属于已有业务对象,允许在只读计算中填写。
function measure(self: MeasuredColumn, mount: Mount, constraints: Constraints): MeasureResult {
result = Column.measure(self, mount, constraints)
result.width = self.width
return result
}
}
// 两个容器使用同一个 paragraph,分别由 Policy=280 与 measure.width=360 约束。
policy = Policy(280)
paragraph = TextBlock("源码 arrange 改变分配宽度后,文字会按实际宽度重新测量。增加的高度继续影响容器和相邻对象,直到整棵布局稳定后才发布。这里与下面使用的是同一个 TextBlock;每个 Mount 都有自己的约束与几何。同一套内存对象不需要复制业务状态,也不通过丢弃传播来结束更新。")
tail = TextBlock("这一行跟随上方段落。")
arranged = ArrangedColumn(0, 12, paragraph, tail, policy)
measured = MeasuredColumn(0, 12, paragraph, TextBlock("这一段的宽度来自源码 measure。"), 360)
narrow = Button("arrange 为 280")
wide = Button("arrange 为 560")
// 保留事件订阅引用,两个按钮调用同一 Policy 的不同方法。
narrowConnection = narrow.on("click", policy.narrow)
wideConnection = wide.on("click", policy.wide)
page = Page()
page.title = "约束协商"
page.render(Column(24, 16, Row(0, 12, narrow, wide), arranged, measured))
// 成功输入结束后宿主才消费原生窗口命令;窗口实际尺寸再回传为下一次布局约束。
ui.window().resize(850, 700)
ui.window().setTitle("测量与排列直到稳定")