Window menu: show check marks next to visible panels

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
pravdomilandClaude Opus 5.5 committed 2026-10-11 17:25:58 +02:00
1 parent 9a7d3e7699
commit 41c92d3856
2 files changed
+38

No files matched your search

+14
View File
@@ -1361,6 +1361,18 @@ pub(crate) fn entry_shortcut(app: &EffectcraftApp, e: &MenuEntry) -> Option<Stri
app.session.shortcuts().shortcut_of(&e.command, &e.params).map(str::to_string)
}
/// Whether panel `p` is on screen: the front tab of a floating window, or of a docked group
/// (an open frame in a stack) that a maximized panel does not cover.
pub(crate) fn panel_shown(app: &EffectcraftApp, p: PanelKind) -> bool {
if app.ui.floating.iter().any(|f| f.panels.get(f.active) == Some(&p)) {
return true;
}
match app.ui.maximized.filter(|m| app.ui.dock.contains(*m)) {
Some(m) => m == p,
None => app.ui.dock.is_visible(p),
}
}
/// Check-mark state of frontend toggles (engine state is answered by the engine).
pub(crate) fn entry_checked(app: &EffectcraftApp, e: &MenuEntry) -> Option<bool> {
let v = &app.ui.viewer;
@@ -1379,6 +1391,8 @@ pub(crate) fn entry_checked(app: &EffectcraftApp, e: &MenuEntry) -> Option<bool>
Some(v.res.label().eq_ignore_ascii_case(e.command.trim_start_matches("view.res.")))
}
"window.workspace" => Some(pstr("name").is_some_and(|n| n == app.ui.workspace)),
// The Tools panel is the header toolbar: always on screen.
"window.panel" => Some(pstr("panel").is_some_and(|n| n.eq_ignore_ascii_case("tools") || PanelKind::from_name(n).is_some_and(|p| panel_shown(app, p)))),
"view.panelBackground" if e.params.get("pick").is_none() => {
let cur = match v.pasteboard {
None => "mediumGray",
+24
View File
@@ -316,6 +316,8 @@ pub fn state_key(app: &EffectcraftApp) -> u64 {
(v.rulers, v.guides, v.snap_guides, v.lock_guides, v.grid, v.snap_grid, v.show_layer_controls, v.pasteboard).hash(&mut h);
v.res.label().hash(&mut h);
(app.ui.cache_when_idle, app.session.prefs.preview.active().include_audio, &app.ui.workspace, app.dialog.is_some()).hash(&mut h);
// Window menu check marks: the panels on screen.
crate::dock::PanelKind::ALL.iter().filter(|p| crate::menus::panel_shown(app, **p)).for_each(|p| p.hash(&mut h));
h.finish()
}
@@ -495,6 +497,28 @@ mod tests {
}
}
/// Window menu entries are checked while their panel is on screen.
#[test]
fn window_menu_checks_the_panels_on_screen() {
use crate::dock::PanelKind;
let mut app = app();
let checked = |app: &EffectcraftApp, panel: &str| {
build(app).items().into_iter().find(|i| i.command == "window.panel" && i.params["panel"] == panel).and_then(|i| i.checked)
};
assert_eq!(checked(&app, "timeline"), Some(true));
assert_eq!(checked(&app, "tools"), Some(true));
assert_eq!(checked(&app, "renderQueue"), Some(false));
let k0 = state_key(&app);
app.show_panel(PanelKind::RenderQueue);
assert_ne!(state_key(&app), k0);
// A tab behind another one, a closed panel and panels under a maximized one are not shown.
assert_eq!((checked(&app, "renderQueue"), checked(&app, "timeline")), (Some(true), Some(false)));
app.ui.dock.close(PanelKind::RenderQueue);
assert_eq!((checked(&app, "renderQueue"), checked(&app, "timeline")), (Some(false), Some(true)));
app.ui.maximized = Some(PanelKind::Timeline);
assert_eq!((checked(&app, "timeline"), checked(&app, "project")), (Some(true), Some(false)));
}
#[test]
fn state_changes_flow_into_the_spec() {
let mut app = app();