mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-02 08:43:57 +00:00
keymap: report Changed after a Cancel that undid edits, so apps rebuild their menus
This commit is contained in:
1 parent
2abdcd53ab
commit
0039a5c866
4 files changed
+32
-7
No files matched your search
@@ -306,6 +306,7 @@ if let Some(state) = &mut self.shortcuts {
|
||||
let dialog = dialog.sets(&mut self.settings.shortcut_sets, &BUILTINS);
|
||||
match dialog.show(ctx, state) {
|
||||
Some(Outcome::Ok) => self.save_settings(),
|
||||
// After each edit, and after a Cancel that undid edits.
|
||||
Some(Outcome::Changed) => self.rebuild_menus(),
|
||||
Some(Outcome::Import { formats }) => self.pick_import_file(formats),
|
||||
Some(Outcome::Export { name, json }) => self.save_file(&name, json),
|
||||
@@ -324,8 +325,8 @@ Outcomes:
|
||||
| Outcome | The app |
|
||||
|---|---|
|
||||
| `Ok` | Saves `Profiles` (with sets) or `keymap.overrides()`. |
|
||||
| `Cancel` | Nothing to do: the keymap and the sets are as they were at open. |
|
||||
| `Changed` | Updates its menus, or saves at once if it saves live. When a frame also has another outcome, `Changed` comes on the next frame. |
|
||||
| `Cancel` | Nothing to save: the keymap and the sets are as they were at open. When Cancel undid edits, `Changed` follows. |
|
||||
| `Changed` | Updates its menus, or saves at once if it saves live. It comes after each edit and after a Cancel that undid edits. When a frame also has another outcome, `Changed` comes on the next frame; `is_open()` stays true until it has. |
|
||||
| `Import { formats }` | Opens a file of one of the formats, then calls `import_json` (craft-keymap JSON, `ui::JSON_FORMAT`) or reads it into a `ForeignSet` and calls `review_import`. |
|
||||
| `Export { name, json }`, `ExportAs { format, name, keymap }` | Writes the set where the user chooses (a download on the web). |
|
||||
| `Summary { name, html, text }` | Shows, saves or prints the summary. |
|
||||
|
||||
@@ -34,7 +34,8 @@ use state::Env;
|
||||
pub enum Outcome {
|
||||
/// Closed with OK: save `Profiles` (with sets) or `keymap.overrides()`.
|
||||
Ok,
|
||||
/// Closed with Cancel: the keymap and profiles are back as they were when it opened.
|
||||
/// Closed with Cancel: the keymap and profiles are back as they were when it opened. When that
|
||||
/// undid edits, `Changed` follows on the next frame.
|
||||
Cancel,
|
||||
/// An edit (for live menus and live saving). When a frame also has another outcome, such as
|
||||
/// `Import` after the Save changes prompt, `Changed` follows on the next frame.
|
||||
@@ -203,6 +204,9 @@ impl<'a> ShortcutsDialog<'a> {
|
||||
/// screen allows, at most 1320×900). Closing it with × is Cancel.
|
||||
pub fn show(self, ctx: &egui::Context, state: &mut DialogState) -> Option<Outcome> {
|
||||
self.with_env(|env| {
|
||||
if !state.is_showing() {
|
||||
return state.finish();
|
||||
}
|
||||
let title = env.text.visual(&env.text.ui(env.options.title));
|
||||
let screen = ctx.content_rect().size();
|
||||
let max = egui::vec2(1320.0, 900.0).min(screen - egui::vec2(16.0, 16.0)).max(egui::vec2(240.0, 180.0));
|
||||
@@ -218,10 +222,13 @@ impl<'a> ShortcutsDialog<'a> {
|
||||
.min_size(min)
|
||||
.max_size(max)
|
||||
.show(ctx, |ui| out = frame(ui, env, state));
|
||||
if !open && state.is_open() {
|
||||
if !open && state.is_showing() {
|
||||
state.cancel(env);
|
||||
out = state.finish();
|
||||
}
|
||||
if state.change_pending() {
|
||||
ctx.request_repaint();
|
||||
}
|
||||
out
|
||||
})
|
||||
}
|
||||
@@ -272,7 +279,7 @@ impl<'a> ShortcutsDialog<'a> {
|
||||
fn frame(ui: &mut egui::Ui, env: &mut Env, state: &mut DialogState) -> Option<Outcome> {
|
||||
state.begin(env);
|
||||
state.input(env, ui.ctx());
|
||||
if state.is_open() {
|
||||
if state.is_showing() {
|
||||
view::body(ui, env, state);
|
||||
}
|
||||
let out = state.finish();
|
||||
|
||||
@@ -264,8 +264,15 @@ impl DialogState {
|
||||
}
|
||||
}
|
||||
|
||||
/// False after OK or Cancel: drop the state.
|
||||
/// False once the dialog has closed with OK or Cancel and reported its last outcome: drop the
|
||||
/// state then. After a Cancel that undid edits it stays true for the frame that reports
|
||||
/// [`Outcome::Changed`].
|
||||
pub fn is_open(&self) -> bool {
|
||||
self.phase != Phase::Closed || self.changed
|
||||
}
|
||||
|
||||
/// Whether the dialog is drawn: not yet closed with OK or Cancel.
|
||||
pub(crate) fn is_showing(&self) -> bool {
|
||||
self.phase != Phase::Closed
|
||||
}
|
||||
|
||||
@@ -698,14 +705,20 @@ impl DialogState {
|
||||
}
|
||||
|
||||
/// Cancel, window ×, or Escape when idle: everything back as it was when the dialog opened.
|
||||
/// When that undoes edits, Changed follows, so the app rebuilds its menus (and saves, if it
|
||||
/// saved the edits live).
|
||||
pub(crate) fn cancel(&mut self, env: &mut Env) {
|
||||
let mut undone = false;
|
||||
if let Some(opened) = self.opened.take() {
|
||||
undone = *env.keymap.overrides() != opened.overrides;
|
||||
env.keymap.set_overrides(opened.overrides);
|
||||
if let (Some((p, _)), Some(profiles)) = (env.sets.as_mut(), opened.profiles) {
|
||||
undone |= **p != profiles;
|
||||
**p = profiles;
|
||||
}
|
||||
}
|
||||
self.close(Outcome::Cancel);
|
||||
self.changed = undone;
|
||||
}
|
||||
|
||||
fn close(&mut self, outcome: Outcome) {
|
||||
@@ -1167,8 +1180,9 @@ mod tests {
|
||||
assert!(matches!(st.finish(), Some(Outcome::Changed)));
|
||||
st.escape(&mut fx.env());
|
||||
assert!(matches!(st.finish(), Some(Outcome::Cancel)));
|
||||
assert!(!st.is_open());
|
||||
assert!(fx.keys("object.front").is_empty(), "Cancel restores the opening keymap");
|
||||
assert!(st.is_open() && matches!(st.finish(), Some(Outcome::Changed)), "Changed follows, for the app's menus");
|
||||
assert!(!st.is_open());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -497,6 +497,9 @@ fn window_close_is_cancel() {
|
||||
click(&mut h, "Cancel");
|
||||
assert!(h.state().canceled());
|
||||
assert_eq!(h.state().bindings("file.save"), ["Cmd+S"]);
|
||||
let after: Vec<bool> = h.state().outcomes.iter().skip_while(|o| !matches!(o, Outcome::Cancel)).map(|o| matches!(o, Outcome::Changed)).collect();
|
||||
assert_eq!(after, [false, true], "Changed follows Cancel, which undid an edit");
|
||||
assert!(!h.state().state.is_open());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user