diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 474fa3ccb..9834a73f4 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -905,6 +905,7 @@ lighting Light Světlo Options for Selection… Možnosti výběru… Panel Options… Možnosti panelu… Panels Panely + Panels Except Tools and Control Panely kromě nástrojů a ovládacího panelu Perspective Plane Options… Možnosti perspektivní roviny… Placement Options… Možnosti umístění… Plug-in… Zásuvný modul… diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index d5c302260..840a5f1cc 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -1968,6 +1968,7 @@ Panel menu Bedienfeldmenü Panel Options… Bedienfeldoptionen… Panels Bedienfelder + Panels Except Tools and Control Bedienfelder außer Werkzeugen und Steuerung Paragraph Absatz Paragraph Style Absatzformat Paragraph Style Options Absatzformatoptionen diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 293100a33..eab75bf95 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -2017,6 +2017,7 @@ Panel menu Menú del panel Panel Options… Opciones del panel… Panels Paneles + Panels Except Tools and Control Paneles excepto Herramientas y Control Paragraph Párrafo Paragraph Style Estilo de párrafo Paragraph Style Options Opciones de estilo de párrafo diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index 7e68a6037..d0eb66c23 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -2014,6 +2014,7 @@ Panel menu Menu du panneau Panel Options… Options du panneau… Panels Panneaux + Panels Except Tools and Control Panneaux sauf Outils et Contrôle Paragraph Paragraphe Paragraph Style Style de paragraphe Paragraph Style Options Options de style de paragraphe diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 7f645bb46..2e2622acd 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -2475,6 +2475,7 @@ Panel menu Panelmenü Panel Options… Panel beállításai… Panels Panelek + Panels Except Tools and Control Panelek az Eszközök és a Vezérlősáv kivételével Paragraph Bekezdés Paragraph Style Bekezdésstílus Paragraph Style Options Bekezdésstílus beállításai diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 15f4435ac..d32558078 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -2019,6 +2019,7 @@ Panel menu Menu del pannello Panel Options… Opzioni pannello… Panels Pannelli + Panels Except Tools and Control Pannelli tranne Strumenti e Controllo Paragraph Paragrafo Paragraph Style Stile paragrafo Paragraph Style Options Opzioni stile paragrafo diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index 5d00929d7..60b0feee0 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -2094,6 +2094,7 @@ Panel Options… パネルオプション… Panel menu パネルメニュー Panels パネル + Panels Except Tools and Control ツールとコントロール以外のパネル Paragraph Style Options 段落スタイルオプション Password パスワード Paste Offset ペースト位置のオフセット diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index f26aff051..35e877f4d 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -2089,6 +2089,7 @@ Panel Options… 패널 옵션… Panel menu 패널 메뉴 Panels 패널 + Panels Except Tools and Control 도구와 컨트롤을 제외한 패널 Paragraph Style Options 단락 스타일 옵션 Password 암호 Paste Offset 붙여넣기 간격 diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index d64775cea..aa8178fe4 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -841,6 +841,7 @@ lighting Light Światło Options for Selection… Opcje zaznaczenia… Panel Options… Opcje panelu… Panels Panele + Panels Except Tools and Control Panele oprócz narzędzi i sterowania Perspective Plane Options… Opcje płaszczyzny perspektywy… Placement Options… Opcje umieszczania… Plug-in… Wtyczka… diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index 84adeccfb..0594bf829 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -1654,6 +1654,7 @@ Panel Options… Opções do Painel… Panel menu Menu do painel Panels Painéis + Panels Except Tools and Control Painéis exceto Ferramentas e Controle Paragraph Parágrafo Paragraph Style Options Opções de Estilo de Parágrafo Paragraph Styles Estilos de Parágrafo diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 3025bef20..c793256e8 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -2015,6 +2015,7 @@ Panel menu Меню панели Panel Options… Параметры панели… Panels Панели + Panels Except Tools and Control Панели, кроме инструментов и панели Control Paragraph Абзац Paragraph Style Стиль абзаца Paragraph Style Options Параметры стиля абзаца diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 004646b2a..a2c4a40ca 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -2011,6 +2011,7 @@ Panel menu Меню панелі Panel Options… Параметри панелі… Panels Панелі + Panels Except Tools and Control Панелі, крім інструментів і панелі керування Paragraph Абзац Paragraph Style Стиль абзацу Paragraph Style Options Параметри стилю абзацу diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index 871bfdbd4..a66ca0641 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -2268,6 +2268,7 @@ Panel menu Menu bảng Panel Options… Tùy chọn bảng… Panels Bảng + Panels Except Tools and Control Bảng trừ Công cụ và Điều khiển Paragraph Đoạn văn Paragraph Style Kiểu đoạn văn Paragraph Style Options Tùy chọn kiểu đoạn văn diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 192eec074..a845dfc8d 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -1906,6 +1906,7 @@ Panel menu 面板菜单 Panel Options… 面板选项… Panels 面板 + Panels Except Tools and Control 除工具和控制栏外的面板 Paragraph 段落 Paragraph Style 段落样式 Paragraph Style Options 段落样式选项 diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 4b7f71296..20f589c21 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -1996,6 +1996,7 @@ Panel menu 面板選單 Panel Options… 面板選項… Panels 面板 + Panels Except Tools and Control 除工具與控制以外的面板 Paragraph 段落 Paragraph Style 段落樣式 Paragraph Style Options 段落樣式選項 diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 3e33afe7c..f64c108ca 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -307,6 +307,12 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[ ), ("window.taskBar.reset", "Reset Bar Position", "", "{} unpin the Contextual Task Bar and put it back under the selection"), ("window.dock", "Panels", "Tab", "{} show/hide all panels"), + ( + "window.panels", + "Panels Except Tools and Control", + "Shift+Tab", + "{} show/hide the dock and the floating panels (hiding them closes a panel popped out of the icon column), leaving the toolbar and the Control bar as they are; returns whether the panels show", + ), ("window.panel", "Show Panel", "", "{panel: id} e.g. layers, swatches, stroke (case-insensitive; display labels like \"Layers\" work too)"), ( "window.panel.layout", @@ -1225,6 +1231,17 @@ pub fn run_ui_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option { + let on = !app.ui.dock; + app.ui.dock = on; + if !on { + app.ui.open_panel = None; + } Ok(json!(on)) } "window.collapseDock" => opt_bool(p, "collapsed").map(|collapsed| { diff --git a/crates/ui-egui/src/shortcuts.rs b/crates/ui-egui/src/shortcuts.rs index 9cd6de9a7..63fb11ce0 100644 --- a/crates/ui-egui/src/shortcuts.rs +++ b/crates/ui-egui/src/shortcuts.rs @@ -697,6 +697,68 @@ mod tests { assert_eq!(doc["layers"][0]["children"][0]["name"], "a\tb"); } + /// Shift+Tab shows and hides the panels and leaves the toolbar and the Control bar as they are, + /// while Tab hides all three. Hiding the panels closes a panel popped out of the icon column. + /// In a focused field neither key shows or hides anything. + #[test] + fn shift_tab_hides_the_panels_but_not_the_toolbar_or_the_control_bar() { + let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default()); + app.session.execute("file.new", &json!({"width": 200, "height": 200})).unwrap(); + let ctx = egui::Context::default(); + let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1600.0, 850.0)); + let run = |app: &mut VectorcraftApp, events: Vec| { + let mut out = ctx.run_ui(egui::RawInput { events, screen_rect: Some(screen), ..Default::default() }, |ui| { + app.logic(ui.ctx()); + app.ui(ui); + }); + out.textures_delta.clear(); + }; + let press = |modifiers| egui::Event::Key { key: Key::Tab, physical_key: None, pressed: true, repeat: false, modifiers }; + let shown = |app: &VectorcraftApp| (app.ui.dock, app.ui.toolbar, app.ui.control_bar); + app.ui.control_bar = true; + for _ in 0..3 { + run(&mut app, vec![]); + } + assert_eq!(shown(&app), (true, true, true)); + app.run("window.panel", json!({"panel": "color"})).unwrap(); + run(&mut app, vec![press(Modifiers::SHIFT)]); + run(&mut app, vec![]); + assert_eq!(shown(&app), (false, true, true), "Shift+Tab hid the panels only"); + assert_eq!(app.ui.open_panel, None, "and the panel popped out of the icon column"); + run(&mut app, vec![press(Modifiers::SHIFT)]); + run(&mut app, vec![]); + assert_eq!(shown(&app), (true, true, true), "a second Shift+Tab shows them again"); + app.run("window.panel", json!({"panel": "color"})).unwrap(); + run(&mut app, vec![press(Modifiers::NONE)]); + run(&mut app, vec![]); + assert_eq!(shown(&app), (false, false, false), "Tab hides the toolbar and the Control bar too"); + assert_eq!(app.ui.open_panel, None); + run(&mut app, vec![press(Modifiers::NONE)]); + run(&mut app, vec![]); + assert_eq!(shown(&app), (true, true, true)); + // A field of the Color panel has the keyboard focus: Shift+Tab and Tab do not show or hide anything. + app.run("window.panel", json!({"panel": "color"})).unwrap(); + for _ in 0..3 { + run(&mut app, vec![]); + } + let fields: Vec<(egui::Id, egui::Rect)> = ctx.viewport(|vp| { + vp.prev_pass.widgets.layers().flat_map(|(_, w)| w.iter()).filter(|w| w.sense.senses_click()).map(|w| (w.id, w.rect)).collect() + }); + let (id, rect) = + fields.into_iter().find(|&(id, _)| egui::TextEdit::load_state(&ctx, id).is_some()).unwrap_or_else(|| panic!("no field on screen")); + let click = + |pressed| egui::Event::PointerButton { pos: rect.center(), button: egui::PointerButton::Primary, pressed, modifiers: Modifiers::NONE }; + run(&mut app, vec![egui::Event::PointerMoved(rect.center()), click(true)]); + run(&mut app, vec![click(false)]); + assert!(ctx.memory(|m| m.has_focus(id)), "the field has the keyboard"); + for modifiers in [Modifiers::SHIFT, Modifiers::NONE] { + run(&mut app, vec![press(modifiers)]); + run(&mut app, vec![]); + assert_eq!(shown(&app), (true, true, true), "{modifiers:?}"); + assert_eq!(app.ui.open_panel.as_deref(), Some("color"), "{modifiers:?}"); + } + } + #[test] fn copy_and_paste_events_use_the_system_clipboard() { let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default()); diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index b3c12b0a8..c0ab119f7 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -431,6 +431,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - The Control bar's underlined Transform link opens the Transform panel in a popover under it (reference point, X/Y/W/H, Rotate and Shear with their icons and angle presets, flips, shape properties, Scale Corners and Scale Strokes & Effects), as its Stroke link does the Stroke panel; X/Y/W/H also show inline while the bar has room. The reference point locator is nine squares, the outer eight joined around the box. - In isolation mode the Control bar has an Exit Isolation Mode button (`object.exitIsolation`), except while a pattern is edited. Outside isolation mode, with one group, compound path, path, image, mesh or placed file selected, it has an Isolate Selected Object button (`object.isolate`), which also isolates a path inside a group that Direct Selection selected. - Tab shows and hides the panels (in the Type tool it types a tab) without moving the keyboard focus onto a field, so the next shortcut or letter still works; in dialogs and panel fields it moves between fields. + - Shift+Tab (`window.panels`) shows and hides the dock and the floating panels and leaves the toolbar and the Control bar as they are; hiding the panels with Tab or Shift+Tab also closes a panel popped out of the icon column. - Cmd/Ctrl+A follows the keyboard: in a panel, dialog or search field it selects the field's text, while the Type tool edits it selects all of that text (also `select.all` over MCP), and only otherwise every object. On macOS the menu bar's Select All, Cut, Copy and Paste (keys or clicks) act on a focused field too, and elsewhere the in-window menus' do: the field that had the keyboard when the menu opened gets them, with its selection, and the keyboard back (#516). Not yet: Select All across threaded frames (one frame's text is selected). - Shortcut sets other apps save as text (`.kys`) open in Import Shortcut Set from File › Open, from Edit › Keyboard Shortcuts › Import… in the desktop app, or from a drop on the window. It matches each entry to a tool, command or panel by name and decodes the file's key and modifier codes where VectorCraft's default shortcuts agree on them; the user answers the rest, and Apply fills the Keyboard Shortcuts dialog's working set. The answers are kept with the preferences for the next import (`shortcutSet.read`, `importMatches.*`). - On Windows and Linux the app bar is the window's title bar (its own minimize, maximize and close buttons, drag to move, edges to resize), with the dragon app icon as the brand mark; dialogs and menus size to their content. As on a native menu bar, once one menu is open, moving the pointer onto another title opens that one.