fix(styles): make double-click inline rename actually fire
The list row wrapped a `button` inside the `mouse_area`. The button captured the press, so the parent `mouse_area` never saw the second click and `on_double_click` never fired — double-clicking a style name did nothing. Drop the inner button: the row is now a plain `mouse_area` carrying both `on_press` (select) and `on_double_click` (start rename), with selection shown via the container background. Focus the rename field on start so the user can type immediately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f2dfd01795
commit
65a25033bc
3 changed files with 47 additions and 42 deletions
|
|
@ -6170,7 +6170,9 @@ impl OpenCADStudio {
|
||||||
// ── Shared inline rename (all style managers) ─────────────────
|
// ── Shared inline rename (all style managers) ─────────────────
|
||||||
Message::StyleRenameStart(kind, name) => {
|
Message::StyleRenameStart(kind, name) => {
|
||||||
self.style_rename_start(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) => {
|
Message::StyleRenameEdit(s) => {
|
||||||
self.style_rename_buf = s;
|
self.style_rename_buf = s;
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,51 @@
|
||||||
//! Shared style-manager list row.
|
//! Shared style-manager list row.
|
||||||
//!
|
//!
|
||||||
//! Every style manager renders the same left-hand list of style names where a
|
//! 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
|
//! single click selects and a double click renames inline.
|
||||||
//! button style differs per manager, so it is passed in.
|
//!
|
||||||
|
//! 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 crate::app::{Message, StyleKind};
|
||||||
use iced::widget::button::{Status, Style};
|
use iced::widget::{container, mouse_area, text, text_input};
|
||||||
use iced::widget::{button, mouse_area, text, text_input};
|
use iced::{Background, Color, Element, Fill, Theme};
|
||||||
use iced::{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
|
/// One row of the style list. Renders an editable `text_input` when `name` is
|
||||||
/// the style being renamed (`rename_active`), otherwise a selectable button
|
/// the style being renamed (`rename_active`), otherwise a selectable row whose
|
||||||
/// wrapped in a `mouse_area` whose double click starts the rename.
|
/// double click starts the rename.
|
||||||
pub fn item<'a>(
|
pub fn item<'a>(
|
||||||
name: &str,
|
name: &str,
|
||||||
label: String,
|
label: String,
|
||||||
|
is_selected: bool,
|
||||||
kind: StyleKind,
|
kind: StyleKind,
|
||||||
on_select: Message,
|
on_select: Message,
|
||||||
rename_active: Option<&str>,
|
rename_active: Option<&str>,
|
||||||
rename_buf: &'a str,
|
rename_buf: &'a str,
|
||||||
style: impl Fn(&Theme, Status) -> Style + 'a,
|
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
if rename_active == Some(name) {
|
if rename_active == Some(name) {
|
||||||
text_input("", rename_buf)
|
text_input("", rename_buf)
|
||||||
|
.id(iced::widget::Id::new("style-rename-input"))
|
||||||
.on_input(Message::StyleRenameEdit)
|
.on_input(Message::StyleRenameEdit)
|
||||||
.on_submit(Message::StyleRenameCommit(kind))
|
.on_submit(Message::StyleRenameCommit(kind))
|
||||||
.size(11)
|
.size(11)
|
||||||
|
|
@ -30,14 +53,17 @@ pub fn item<'a>(
|
||||||
.width(Fill)
|
.width(Fill)
|
||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
mouse_area(
|
let row = container(text(label).size(11).color(TEXT))
|
||||||
button(text(label).size(11))
|
.padding([4, 8])
|
||||||
.on_press(on_select)
|
.width(Fill)
|
||||||
.style(style)
|
.style(move |_: &Theme| container::Style {
|
||||||
.padding([4, 8])
|
background: is_selected.then_some(Background::Color(ACTIVE)),
|
||||||
.width(Fill),
|
text_color: Some(TEXT),
|
||||||
)
|
..Default::default()
|
||||||
.on_double_click(Message::StyleRenameStart(kind, name.to_string()))
|
});
|
||||||
.into()
|
mouse_area(row)
|
||||||
|
.on_press(on_select)
|
||||||
|
.on_double_click(Message::StyleRenameStart(kind, name.to_string()))
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,6 @@ const ACCENT: Color = Color {
|
||||||
b: 0.85,
|
b: 0.85,
|
||||||
a: 1.0,
|
a: 1.0,
|
||||||
};
|
};
|
||||||
const ACTIVE: Color = Color {
|
|
||||||
r: 0.20,
|
|
||||||
g: 0.40,
|
|
||||||
b: 0.70,
|
|
||||||
a: 1.0,
|
|
||||||
};
|
|
||||||
const LIST: Color = Color {
|
const LIST: Color = Color {
|
||||||
r: 0.12,
|
r: 0.12,
|
||||||
g: 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(
|
crate::ui::style_list::item(
|
||||||
name,
|
name,
|
||||||
label,
|
label,
|
||||||
|
is_sel,
|
||||||
s.kind,
|
s.kind,
|
||||||
(s.on_select)(name.clone()),
|
(s.on_select)(name.clone()),
|
||||||
s.rename_active,
|
s.rename_active,
|
||||||
s.rename_buf,
|
s.rename_buf,
|
||||||
list_item(is_sel),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.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> {
|
fn hdivider<'a>() -> Element<'a, Message> {
|
||||||
container(Space::new().width(Fill).height(1))
|
container(Space::new().width(Fill).height(1))
|
||||||
.width(Fill)
|
.width(Fill)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue