Window: Shift+Tab shows and hides the panels but leaves the toolbar and the Control bar

Shift+Tab ran Tab's command and hid the toolbar and the Control bar
along with the panels. egui matches a chord without Shift when Shift
is also held.

A new UI command, window.panels (default Shift+Tab), shows and hides
the dock and the floating panels and leaves the toolbar and the
Control bar as they are. The shortcut table tries chords with more
modifiers first, so Tab's chord no longer takes Shift+Tab. Hiding the
panels with Tab or Shift+Tab also closes a panel popped out of the
icon column, which stayed on screen at the window's right edge.

Docs: docs/target-app-parity.md.
This commit is contained in:
dotCooCoo
2026-10-16 02:25:56 +07:00
committed by bflatastic
parent 103c6ebdfb
commit b5a0fee1ea
18 changed files with 95 additions and 0 deletions
+1
View File
@@ -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…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2094,6 +2094,7 @@
Panel Options… パネルオプション…
Panel menu パネルメニュー
Panels パネル
Panels Except Tools and Control ツールとコントロール以外のパネル
Paragraph Style Options 段落スタイルオプション
Password パスワード
Paste Offset ペースト位置のオフセット
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2089,6 +2089,7 @@
Panel Options… 패널 옵션…
Panel menu 패널 메뉴
Panels 패널
Panels Except Tools and Control 도구와 컨트롤을 제외한 패널
Paragraph Style Options 단락 스타일 옵션
Password 암호
Paste Offset 붙여넣기 간격
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -2015,6 +2015,7 @@
Panel menu Меню панели
Panel Options… Параметры панели…
Panels Панели
Panels Except Tools and Control Панели, кроме инструментов и панели Control
Paragraph Абзац
Paragraph Style Стиль абзаца
Paragraph Style Options Параметры стиля абзаца
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2011,6 +2011,7 @@
Panel menu Меню панелі
Panel Options… Параметри панелі…
Panels Панелі
Panels Except Tools and Control Панелі, крім інструментів і панелі керування
Paragraph Абзац
Paragraph Style Стиль абзацу
Paragraph Style Options Параметри стилю абзацу
Can't render this file because it contains an unexpected character in line 713 and column 40.
+1
View File
@@ -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
1 # Vietnamese (vi) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
2268
2269
2270
2271
2272
2273
2274
+1
View File
@@ -1906,6 +1906,7 @@
Panel menu 面板菜单
Panel Options… 面板选项…
Panels 面板
Panels Except Tools and Control 除工具和控制栏外的面板
Paragraph 段落
Paragraph Style 段落样式
Paragraph Style Options 段落样式选项
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1996,6 +1996,7 @@
Panel menu 面板選單
Panel Options… 面板選項…
Panels 面板
Panels Except Tools and Control 除工具與控制以外的面板
Paragraph 段落
Paragraph Style 段落樣式
Paragraph Style Options 段落樣式選項
Can't render this file because it contains an unexpected character in line 6 and column 47.
+17
View File
@@ -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<R
app.ui.dock = on;
app.ui.toolbar = on;
app.ui.control_bar = on;
if !on {
app.ui.open_panel = None;
}
Ok(json!(on))
}
"window.panels" => {
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| {
+62
View File
@@ -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<egui::Event>| {
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());
+1
View File
@@ -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.