Review: System Title Bar only where it applies, docs, title repaint
- Preferences hides System Title Bar on macOS and the web, where it did nothing (it fell through to the plain checkbox row), and lists it with the window options instead of under Language. - The next-launch note reuses "Applies the next time VectorCraft starts." instead of a second wording in every catalog. - A new window title asks for one more frame: AppKit lays the title bar out again for it, and the next frame centres the window buttons (#968). - The menu bar drops the bold branch for the VectorCraft menu it no longer shows; theme is imported where the tests use it. - Docs: Language is Preferences › User Interface › Language (VectorCraft › Language on macOS); the control protocol describes System Title Bar; ROADMAP Last updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2e643b0e76
commit
6315086f96
File diff suppressed because one or more lines are too long
|
|
@ -630,10 +630,8 @@ fn main() -> std::process::ExitCode {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn ui_state_with_prefs(prefs: serde_json::Value) -> vectorcraft_ui_egui::UiState {
|
||||
let mut ui = vectorcraft_ui_egui::UiState::default();
|
||||
ui.engine_prefs = prefs;
|
||||
ui
|
||||
fn ui_state_with_prefs(engine_prefs: serde_json::Value) -> vectorcraft_ui_egui::UiState {
|
||||
vectorcraft_ui_egui::UiState { engine_prefs, ..Default::default() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -278,11 +278,11 @@ pub const PREF_SPECS: &[PrefSpec] = &[
|
|||
p!("toolGroupLabels", "User Interface", "", "Show Tool Group Labels", bool),
|
||||
p!("openDocumentsAsTabs", "User Interface", "", "Open Documents As Tabs", bool),
|
||||
p!("largeTabs", "User Interface", "", "Large Tabs", bool),
|
||||
p!("systemTitleBar", "User Interface", "", "System Title Bar", bool),
|
||||
p!("uiScaling", "User Interface", "UI Scaling", "Scale", num(0.75, 2.0, "×")),
|
||||
p!("scaleCursorWithUi", "User Interface", "UI Scaling", "Scale Cursor Proportional to UI", bool),
|
||||
// `auto` or a language code the shell registers (`zh-hant`); the shell shows it as a dropdown.
|
||||
p!("interfaceLanguage", "User Interface", "Language", "Language", text),
|
||||
p!("systemTitleBar", "User Interface", "", "System Title Bar", bool),
|
||||
// Performance
|
||||
p!("gpuPerformance", "Performance", "GPU Performance", "GPU Performance", bool),
|
||||
p!("animatedZoom", "Performance", "GPU Performance", "Animated Zoom", bool),
|
||||
|
|
|
|||
|
|
@ -130,6 +130,9 @@ pub fn sync_window_title(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
|||
if app.last_window_title != want {
|
||||
app.last_window_title = want.clone();
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Title(want));
|
||||
// One more frame: a new title makes AppKit lay its title bar out again, putting the window
|
||||
// buttons back where it keeps them until the next frame centres them on the bar (#968).
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -673,5 +673,4 @@
|
|||
Stained Glass… Vitráž…
|
||||
Texturizer… Texturovač…
|
||||
System Title Bar Systémové záhlaví okna
|
||||
Applies at next launch. Projeví se při příštím spuštění.
|
||||
Exit Ukončit
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3976,4 +3976,3 @@ axis Both Ambos
|
|||
Bottom Right Abajo a la derecha
|
||||
Edge Borde
|
||||
System Title Bar Barra de título del sistema
|
||||
Applies at next launch. Se aplicará en el próximo inicio.
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3988,4 +3988,3 @@ axis Both Les deux
|
|||
effect Soft Doux
|
||||
Edge Bord
|
||||
System Title Bar Barre de titre du système
|
||||
Applies at next launch. Prend effet au prochain démarrage.
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3978,4 +3978,3 @@ effect Soft Morbido
|
|||
effect Regular Normale
|
||||
Edge Bordo
|
||||
System Title Bar Barra del titolo di sistema
|
||||
Applies at next launch. Si applica al prossimo avvio.
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3971,4 +3971,3 @@ effect Horizontal 水平
|
|||
effect Vertical 垂直
|
||||
Edge エッジ
|
||||
System Title Bar システムのタイトルバー
|
||||
Applies at next launch. 次回の起動時に適用されます。
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -2733,5 +2733,4 @@
|
|||
Stained Glass… Vitral…
|
||||
Texturizer… Texturizador…
|
||||
System Title Bar Barra de título do sistema
|
||||
Applies at next launch. Aplica-se na próxima inicialização.
|
||||
Exit Sair
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -3974,4 +3974,3 @@ axis Both Оба
|
|||
Bottom Right Снизу справа
|
||||
Edge Край
|
||||
System Title Bar Системная строка заголовка
|
||||
Applies at next launch. Применится при следующем запуске.
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3959,4 +3959,3 @@ axis Both Обидві
|
|||
Bottom Right Знизу праворуч
|
||||
Edge Край
|
||||
System Title Bar Системний рядок заголовка
|
||||
Applies at next launch. Набуде чинності після перезапуску.
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 13.
|
|
|
@ -3607,4 +3607,3 @@ effect Horizontal 水平
|
|||
effect Vertical 垂直
|
||||
Edge 边缘
|
||||
System Title Bar 系统标题栏
|
||||
Applies at next launch. 下次启动时生效。
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3388,4 +3388,3 @@ axis Both 兩者
|
|||
effect Soft 柔和
|
||||
Edge 邊緣
|
||||
System Title Bar 系統標題列
|
||||
Applies at next launch. 下次啟動時套用。
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -13,7 +13,7 @@ use crate::VectorcraftApp;
|
|||
use crate::io;
|
||||
use crate::panels::character::Face;
|
||||
use crate::state::{DockTab, next_zoom};
|
||||
use crate::theme::{self, Brightness, Tokens};
|
||||
use crate::theme::{Brightness, Tokens};
|
||||
use crate::widgets;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -2754,11 +2754,7 @@ pub fn menu_bar(app: &mut VectorcraftApp, ui: &mut egui::Ui) -> f32 {
|
|||
.ui(ui, |ui| {
|
||||
let mut titles = Vec::with_capacity(tree.len());
|
||||
for (title, items) in tree.iter() {
|
||||
let text = if *title == "VectorCraft" {
|
||||
egui::RichText::new(tl!(title)).font(theme::semibold(13.0)).color(t.text)
|
||||
} else {
|
||||
egui::RichText::new(tl!(title)).size(13.0).color(t.text)
|
||||
};
|
||||
let text = egui::RichText::new(tl!(title)).size(13.0).color(t.text);
|
||||
titles.push(ui.menu_button(text, |ui| menu_body(app, ui, items, &mut clicked)).response);
|
||||
}
|
||||
(ui.cursor().min.x, switch_on_hover(ui.ctx(), &titles))
|
||||
|
|
@ -3520,6 +3516,7 @@ pub fn menu_strings() -> std::collections::BTreeSet<String> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::theme;
|
||||
|
||||
/// One headless frame of the in-window menu bar; returns its titles (left to right) as
|
||||
/// (rect, id of the title's popup).
|
||||
|
|
|
|||
|
|
@ -261,10 +261,13 @@ fn category_fields(ui: &mut egui::Ui, d: &mut Dialog, cat: &str) {
|
|||
PrefKind::Bool if sp.key == "animatedZoom" => {
|
||||
ui.add_enabled_ui(d.bool("gpuPerformance"), |ui| bool_row(ui, d, sp.key, sp.label));
|
||||
}
|
||||
PrefKind::Bool if sp.key == "systemTitleBar" && cfg!(all(not(target_arch = "wasm32"), not(target_os = "macos"))) => {
|
||||
bool_row(ui, d, sp.key, sp.label);
|
||||
// The window's decorations are chosen once, when the app starts.
|
||||
ui.label(egui::RichText::new(tl!("Applies at next launch.")).color(t.text_dim).size(11.0));
|
||||
// Windows and Linux only: macOS always has the system's title bar, the web has none.
|
||||
PrefKind::Bool if sp.key == "systemTitleBar" => {
|
||||
if cfg!(all(not(target_arch = "wasm32"), not(target_os = "macos"))) {
|
||||
bool_row(ui, d, sp.key, sp.label);
|
||||
// The window's decorations are chosen once, when the app starts.
|
||||
ui.label(egui::RichText::new(tl!("Applies the next time VectorCraft starts.")).color(t.text_dim).size(11.0));
|
||||
}
|
||||
}
|
||||
PrefKind::Bool => bool_row(ui, d, sp.key, sp.label),
|
||||
PrefKind::Num { min, max, unit } => {
|
||||
|
|
@ -558,7 +561,7 @@ mod tests {
|
|||
let mut shown = vec![];
|
||||
out.shapes.iter().for_each(|c| texts(&c.shape, &mut shown));
|
||||
assert!(shown.iter().any(|t| t == "System Title Bar"), "{shown:?}");
|
||||
assert!(shown.iter().any(|t| t == "Applies at next launch."), "{shown:?}");
|
||||
assert!(shown.iter().any(|t| t == "Applies the next time VectorCraft starts."), "{shown:?}");
|
||||
a.ui.dialog.as_mut().unwrap().fields.insert("systemTitleBar".into(), json!(true));
|
||||
confirm(&mut a).unwrap();
|
||||
assert!(a.session.prefs.system_title_bar);
|
||||
|
|
|
|||
|
|
@ -208,8 +208,10 @@ Tile Edge Color: Object → Pattern → Tile Edge Color… (`ui.tileEdgeColor`)
|
|||
Window title bar: on Windows and Linux the window has no OS decorations and the app bar is the title bar. Its
|
||||
caption buttons (Minimize, Maximize/Restore, Close) sit at the bar's right end, 46 pt each; they are window chrome,
|
||||
not commands, so drive them with `ui.click` if needed. Close runs `app.quit` (the same `saveChanges` questions for
|
||||
modified documents), and empty bar space and the 5 pt window edges move and resize the window. macOS and the web
|
||||
build are unchanged.
|
||||
modified documents), and empty bar space and the 5 pt window edges move and resize the window. Preferences › User
|
||||
Interface › System Title Bar (`systemTitleBar`, read when the app starts) gives the window its OS decorations back
|
||||
instead: the OS title then shows the active document (`*name — VectorCraft` with unsaved changes) and the app bar
|
||||
drops its brand mark. On macOS the window buttons are centred on the app bar; the web build is unchanged.
|
||||
|
||||
Fill/Stroke chips and panel shortcuts: the Control bar's and Properties' Fill and Stroke chips bring their proxy
|
||||
forward (`paint.toggleActive {fill}`) and open a popover with the Swatches panel (Shift-click: the Color panel's mixer);
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ By default VectorCraft's own crates log at `info` and everything else at `warn`.
|
|||
|
||||
## macOS: the menu bar
|
||||
|
||||
On macOS the menus live in the system menu bar, not in the window's app bar (which keeps the brand mark, Home, the search box and the workspace switcher next to the traffic lights). `--in-window-menus` or `VECTORCRAFT_IN_WINDOW_MENUS=1` keeps them in the window, as on Windows, Linux and the web; so does a menu bar AppKit refuses to build (logged). `ui.inspect` says which with `nativeMenuBar`.
|
||||
On macOS the menus live in the system menu bar, not in the window's app bar (which keeps the brand mark, Home, the search icon and the workspace switcher next to the traffic lights, centred on the bar by `apps/vectorcraft/src/mac_window.rs`). `--in-window-menus` or `VECTORCRAFT_IN_WINDOW_MENUS=1` keeps them in the window, as on Windows, Linux and the web; so does a menu bar AppKit refuses to build (logged). `ui.inspect` says which with `nativeMenuBar`.
|
||||
|
||||
- **One menu model.** `crates/ui-egui/src/native_menu.rs` (platform-free, tested on every platform) builds the menu bar from the in-window menus (`menus::menu_tree`, each item through `menus::entry`, which the in-window menus draw too) and lays it out the Mac way: the VectorCraft menu holds About, Settings ▸ (one item per Preferences page, General… ⌘K), Language ▸, Appearance ▸ (UI brightness), Services, Hide VectorCraft ⌃⌘H (⌘H stays View › Hide Edges), Hide Others ⌥⌘H, Show All and Quit ⌘Q (the app's own `app.quit`, so unsaved documents are asked about); those leave Edit and Help. The in-window bar itself never shows the VectorCraft menu (it starts at File, as in Illustrator, on every platform): Language and Appearance have no in-window menu and are synthesized in `mac_layout`, and Quit is File › Exit in the window, relabelled to Quit in the App menu. Window starts with Minimize ⌃⌘M and Zoom and ends with Bring All to Front, and Help is the system's Help menu (its search field). A system key a command (or a user's shortcut) already has stays the command's, and the log says so.
|
||||
- **The native side** is `apps/vectorcraft/src/mac_menu.rs`: muda (`=0.21.1`, default features off, macOS only, no `unsafe`) builds the `NSMenu`s. Labels, enabled and checked are updated in place when anything they show may have changed (a command ran, the document, its history or selection changed, a click or a key press); a change of structure (a recent file, the language, a shortcut) rebuilds the menus.
|
||||
|
|
@ -182,8 +182,8 @@ locale such as `ru-RU`, `ru-BY` or `ru-KZ` resolves to it), Ukrainian (`uk`, com
|
|||
- The shared widgets (`widgets::check`, `dropdown`, `menu_item`, the buttons, `label_row`, tooltips of
|
||||
`icon_button`…), the menus, the dock, the toolbar, the dialog frame and `panels::empty_state` translate
|
||||
the text they are given, so a panel mostly needs its literals wrapped in `tl!` to be covered by the tests.
|
||||
- The language is VectorCraft › Language (the `app.language` UI command, `{lang: auto|<code>}`) or Edit ›
|
||||
Preferences › User Interface › Language; both set the `interfaceLanguage` preference (`auto` or a language
|
||||
- The language is Edit › Preferences › User Interface › Language or, on macOS, VectorCraft › Language (the
|
||||
`app.language` UI command, `{lang: auto|<code>}`); both set the `interfaceLanguage` preference (`auto` or a language
|
||||
code; `auto` follows the system locale: `VECTORCRAFT_LOCALE`, then `LC_ALL`/`LC_MESSAGES`/`LANG`/`LANGUAGE`,
|
||||
the macOS preferred languages, the Windows user locale; on the web, `?lang=<code>` in the address, then
|
||||
the browser's `navigator.languages`). The Preferences dialog previews the chosen language before OK.
|
||||
|
|
|
|||
|
|
@ -2601,7 +2601,7 @@ without ideographs uses its em box. One undo step.
|
|||
|
||||
## New type in a Japanese interface
|
||||
|
||||
While the interface is in Japanese (VectorCraft › Language, or `auto` on a Japanese system), new type starts with em
|
||||
While the interface is in Japanese (Preferences › User Interface › Language, or `auto` on a Japanese system), new type starts with em
|
||||
box top-to-top leading (`leadingModel: "emBoxTop"`) and em box centre character alignment (`charAlign: "emBoxCenter"`);
|
||||
in other languages it starts on the Roman baseline (#432). This covers the Type tools,
|
||||
`text.create` and `text.createInPath`, which also take `leadingModel` and `charAlign` to choose, and `paraStyle.new` /
|
||||
|
|
|
|||
Loading…
Reference in New Issue