mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-26 11:09:23 -06:00
LR-BEHAV-TEXTFIELD: Rename Keyword's name field is a shared text field
It gets the Cut / Copy / Paste / Select All menu and opens with the name selected, so typing replaces it. Return now renames: the field took the focus back on every frame, so egui never reported the focus Return gives up and only the OK button renamed. The field still keeps the focus, except while its own menu has it; Esc still cancels the dialog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
aa57db05a1
commit
d1ec843863
@@ -1560,6 +1560,46 @@ mod tests {
|
||||
h.settle(SETTLE);
|
||||
}
|
||||
|
||||
/// Rename Keyword's name field is a shared text field. It opens with the name selected, so
|
||||
/// typing replaces it, and Return renames; right-click ▸ Paste works too; Esc cancels the
|
||||
/// dialog and renames nothing.
|
||||
#[test]
|
||||
fn the_rename_keyword_field_selects_pastes_and_cancels() {
|
||||
let mut h = demo([1200.0, 800.0]);
|
||||
let t = Duration::from_secs(10);
|
||||
let first = h.app.session.visible_cloned()[0].0;
|
||||
h.request("engine.execute", json!({"command": "photo.setMeta", "params": {"ids": [first], "addKeywords": ["travel"]}}), t);
|
||||
let keywords = |h: &Headless| h.app.session.catalog.photo(lightcraft_catalog::PhotoId(first)).unwrap().meta.keywords.clone();
|
||||
let open = |h: &mut Headless, name: &str| {
|
||||
h.app.ui.dialog = Some(crate::state::Dialog::RenameKeyword { from: name.into(), to: name.into() });
|
||||
h.settle(SETTLE);
|
||||
};
|
||||
let ask = |h: &mut Headless, method: &str, params: serde_json::Value| {
|
||||
let r = h.request(method, params.clone(), t);
|
||||
assert_eq!(r["ok"], true, "{method} {params}: {r}");
|
||||
h.settle(SETTLE);
|
||||
};
|
||||
// typing replaces the selected name
|
||||
open(&mut h, "travel");
|
||||
ask(&mut h, "ui.text", json!({"text": "trips"}));
|
||||
ask(&mut h, "ui.key", json!({"key": "Enter"}));
|
||||
assert!(keywords(&h).contains(&"trips".to_string()) && !keywords(&h).contains(&"travel".to_string()), "{:?}", keywords(&h));
|
||||
assert_eq!(h.app.ui.dialog, None);
|
||||
// the menu's Paste
|
||||
open(&mut h, "trips");
|
||||
h.view.clipboard = "weddings".into();
|
||||
ask(&mut h, "ui.clickWidget", json!({"id": "field:keywordName", "button": "right"}));
|
||||
ask(&mut h, "ui.clickWidget", json!({"id": "field:keywordName:paste"}));
|
||||
ask(&mut h, "ui.key", json!({"key": "Enter"}));
|
||||
assert!(keywords(&h).contains(&"weddings".to_string()), "{:?}", keywords(&h));
|
||||
// Esc cancels
|
||||
open(&mut h, "weddings");
|
||||
ask(&mut h, "ui.text", json!({"text": "parties"}));
|
||||
ask(&mut h, "ui.key", json!({"key": "Escape"}));
|
||||
assert_eq!(h.app.ui.dialog, None, "Esc closed the dialog");
|
||||
assert!(keywords(&h).contains(&"weddings".to_string()), "renamed nothing: {:?}", keywords(&h));
|
||||
}
|
||||
|
||||
/// The sidebar's file-system checks run on worker threads and add rows when they land, which
|
||||
/// moves every row below them: `busy()` counts them, so `settle` waits for them before a test
|
||||
/// reads widget positions (a click aimed at a stale rect hits the neighbouring row).
|
||||
|
||||
@@ -410,10 +410,17 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context) {
|
||||
}
|
||||
Dialog::RenameKeyword { from, to } => {
|
||||
let n = app.session.catalog.photos().filter(|p| p.meta.keywords.iter().any(|k| lightcraft_catalog::keywords::is_under(k, from))).count();
|
||||
let r = ui.add(egui::TextEdit::singleline(to).hint_text(crate::i18n::tr("New name")).desired_width(f32::INFINITY));
|
||||
crate::widgets::register(ui.ctx(), "field:keywordName", r.rect);
|
||||
r.request_focus();
|
||||
if r.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter)) {
|
||||
// the name, selected so typing replaces it; Esc cancels the dialog (below)
|
||||
let r = crate::text_field::TextField::singleline("field:keywordName", to)
|
||||
.hint(crate::i18n::tr("New name"))
|
||||
.width(f32::INFINITY)
|
||||
.select_on_focus(true)
|
||||
.show(ui);
|
||||
// the field keeps the focus, but leaves it to its own menu
|
||||
if !r.editing {
|
||||
r.response.request_focus();
|
||||
}
|
||||
if r.ending == Some(crate::text_field::Ending::Return) {
|
||||
confirm = true;
|
||||
}
|
||||
ui.label(
|
||||
|
||||
Reference in New Issue
Block a user