diff --git a/src/app/view/overlay.rs b/src/app/view/overlay.rs index bf61cc394..10d7afe5f 100644 --- a/src/app/view/overlay.rs +++ b/src/app/view/overlay.rs @@ -1127,6 +1127,8 @@ const MENU_CURSOR_INSET_X: f32 = 24.0; /// not the row carries a glyph (object snaps, command icons). const MENU_GUTTER_W: f32 = 18.0; const MENU_ICON_SIZE: f32 = 14.0; +/// Trailing check mark of checked rows; sits in the submenu caret column. +const MENU_CHECK_SIZE: f32 = 10.0; /// The gutter cell: the row's glyph, faded with a disabled row, or empty /// space of the same width. @@ -1264,16 +1266,13 @@ pub(super) fn viewport_context_menu_overlay( position_canvas_overlay_clamped(pos, bottom_inset, offset, panel.into()) } -/// One menu row: label (bold for the default row, "✓ "-prefixed when -/// checked), and the keyword hint right-aligned and dimmed. Disabled rows -/// render without a press handler and with faded text. +/// One menu row: label (bold for the default row), the keyword hint +/// right-aligned and dimmed, and a check mark in the trailing column (where +/// submenu headers draw their caret) when checked, so checked labels stay +/// aligned with the others. Disabled rows render without a press handler and +/// with faded text and icons. fn context_menu_row(item: &MenuItem, indent: f32, highlighted: bool) -> Element<'static, Message> { - let label = if item.checked { - format!("✓ {}", item.label) - } else { - item.label.clone() - }; - let mut label_text = text(label).size(12); + let mut label_text = text(item.label.clone()).size(12); if item.default { label_text = label_text.font(iced::Font { weight: iced::font::Weight::Bold, @@ -1303,6 +1302,16 @@ fn context_menu_row(item: &MenuItem, indent: f32, highlighted: bool) -> Element< }), ); } + if item.checked { + if item.hint.is_none() { + content = content.push(iced::widget::Space::new().width(Fill)); + } + content = content.push(if enabled { + crate::ui::icons::themed(crate::ui::icons::CHECK, MENU_CHECK_SIZE) + } else { + crate::ui::icons::themed_disabled(crate::ui::icons::CHECK, MENU_CHECK_SIZE) + }); + } let mut btn = button(content) .padding(iced::Padding { top: 3.0, diff --git a/src/ui/icons.rs b/src/ui/icons.rs index 694b98a07..eaf0c2f41 100644 --- a/src/ui/icons.rs +++ b/src/ui/icons.rs @@ -509,13 +509,16 @@ pub fn themed_secondary<'a, M: 'a>(bytes: &'static [u8], size: f32) -> Element<' .into() } -/// Render disabled chrome with the active Iced theme's text color. +/// Render disabled chrome with the active Iced theme's text color, faded +/// like disabled text. The fade goes through the widget's opacity: an SVG +/// tint only replaces RGB, so alpha on the style colour would be ignored. pub fn themed_disabled<'a, M: 'a>(bytes: &'static [u8], size: f32) -> Element<'a, M> { svg(themed_handle(bytes)) .width(size) .height(size) + .opacity(0.42_f32) .style(|theme: &Theme, _| svg::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.42)), + color: Some(theme.palette().background.base.text), }) .into() }