diff --git a/src/app/update.rs b/src/app/update.rs index c818abc35..a526fa9a3 100644 --- a/src/app/update.rs +++ b/src/app/update.rs @@ -6170,7 +6170,9 @@ impl OpenCADStudio { // ── Shared inline rename (all style managers) ───────────────── Message::StyleRenameStart(kind, name) => { self.style_rename_start(kind, name); - Task::none() + // Focus the freshly-shown rename field so the user can type + // immediately after the double click. + iced::widget::operation::focus(crate::ui::style_list::rename_input_id()) } Message::StyleRenameEdit(s) => { self.style_rename_buf = s; diff --git a/src/ui/style_list.rs b/src/ui/style_list.rs index 5518e2bf6..c6728e157 100644 --- a/src/ui/style_list.rs +++ b/src/ui/style_list.rs @@ -1,28 +1,51 @@ //! Shared style-manager list row. //! //! Every style manager renders the same left-hand list of style names where a -//! single click selects and a double click renames inline. Only the row's -//! button style differs per manager, so it is passed in. +//! single click selects and a double click renames inline. +//! +//! The whole row is a `mouse_area` (not a `button`): an inner interactive +//! widget would capture the press and the parent `mouse_area` would never see +//! the second click, so `on_double_click` would never fire. `mouse_area` +//! carries both `on_press` (select) and `on_double_click` (rename) itself. use crate::app::{Message, StyleKind}; -use iced::widget::button::{Status, Style}; -use iced::widget::{button, mouse_area, text, text_input}; -use iced::{Element, Fill, Theme}; +use iced::widget::{container, mouse_area, text, text_input}; +use iced::{Background, Color, Element, Fill, Theme}; + +/// Shared id for the inline rename field, so the rename-start handler can focus +/// it the moment the row turns editable. +pub fn rename_input_id() -> iced::widget::Id { + iced::widget::Id::new("style-rename-input") +} + +const TEXT: Color = Color { + r: 0.88, + g: 0.88, + b: 0.88, + a: 1.0, +}; +const ACTIVE: Color = Color { + r: 0.20, + g: 0.40, + b: 0.70, + a: 1.0, +}; /// One row of the style list. Renders an editable `text_input` when `name` is -/// the style being renamed (`rename_active`), otherwise a selectable button -/// wrapped in a `mouse_area` whose double click starts the rename. +/// the style being renamed (`rename_active`), otherwise a selectable row whose +/// double click starts the rename. pub fn item<'a>( name: &str, label: String, + is_selected: bool, kind: StyleKind, on_select: Message, rename_active: Option<&str>, rename_buf: &'a str, - style: impl Fn(&Theme, Status) -> Style + 'a, ) -> Element<'a, Message> { if rename_active == Some(name) { text_input("", rename_buf) + .id(iced::widget::Id::new("style-rename-input")) .on_input(Message::StyleRenameEdit) .on_submit(Message::StyleRenameCommit(kind)) .size(11) @@ -30,14 +53,17 @@ pub fn item<'a>( .width(Fill) .into() } else { - mouse_area( - button(text(label).size(11)) - .on_press(on_select) - .style(style) - .padding([4, 8]) - .width(Fill), - ) - .on_double_click(Message::StyleRenameStart(kind, name.to_string())) - .into() + let row = container(text(label).size(11).color(TEXT)) + .padding([4, 8]) + .width(Fill) + .style(move |_: &Theme| container::Style { + background: is_selected.then_some(Background::Color(ACTIVE)), + text_color: Some(TEXT), + ..Default::default() + }); + mouse_area(row) + .on_press(on_select) + .on_double_click(Message::StyleRenameStart(kind, name.to_string())) + .into() } } diff --git a/src/ui/style_manager.rs b/src/ui/style_manager.rs index 5fbecde02..b85aab36f 100644 --- a/src/ui/style_manager.rs +++ b/src/ui/style_manager.rs @@ -48,12 +48,6 @@ const ACCENT: Color = Color { b: 0.85, a: 1.0, }; -const ACTIVE: Color = Color { - r: 0.20, - g: 0.40, - b: 0.70, - a: 1.0, -}; const LIST: Color = Color { r: 0.12, g: 0.12, @@ -128,11 +122,11 @@ pub fn view<'a, 'b>(s: Scaffold<'a, 'b>) -> Element<'a, Message> { crate::ui::style_list::item( name, label, + is_sel, s.kind, (s.on_select)(name.clone()), s.rename_active, s.rename_buf, - list_item(is_sel), ) }) .collect(); @@ -222,23 +216,6 @@ fn btn_s(accent: bool) -> impl Fn(&Theme, Status) -> Style { } } -fn list_item(active: bool) -> impl Fn(&Theme, Status) -> Style { - move |_: &Theme, st| Style { - background: Some(Background::Color(match (active, st) { - (true, _) => ACTIVE, - (false, Status::Hovered | Status::Pressed) => Color { - r: 0.26, - g: 0.26, - b: 0.26, - a: 1.0, - }, - _ => Color::TRANSPARENT, - })), - text_color: TEXT, - ..Default::default() - } -} - fn hdivider<'a>() -> Element<'a, Message> { container(Space::new().width(Fill).height(1)) .width(Fill)