mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-31 14:17:12 -06:00
Merge pull request #318 from vangel76/fix/theme-toggle
UI: title-bar light/dark switch, File › Display theme, system appearance on first run (#194, #239) # Conflicts: # docs/ui-parity.md
This commit is contained in:
@@ -97,6 +97,8 @@ fn load_prefs(app: &mut SheetApp) {
|
||||
}
|
||||
// First run (or a ui.json without a usable language): follow the desktop's language.
|
||||
app.ui.language = gridcraft_ui_egui::i18n::Language::system();
|
||||
// ...and its light or dark appearance (#239), until a theme is chosen and saved in ui.json.
|
||||
app.ui.system_theme = true;
|
||||
let Some(dir) = config_dir() else { return };
|
||||
if let Ok(b) = std::fs::read(dir.join("ui.json"))
|
||||
&& let Ok(ui) = serde_json::from_slice::<gridcraft_ui_egui::UiState>(&b)
|
||||
|
||||
@@ -108,6 +108,8 @@ pub enum Icon {
|
||||
Share,
|
||||
Search,
|
||||
Settings,
|
||||
/// Light/dark appearance: a circle, its right half filled.
|
||||
Appearance,
|
||||
Sheet,
|
||||
Book,
|
||||
Folder,
|
||||
@@ -596,6 +598,16 @@ pub fn paint(p: &Painter, rect: Rect, icon: Icon, c: Color32) {
|
||||
g.circle(8.0, 8.0, 5.0, None, Some(c));
|
||||
g.circle(8.0, 8.0, 2.0, Some(c), None);
|
||||
}
|
||||
Icon::Appearance => {
|
||||
g.circle(8.0, 8.0, 5.5, None, Some(c));
|
||||
let half: Vec<(f32, f32)> = (0..=12)
|
||||
.map(|i| {
|
||||
let a = std::f32::consts::PI * (i as f32 / 12.0 - 0.5);
|
||||
(8.0 + 5.5 * a.cos(), 8.0 + 5.5 * a.sin())
|
||||
})
|
||||
.collect();
|
||||
g.poly(&half, c);
|
||||
}
|
||||
Icon::Book => {
|
||||
g.rect(2.0, 2.0, 12.0, 12.0, Some(GREEN), None);
|
||||
g.rect(4.0, 4.0, 8.0, 8.0, Some(Color32::WHITE), None);
|
||||
|
||||
@@ -135,6 +135,16 @@ pub fn title_bar(app: &mut SheetApp, ui: &mut Ui) {
|
||||
if icon_button(ui, Icon::Comment, t.text_dim, "Comments", vec2(28.0, ch)).clicked() {
|
||||
app.open_dialog("comments", json!({}));
|
||||
}
|
||||
// Quick light/dark switch (#194); right-click offers System as well. The same
|
||||
// choice lives in File › Display theme and the View tab.
|
||||
let lang = app.ui.language;
|
||||
let theme = icon_button(ui, Icon::Appearance, t.text_dim, "Dark Mode", vec2(28.0, 26.0));
|
||||
let dark = ui.ctx().theme() == egui::Theme::Dark;
|
||||
theme.widget_info(|| egui::WidgetInfo::selected(egui::WidgetType::Checkbox, true, dark, lang.tr("Dark Mode")));
|
||||
if theme.clicked() {
|
||||
act(app, "view.darkMode", json!({}));
|
||||
}
|
||||
theme.context_menu(|ui| theme_choices(app, ui));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -252,9 +262,24 @@ fn file_menu(app: &mut SheetApp, ui: &mut Ui) {
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
// Excel keeps the theme under File › Account › Office Theme (#194).
|
||||
ui.separator();
|
||||
ui.menu_button(app.ui.language.tr("Display theme"), |ui| theme_choices(app, ui));
|
||||
});
|
||||
}
|
||||
|
||||
/// System / Light / Dark, as in the View tab's Display theme box (`view.theme`).
|
||||
fn theme_choices(app: &mut SheetApp, ui: &mut Ui) {
|
||||
let lang = app.ui.language;
|
||||
let mode = app.ui.theme_mode();
|
||||
for (value, label) in [("system", "System"), ("light", "Light"), ("dark", "Dark")] {
|
||||
if ui.radio(mode == value, lang.tr(label)).clicked() {
|
||||
act(app, "view.theme", json!({"mode": value}));
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn contextual_tabs(app: &SheetApp) -> Vec<&'static str> {
|
||||
let mut v = Vec::new();
|
||||
if let Some(d) = app.session.active()
|
||||
|
||||
@@ -162,3 +162,29 @@ fn invalid_mode_preserves_preferences_and_legacy_overrides_leave_system_mode() {
|
||||
system_theme(&mut h, Some(Theme::Dark));
|
||||
assert_appearance(&h, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn title_bar_switch_and_file_menu_choose_the_theme() {
|
||||
// #194: one click in the title bar switches light/dark; File › Display theme offers all three.
|
||||
let mut h = harness(UiState::default());
|
||||
system_theme(&mut h, Some(Theme::Light));
|
||||
assert_appearance(&h, false);
|
||||
h.get_by_role_and_label(egui::accesskit::Role::CheckBox, "Dark Mode").click();
|
||||
h.run_steps(2);
|
||||
assert_eq!(preferences(&h)["dark"], true);
|
||||
assert_eq!(preferences(&h)["systemTheme"], false);
|
||||
assert_appearance(&h, true);
|
||||
h.get_by_role_and_label(egui::accesskit::Role::CheckBox, "Dark Mode").click();
|
||||
h.run_steps(2);
|
||||
assert_appearance(&h, false);
|
||||
|
||||
h.get_by_label("File").click();
|
||||
h.run_steps(3);
|
||||
h.get_by_label("Display theme ⏵").click();
|
||||
h.run_steps(3);
|
||||
h.get_by_label("System").click();
|
||||
h.run_steps(3);
|
||||
assert_eq!(preferences(&h)["systemTheme"], true);
|
||||
system_theme(&mut h, Some(Theme::Dark));
|
||||
assert_appearance(&h, true);
|
||||
}
|
||||
|
||||
+2
-1
@@ -23,7 +23,7 @@ Sources: `crates/ui-egui/src` (ribbon, grid, editor, formula bar, dialogs, panes
|
||||
| Status bar: Sum/Count/Average and more, view buttons, zoom | yes | yes | customizable statistics partial |
|
||||
| Task panes (Format Chart, Comments, Watch, Selection, PivotTable fields) | yes | yes | element-level Format pane for shapes and pictures missing |
|
||||
| Backstage (File) view: Info, New with templates, Open recent, Export, Options | yes | partial | Options dialog and template gallery missing |
|
||||
| Dark mode, system appearance | yes | yes | done (10-09) |
|
||||
| Dark mode, system appearance | yes | yes | done (10-09); follows the system on first run, title-bar switch and File › Display theme (#194, #239) |
|
||||
| Page Layout view (paper view with rulers and header editing) | yes | **no** (Page Break Preview only) | 8–12 h |
|
||||
| Multiple windows per workbook | yes | no (#162) | see [hardware-parity.md](hardware-parity.md) |
|
||||
|
||||
@@ -94,5 +94,6 @@ scrollbar bugs 2–4 · pixel/feel pass against observed Excel 7–12.
|
||||
|---|---|---|
|
||||
| 2026-10-11 | minor | Delete and Backspace now remove the selected chart, picture or shape (#213) |
|
||||
| 2026-10-10 | minor | Keep formula helpers inside the worksheet when scrolling (#200) |
|
||||
| 2026-10-11 | trivial | Theme: title-bar light/dark switch, File › Display theme, system appearance on first run (#194, #239) |
|
||||
| 2026-10-10 | minor | Chart resize bug (#190) |
|
||||
| 2026-10-10 | major | Created: chrome, grid, keyboard, dialogs, accessibility; key tips, Page Layout view and accessibility tree flagged |
|
||||
|
||||
Reference in New Issue
Block a user