mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-07 23:00:15 +00:00
M1: keep sidebar field text in place on focus
This commit is contained in:
+2
-1
File diff suppressed because one or more lines are too long
@@ -1153,3 +1153,44 @@ fn prepared_save_cannot_enter_a_replacement(route: &str, save_as: bool, discard:
|
||||
assert!(u.app.ui.after_field.is_none());
|
||||
std::fs::remove_dir_all(&dir).ok();
|
||||
}
|
||||
|
||||
/// Replacing a painted value with its editor must preserve its baseline, including inside
|
||||
/// the horizontal rows used by the sidebar.
|
||||
#[test]
|
||||
fn sidebar_field_text_stays_in_place_on_focus() {
|
||||
for numeric in [true, false] {
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::apply(&ctx, crate::theme::Tokens::light());
|
||||
let id = Id::unique("baseline_field");
|
||||
let draw = |events| {
|
||||
let mut out = ctx.run_ui(
|
||||
egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(Pos2::ZERO, egui::vec2(400.0, 200.0))), events, ..Default::default() },
|
||||
|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if numeric {
|
||||
crate::widgets::number_field(ui, id, crate::widgets::Lead::None, Some(123.0), "", 100.0, 1.0);
|
||||
} else {
|
||||
crate::widgets::text_field(ui, id, "123", 100.0, "");
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
out.textures_delta.clear();
|
||||
out
|
||||
};
|
||||
draw(vec![]);
|
||||
let before = draw(vec![]);
|
||||
let bounds = |out: &egui::FullOutput| painted_texts(&out.shapes).into_iter().find(|(text, _, _)| text == "123").expect("field text").2;
|
||||
let before = bounds(&before);
|
||||
let p = before.center();
|
||||
for pressed in [true, false] {
|
||||
draw(vec![
|
||||
Event::PointerMoved(p),
|
||||
Event::PointerButton { pos: p, button: egui::PointerButton::Primary, pressed, modifiers: Modifiers::NONE },
|
||||
]);
|
||||
}
|
||||
assert!(ctx.memory(|m| m.has_focus(id.with("te"))), "editor is focused");
|
||||
let after = bounds(&draw(vec![]));
|
||||
assert!((before.center().y - after.center().y).abs() <= 0.5, "numeric={numeric}: before={before:?}, after={after:?}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,12 +112,13 @@ fn lead_field(ui: &mut Ui, id: Id, glyph: LeadGlyph, value: &str, width: f32, ti
|
||||
let mut out = None;
|
||||
match editing {
|
||||
Some(mut text) => {
|
||||
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(text_rect.shrink2(vec2(2.0, 4.0))));
|
||||
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(text_rect.shrink2(vec2(2.0, 0.0))));
|
||||
let r = child.add(
|
||||
egui::TextEdit::singleline(&mut text)
|
||||
.id(id.with("te"))
|
||||
.frame(egui::Frame::NONE)
|
||||
.font(regular(11.0))
|
||||
.align(Align2::LEFT_CENTER)
|
||||
.desired_width(text_rect.width() - 6.0),
|
||||
);
|
||||
crate::a11y::own_focus(&r);
|
||||
|
||||
@@ -361,7 +361,9 @@ fn number_field_impl(
|
||||
.font(regular(11.0))
|
||||
.desired_width(edit_rect.width() - 6.0)
|
||||
.align(egui::Align2::LEFT_CENTER);
|
||||
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(edit_rect.shrink2(vec2(0.0, 4.0))));
|
||||
// TextEdit already reserves the theme's 24 pt interaction height. Insetting its
|
||||
// top would move its baseline below the centered value painted while idle.
|
||||
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(edit_rect));
|
||||
let r = child.add(te);
|
||||
a11y::own_focus(&r);
|
||||
keep_focus(&r, started);
|
||||
@@ -628,12 +630,13 @@ fn text_field_in(ui: &mut Ui, id: Id, value: &str, rect: Rect, placeholder: &str
|
||||
/// its own (the field draws it), showing `hint` while empty; `password` shows dots.
|
||||
fn field_editor(ui: &mut Ui, rect: Rect, id: Id, text: &mut String, hint: &str, password: bool) -> Response {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(rect.shrink2(vec2(8.0, 4.0))));
|
||||
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(rect.shrink2(vec2(8.0, 0.0))));
|
||||
let r = child.add(
|
||||
egui::TextEdit::singleline(text)
|
||||
.id(id)
|
||||
.frame(egui::Frame::NONE)
|
||||
.password(password)
|
||||
.align(Align2::LEFT_CENTER)
|
||||
.font(regular(11.0))
|
||||
.hint_text(egui::RichText::new(hint).font(regular(11.0)).color(t.text_tertiary))
|
||||
.desired_width(rect.width() - 16.0),
|
||||
|
||||
+3
-2
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user