refactor(app-iced): paint.rs 按组件拆成 paint/ 目录(复审 P2-5)

- paint.rs 原本正好 400 行、零余量:再加一个态就得动它(和 app.rs 同一个问题)
- 拆成 mod.rs(Frame / 状态层 / 禁用色 / 标签色)+ check.rs / radio.rs / switch.rs / chip.rs
- 对外 API 一字不改(selection::paint::* 路径全部保持)
- 顺带把「选中且禁用的 Checkbox 容器」从 12% 改成 A1 的 38%(复审 P2-3):这一行就在被移动的
  check.rs 里,单独切 hunk 只会让历史不完整;断言在下一条提交
This commit is contained in:
AskaEth committed 2026-11-02 06:52:10 +08:00
1 parent b69a2cdd7f
commit 17394b73ff
6 files changed
+460 -400

No files matched your search

@@ -0,0 +1,79 @@
//! Chip 的角色映射(`research/12b` §13.5 / §13.6 / §13.7)。
use unlucky_design::color::Role;
use crate::theme::{Ui, STROKE_PX};
use super::super::super::interaction::Interaction;
use super::{disabled_container, disabled_ink, state_layer, ChipPaint, Frame};
/// Chip 的三种(§13.6 / §13.7):Assist / Filter / Input。
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChipVariant {
/// Assist:**永远未选中**,前置图标 `Primary`(`AssistChipTokens.IconColor`)。
Assist,
/// Filter:可选中(`SecondaryContainer`),选中态无描边。
Filter,
/// Input:可选中 + 后置关闭图标。
Input,
}
/// Chip 的外观。
///
/// 与 Checkbox/Radio 的区别:Chip 的**状态层就是它自己的容器**(M3 的 chip 没有圆形状态层),
/// 所以未选中 + hover 的 fill 是「状态层叠在 surface 上」的实色。
pub fn chip(
ui: &Ui,
variant: ChipVariant,
selected: bool,
state: Interaction,
radius: f32,
) -> ChipPaint {
let selected = selected && !matches!(variant, ChipVariant::Assist);
let label_role = if selected {
Role::OnSecondaryContainer
} else if matches!(variant, ChipVariant::Assist) {
Role::OnSurface
} else {
Role::OnSurfaceVariant
};
if state.is_disabled() {
let ink = disabled_ink(ui, Role::OnSurface);
return ChipPaint {
frame: Frame {
fill: selected.then(|| disabled_container(ui)),
outline: (!selected).then(|| disabled_container(ui)),
stroke: STROKE_PX,
radius,
},
label: ink,
icon: ink,
};
}
let outline = (!selected).then(|| ui.color(Role::OutlineVariant));
let fill = if selected {
Some(ui.color(Role::SecondaryContainer))
} else {
state_layer(ui, state, label_role)
};
// Assist / 选中态的前置图标是 `Primary`(`AssistChipTokens.IconColor` /
// `InputChipTokens.SelectedLeadingIconColor`);其余跟文字同色。
let icon_role = if matches!(variant, ChipVariant::Assist) || selected {
Role::Primary
} else {
label_role
};
ChipPaint {
frame: Frame {
fill,
outline,
stroke: STROKE_PX,
radius,
},
label: ui.color(label_role),
icon: ui.color(icon_role),
}
}