// 测量/排列协商示例: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("测量与排列直到稳定")