mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 13:17:19 -06:00
Dialogs: keep dialog open on invalid Enter commit and prevent lock nesting in numeric widget
This commit is contained in:
committed by
bflatastic
parent
5da8c8e495
commit
e2828bc064
@@ -656,7 +656,8 @@ pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
}
|
||||
});
|
||||
});
|
||||
if spec.ok.is_some() && ok_enabled && !after_panel && ctx.input(|i| i.key_pressed(egui::Key::Enter)) {
|
||||
let rejected = ctx.data_mut(|d| d.remove_temp::<bool>(widgets::dialog_reject_commit_flag())).unwrap_or(false);
|
||||
if spec.ok.is_some() && ok_enabled && !after_panel && !rejected && ctx.input(|i| i.key_pressed(egui::Key::Enter)) {
|
||||
ok = true;
|
||||
}
|
||||
if discard {
|
||||
|
||||
@@ -2534,14 +2534,15 @@ fn color_halftone_invalid_input_does_not_revert_to_sub_minimum_value() {
|
||||
frame(&mut app, vec![egui::Event::Text("0.5 px".into())]);
|
||||
frame(&mut app, vec![egui::Event::Key { key: egui::Key::Tab, physical_key: None, pressed: true, repeat: false, modifiers: Default::default() }]);
|
||||
assert_eq!(app.ui.dialog.as_ref().unwrap().fields["maxRadius"], serde_json::json!(4.0));
|
||||
// 2. Refocus Max Radius before typing invalid text
|
||||
crate::widgets::arm_field_focus(&ctx, ("dlg-len", "maxRadius"));
|
||||
// 2. Typing invalid text on Enter must NOT confirm/close the dialog; the dialog stays open
|
||||
app.run("effect.dialog", json!({"effect": "pixelate.colorHalftone"})).unwrap();
|
||||
frame(&mut app, vec![]);
|
||||
frame(&mut app, vec![egui::Event::Text("1jgghgh".into())]);
|
||||
frame(&mut app, vec![egui::Event::Key { key: egui::Key::Tab, physical_key: None, pressed: true, repeat: false, modifiers: Default::default() }]);
|
||||
// The value remains the valid clamped minimum 4.0 pt, never 0.5 px, and rejection flash is set
|
||||
assert_eq!(app.ui.dialog.as_ref().unwrap().fields["maxRadius"], serde_json::json!(4.0));
|
||||
assert!(app.ui.dialog.as_ref().unwrap().fields["maxRadius"] == serde_json::json!(4.0));
|
||||
frame(
|
||||
&mut app,
|
||||
vec![egui::Event::Key { key: egui::Key::Enter, physical_key: None, pressed: true, repeat: false, modifiers: Default::default() }],
|
||||
);
|
||||
assert!(app.ui.dialog.is_some(), "dialog must remain open on invalid Enter commit");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -57,7 +57,8 @@ pub use numeric::{
|
||||
use numeric::{decimal_point, share_of, spinner_step, step_through, step_to_multiple, within_a_millionth};
|
||||
pub use panel_chrome::{bottom_bar, layout_button, list_box, orientation_button, tab_bar};
|
||||
pub(crate) use text::{
|
||||
arm_field_focus, dialog_focus_flag, disarm_field_focus, enter_modifiers, focus_field, own_field_shift_enter, set_dialog_open, take_dialog_focus,
|
||||
arm_field_focus, dialog_focus_flag, dialog_reject_commit_flag, disarm_field_focus, enter_modifiers, focus_field, own_field_shift_enter,
|
||||
reject_dialog_commit, set_dialog_open, take_dialog_focus,
|
||||
};
|
||||
pub use text::{
|
||||
exact_text_field, exact_text_field_named, plain_field, plain_field_named, search_field, text_field, text_field_named, text_presets,
|
||||
|
||||
@@ -117,8 +117,12 @@ fn unit_field(
|
||||
Some(clamped)
|
||||
}
|
||||
None => {
|
||||
ui.data_mut(|d| d.remove::<String>(id));
|
||||
ui.data_mut(|d| d.insert_temp(id.with("invalid-flash"), ui.input(|i| i.time + 0.25)));
|
||||
let end = ui.input(|i| i.time + 0.25);
|
||||
ui.data_mut(|d| {
|
||||
d.remove::<String>(id);
|
||||
d.insert_temp(id.with("invalid-flash"), end);
|
||||
});
|
||||
crate::widgets::reject_dialog_commit(ui.ctx());
|
||||
ui.ctx().request_repaint();
|
||||
None
|
||||
}
|
||||
|
||||
@@ -87,6 +87,16 @@ fn dialog_open_flag() -> egui::Id {
|
||||
egui::Id::unique("dialog-open")
|
||||
}
|
||||
|
||||
/// The flag that tells the dialog runner a field rejected an invalid commit on Enter in this frame.
|
||||
pub(crate) fn dialog_reject_commit_flag() -> egui::Id {
|
||||
egui::Id::unique("dialog-reject-commit")
|
||||
}
|
||||
|
||||
/// Suppress confirming an open dialog on Enter during this frame when an invalid value was committed.
|
||||
pub(crate) fn reject_dialog_commit(ctx: &egui::Context) {
|
||||
ctx.data_mut(|d| d.insert_temp(dialog_reject_commit_flag(), true));
|
||||
}
|
||||
|
||||
/// The app sets this at the start of each frame: while a dialog is open, Shift+Enter in a field
|
||||
/// applies its value and confirms the dialog as Enter does ([`shift_enter_keeps_focus`]).
|
||||
pub(crate) fn set_dialog_open(ctx: &egui::Context, open: bool) {
|
||||
@@ -279,7 +289,8 @@ pub(super) fn recessed_text(
|
||||
d.insert_temp(id, buf.clone());
|
||||
d.insert_temp(focus_id, focused);
|
||||
});
|
||||
let commit = resp.lost_focus() || kept;
|
||||
let enter_commit = rows == 1 && editing && ui.input(|i| i.key_pressed(egui::Key::Enter));
|
||||
let commit = resp.lost_focus() || kept || enter_commit;
|
||||
(buf, commit, resp, rect)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
**Feature evidence last updated:** 2026-10-22.
|
||||
**Feature evidence last updated:** 2026-10-30.
|
||||
|
||||
The shared assessment status line and revision history are current upstream; this dated section records the submission's feature evidence and revisions without rescoring upstream or claiming a new combined build or runtime measurement.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user