From 5680a62d88a71d1f054e0b3bc9f0bb2907836f37 Mon Sep 17 00:00:00 2001 From: Kayshen-X Date: Sun, 14 Jun 2026 06:43:50 +0800 Subject: [PATCH] refactor(editor): route variables panel menus through shared feedback --- .../src/widgets/variables_panel/hover.rs | 38 +++++++ .../src/widgets/variables_panel/menus.rs | 101 ++++++++++++------ 2 files changed, 107 insertions(+), 32 deletions(-) diff --git a/crates/op-editor-ui/src/widgets/variables_panel/hover.rs b/crates/op-editor-ui/src/widgets/variables_panel/hover.rs index b6c2a07cd..6a0f14aaf 100644 --- a/crates/op-editor-ui/src/widgets/variables_panel/hover.rs +++ b/crates/op-editor-ui/src/widgets/variables_panel/hover.rs @@ -191,4 +191,42 @@ mod tests { "pressed add-theme button should paint shared pressed feedback" ); } + + #[test] + fn pressed_add_variable_menu_item_paints_shared_feedback() { + let mut state = themed_state(); + state.editor_ui.variables_add_menu_open = true; + state.editor_ui.pressed_button = Some(ButtonPressTarget::VariablesPanel( + VariablesPanelButton::AddVariableMenuItem(1), + )); + let panel = VariablesPanel::for_editor(&state); + let rect = Rect { + origin: Point2D::new(0.0, 0.0), + size: Point2D::new(VARIABLES_PANEL_WIDTH, panel.intrinsic_height()), + }; + let menu = add_variable_menu_rect(rect); + let row_y = menu.origin.y + ADD_VARIABLE_MENU_ROW_HEIGHT; + let expected_rect = Rect { + origin: Point2D::new(menu.origin.x + 4.0, row_y + 3.0), + size: Point2D::new(menu.size.x - 8.0, ADD_VARIABLE_MENU_ROW_HEIGHT - 6.0), + }; + let expected_color = panel + .theme + .button_hover + .with_alpha(panel.theme.button_hover.a * 1.8); + let mut backend = HoverBackend::default(); + let mut cx = PaintCx { + backend: &mut backend, + }; + + panel.paint(&mut cx, rect); + + assert!( + backend + .round_fills + .iter() + .any(|(fill, color)| *fill == expected_rect && *color == expected_color), + "pressed add-variable menu item should paint shared pressed feedback" + ); + } } diff --git a/crates/op-editor-ui/src/widgets/variables_panel/menus.rs b/crates/op-editor-ui/src/widgets/variables_panel/menus.rs index 99deffacb..72d50b921 100644 --- a/crates/op-editor-ui/src/widgets/variables_panel/menus.rs +++ b/crates/op-editor-ui/src/widgets/variables_panel/menus.rs @@ -4,10 +4,35 @@ use super::paint::paint_text; use super::*; +use crate::widgets::button::paint_button_feedback_wash; use crate::widgets::{draw_icon, Icon, PaintCx}; use crate::{Point2D, Rect}; +use op_editor_core::variables_panel_state::PresetMenuButton; use op_editor_core::VariablesPanelButton; +fn paint_feedback( + panel: &VariablesPanel, + cx: &mut PaintCx<'_>, + target: VariablesPanelButton, + rect: Rect, + radius: f32, +) { + let hovered = panel.hover == Some(target); + let pressed = panel.pressed == Some(target); + if hovered || pressed { + paint_button_feedback_wash(cx.backend, &panel.theme, rect, radius, hovered, pressed); + } +} + +fn preset_menu_row(button: PresetMenuButton) -> usize { + match button { + PresetMenuButton::SaveCurrent | PresetMenuButton::NameInput => 0, + PresetMenuButton::Load(idx) | PresetMenuButton::Delete(idx) => 1 + idx, + PresetMenuButton::Import => 2, + PresetMenuButton::Export => 3, + } +} + pub(super) fn paint_menus( panel: &VariablesPanel, cx: &mut PaintCx<'_>, @@ -27,19 +52,16 @@ pub(super) fn paint_menus( ]; for (idx, (label, icon, color)) in rows.iter().enumerate() { let row_y = menu.origin.y + idx as f32 * ADD_VARIABLE_MENU_ROW_HEIGHT; - if matches!( - panel.hover, - Some(VariablesPanelButton::RowMenuItem(i)) if i == idx - ) { - cx.backend.fill_round_rect( - Rect { - origin: Point2D::new(menu.origin.x + 4.0, row_y + 3.0), - size: Point2D::new(menu.size.x - 8.0, ADD_VARIABLE_MENU_ROW_HEIGHT - 6.0), - }, - 8.0, - theme.button_hover, - ); - } + paint_feedback( + panel, + cx, + VariablesPanelButton::RowMenuItem(idx), + Rect { + origin: Point2D::new(menu.origin.x + 4.0, row_y + 3.0), + size: Point2D::new(menu.size.x - 8.0, ADD_VARIABLE_MENU_ROW_HEIGHT - 6.0), + }, + 8.0, + ); draw_icon( cx.backend, *icon, @@ -63,16 +85,11 @@ pub(super) fn paint_menus( labels.export, ], match panel.hover { - Some(VariablesPanelButton::PresetMenuItem(button)) => match button { - op_editor_core::variables_panel_state::PresetMenuButton::SaveCurrent - | op_editor_core::variables_panel_state::PresetMenuButton::NameInput => Some(0), - op_editor_core::variables_panel_state::PresetMenuButton::Load(idx) - | op_editor_core::variables_panel_state::PresetMenuButton::Delete(idx) => { - Some(1 + idx) - } - op_editor_core::variables_panel_state::PresetMenuButton::Import => Some(2), - op_editor_core::variables_panel_state::PresetMenuButton::Export => Some(3), - }, + Some(VariablesPanelButton::PresetMenuItem(button)) => Some(preset_menu_row(button)), + _ => None, + }, + match panel.pressed { + Some(VariablesPanelButton::PresetMenuItem(button)) => Some(preset_menu_row(button)), _ => None, }, ); @@ -87,6 +104,10 @@ pub(super) fn paint_menus( Some(VariablesPanelButton::AddVariableMenuItem(idx)) => Some(idx), _ => None, }, + match panel.pressed { + Some(VariablesPanelButton::AddVariableMenuItem(idx)) => Some(idx), + _ => None, + }, ); } if let Some(axis) = panel.theme_menu_open.as_deref() { @@ -103,6 +124,10 @@ pub(super) fn paint_menus( Some(VariablesPanelButton::ThemeMenuItem(idx)) => Some(idx), _ => None, }, + match panel.pressed { + Some(VariablesPanelButton::ThemeMenuItem(idx)) => Some(idx), + _ => None, + }, ); } if let Some(value) = panel.variant_menu_open.as_deref() { @@ -119,6 +144,10 @@ pub(super) fn paint_menus( Some(VariablesPanelButton::VariantMenuItem(idx)) => Some(idx), _ => None, }, + match panel.pressed { + Some(VariablesPanelButton::VariantMenuItem(idx)) => Some(idx), + _ => None, + }, ); } paint_axis_dropdown(panel, cx, rect); @@ -157,14 +186,16 @@ fn paint_axis_dropdown(panel: &VariablesPanel, cx: &mut PaintCx<'_>, rect: Rect) .unwrap_or_default(); for (i, v) in values.iter().enumerate() { let row_y = menu_y + (i as f32) * DROPDOWN_ROW_HEIGHT; - if panel.hover == Some(VariablesPanelButton::DropdownItem(i)) { - let highlight = Rect { + paint_feedback( + panel, + cx, + VariablesPanelButton::DropdownItem(i), + Rect { origin: Point2D::new(menu_rect.origin.x + 4.0, row_y + 3.0), size: Point2D::new(menu_rect.size.x - 8.0, DROPDOWN_ROW_HEIGHT - 6.0), - }; - cx.backend - .fill_round_rect(highlight, 8.0, theme.button_hover); - } + }, + 8.0, + ); if *v == active_value { let highlight = Rect { origin: Point2D::new(menu_rect.origin.x + 4.0, row_y + 3.0), @@ -189,19 +220,25 @@ fn paint_popover_rows( rect: Rect, rows: &[&str], hover_row: Option, + pressed_row: Option, ) { cx.backend.fill_round_rect(rect, 12.0, theme.popover); cx.backend.stroke_round_rect(rect, 12.0, theme.border, 1.0); for (idx, label) in rows.iter().enumerate() { let row_y = rect.origin.y + idx as f32 * ADD_VARIABLE_MENU_ROW_HEIGHT; - if hover_row == Some(idx) { - cx.backend.fill_round_rect( + let hovered = hover_row == Some(idx); + let pressed = pressed_row == Some(idx); + if hovered || pressed { + paint_button_feedback_wash( + cx.backend, + &theme, Rect { origin: Point2D::new(rect.origin.x + 4.0, row_y + 3.0), size: Point2D::new(rect.size.x - 8.0, ADD_VARIABLE_MENU_ROW_HEIGHT - 6.0), }, 8.0, - theme.button_hover, + hovered, + pressed, ); } paint_text(