mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-10 20:51:50 +00:00
Merge pull request #4481 from fluorine/dialog-tabs-remaining
Dialogs: draw real tabs in five more dialogs
This commit is contained in:
9 files changed
+149
-45
No files matched your search
@@ -490,14 +490,11 @@ fn body(ui: &mut Ui, d: &mut ColorsDialog) -> Option<bool> {
|
||||
ui.set_width(430.0);
|
||||
ui.label(egui::RichText::new(tl!("Colors")).font(crate::theme::semibold(14.0)));
|
||||
ui.add_space(6.0);
|
||||
ui.horizontal(|ui| {
|
||||
for (tab, label) in [(ColorsTab::Standard, "Standard"), (ColorsTab::Custom, "Custom")] {
|
||||
if ui.selectable_label(d.tab == tab, tl!(label)).clicked() {
|
||||
d.tab = tab;
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
let names = [tl!("Standard").to_string(), tl!("Custom").to_string()];
|
||||
if let Some(k) = crate::widgets::dialog_tabs(ui, &names, d.tab as usize) {
|
||||
d.tab = if k == 0 { ColorsTab::Standard } else { ColorsTab::Custom };
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
ui.horizontal(|ui| {
|
||||
crate::rtl::vertical(ui, |ui| {
|
||||
ui.set_width(330.0);
|
||||
|
||||
@@ -269,14 +269,11 @@ fn symbol_cell(app: &mut WordApp, ui: &mut Ui, font: &str, c: char, selected: bo
|
||||
pub(super) fn symbol_ui(app: &mut WordApp, ui: &mut Ui, f: &mut SymbolForm) -> bool {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
ui.set_width(GRID_COLS as f32 * CELL + 24.0);
|
||||
ui.horizontal(|ui| {
|
||||
for (i, l) in ["Symbols", "Special Characters"].into_iter().enumerate() {
|
||||
if ui.selectable_label(f.tab == i as u8, tl!(l)).clicked() {
|
||||
f.tab = i as u8;
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
let names = [tl!("Symbols").to_string(), tl!("Special Characters").to_string()];
|
||||
if let Some(k) = crate::widgets::dialog_tabs(ui, &names, f.tab as usize) {
|
||||
f.tab = k as u8;
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
let mut insert: Option<(Value, String, String)> = None;
|
||||
if f.tab == 1 {
|
||||
if special_ui(app, ui, f, &mut insert, &t) {
|
||||
|
||||
@@ -557,14 +557,11 @@ impl BordersForm {
|
||||
|
||||
/// The Borders and Shading dialog body. Returns true to close.
|
||||
pub fn borders(app: &mut WordApp, ui: &mut Ui, f: &mut BordersForm) -> bool {
|
||||
ui.horizontal(|ui| {
|
||||
for (i, l) in ["Borders", "Page Border", "Shading"].into_iter().enumerate() {
|
||||
if ui.selectable_label(f.tab == i as u8, tl!(l)).clicked() {
|
||||
f.tab = i as u8;
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
let names = [tl!("Borders").to_string(), tl!("Page Border").to_string(), tl!("Shading").to_string()];
|
||||
if let Some(k) = crate::widgets::dialog_tabs(ui, &names, f.tab as usize) {
|
||||
f.tab = k as u8;
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
let theme = app.session.doc.settings.theme_colors.clone();
|
||||
match f.tab {
|
||||
0 => {
|
||||
|
||||
@@ -396,14 +396,11 @@ fn list_change(app: &mut WordApp, f: &mut AutoCorrectForm, params: Value) -> boo
|
||||
}
|
||||
|
||||
fn autocorrect_ui(app: &mut WordApp, ui: &mut Ui, f: &mut AutoCorrectForm) -> bool {
|
||||
ui.horizontal(|ui| {
|
||||
for (i, l) in ["AutoCorrect", "AutoFormat As You Type", "Math AutoCorrect"].into_iter().enumerate() {
|
||||
if ui.selectable_label(f.tab == i as u8, tl!(l)).clicked() {
|
||||
f.tab = i as u8;
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
let names = [tl!("AutoCorrect").to_string(), tl!("AutoFormat As You Type").to_string(), tl!("Math AutoCorrect").to_string()];
|
||||
if let Some(k) = crate::widgets::dialog_tabs(ui, &names, f.tab as usize) {
|
||||
f.tab = k as u8;
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
match f.tab {
|
||||
0 => autocorrect_tab(app, ui, f),
|
||||
1 => {
|
||||
|
||||
@@ -88,17 +88,14 @@ fn label_of(app: &WordApp, id: &str) -> String {
|
||||
|
||||
/// The dialog body; true closes it.
|
||||
pub fn customize_ribbon(app: &mut WordApp, ui: &mut Ui, f: &mut RibbonForm) -> bool {
|
||||
ui.horizontal(|ui| {
|
||||
for (page, name) in [(Page::Ribbon, "Ribbon"), (Page::QuickAccess, "Quick Access Toolbar")] {
|
||||
if ui.selectable_label(f.page == page, tl!(name)).clicked() && f.page != page {
|
||||
f.page = page;
|
||||
f.renaming = None;
|
||||
f.confirm_reset = false;
|
||||
f.message.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
let names = [tl!("Ribbon").to_string(), tl!("Quick Access Toolbar").to_string()];
|
||||
if let Some(k) = crate::widgets::dialog_tabs(ui, &names, (f.page == Page::QuickAccess) as usize) {
|
||||
f.page = if k == 0 { Page::Ribbon } else { Page::QuickAccess };
|
||||
f.renaming = None;
|
||||
f.confirm_reset = false;
|
||||
f.message.clear();
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
let (left, right, h) = (150.0, 230.0, 300.0);
|
||||
ui.add(egui::TextEdit::singleline(&mut f.filter).hint_text(tl!("Search")).desired_width(left + right + 8.0));
|
||||
let mut cats: Vec<(String, String)> = categories(app).into_iter().map(|c| (c.clone(), tl!(&c).to_string())).collect();
|
||||
|
||||
@@ -274,7 +274,7 @@ fn paragraph_dialog(app: &mut WordApp, ui: &mut Ui, d: &mut Dialog) -> bool {
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let names = ["Indents and Spacing", "Line and Page Breaks", "Asian Typography"].map(|n| tl!(n).to_string());
|
||||
let names = [tl!("Indents and Spacing").to_string(), tl!("Line and Page Breaks").to_string(), tl!("Asian Typography").to_string()];
|
||||
if let Some(k) = crate::widgets::dialog_tabs(ui, &names, *tab as usize) {
|
||||
*tab = k as u8;
|
||||
}
|
||||
@@ -1161,7 +1161,7 @@ fn about_dialog(ui: &mut Ui, d: &mut Dialog) -> bool {
|
||||
return false;
|
||||
};
|
||||
ui.set_width(820.0);
|
||||
let names = ["About", "Contributors", "Models", "Language data"].map(|n| tl!(n).to_string());
|
||||
let names = [tl!("About").to_string(), tl!("Contributors").to_string(), tl!("Models").to_string(), tl!("Language data").to_string()];
|
||||
if let Some(i) = crate::widgets::dialog_tabs(ui, &names, *tab as usize) {
|
||||
*tab = i as u8;
|
||||
}
|
||||
|
||||
@@ -813,5 +813,8 @@ pub(crate) fn rust_sources(dir: &std::path::Path) -> Vec<std::path::PathBuf> {
|
||||
files
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests_dialog_tabs;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
@@ -0,0 +1,95 @@
|
||||
//! Dialogs with real tabs: a click on a tab shows its page.
|
||||
|
||||
use egui_kittest::kittest::Queryable;
|
||||
use serde_json::json;
|
||||
use wordcraft_engine::Session;
|
||||
|
||||
use crate::WordApp;
|
||||
use crate::dialogs::Dialog;
|
||||
|
||||
fn harness(name: &str) -> egui_kittest::Harness<'static, WordApp> {
|
||||
let mut app = WordApp::new(Session::new(wordcraft_doc::Document::new()), crate::Services::default());
|
||||
let _ = app.run("ui.language", json!({"value": "en"}));
|
||||
let _ = app.run("document.setText", json!({"text": "Some text"}));
|
||||
let _ = app.run("select.all", json!({}));
|
||||
let _ = app.run("ui.dialog", json!({"name": name}));
|
||||
if app.dialog.is_none() && app.colors.is_none() {
|
||||
app.dialog = Dialog::open(name, &mut app);
|
||||
}
|
||||
let mut h = egui_kittest::Harness::builder().with_size(egui::vec2(1440.0, 900.0)).with_accessibility_check(false).build_ui_state(
|
||||
|ui, app: &mut WordApp| {
|
||||
let ctx = ui.ctx().clone();
|
||||
app.logic(&ctx);
|
||||
app.ui(ui);
|
||||
},
|
||||
app,
|
||||
);
|
||||
h.ctx.set_fonts(crate::theme::font_definitions(false, false));
|
||||
h.ctx.set_missing_glyph_policy(egui::MissingGlyphPolicy::Tofu);
|
||||
settle(&mut h);
|
||||
h
|
||||
}
|
||||
|
||||
fn settle(h: &mut egui_kittest::Harness<'static, WordApp>) {
|
||||
for _ in 0..4 {
|
||||
h.step();
|
||||
}
|
||||
}
|
||||
|
||||
fn tab_button<'a>(h: &'a egui_kittest::Harness<'static, WordApp>, label: &'a str) -> egui_kittest::Node<'a> {
|
||||
h.query_all_by_role_and_label(egui::accesskit::Role::Button, label).last().unwrap_or_else(|| panic!("no {label} button"))
|
||||
}
|
||||
|
||||
/// Click each tab in turn. After every click `page` must report its index.
|
||||
fn check(name: &str, tabs: &[&str], page: impl Fn(&WordApp) -> usize) {
|
||||
let mut h = harness(name);
|
||||
assert_eq!(page(h.state()), 0, "{name}: opens on the first tab");
|
||||
for (i, label) in tabs.iter().enumerate() {
|
||||
tab_button(&h, label).click();
|
||||
settle(&mut h);
|
||||
assert_eq!(page(h.state()), i, "{name}: the {label} tab shows its page");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn colors_tabs_switch_pages() {
|
||||
check("colors", &["Standard", "Custom"], |app| app.colors.as_ref().map_or(9, |d| d.tab as usize));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn symbol_tabs_switch_pages() {
|
||||
check("symbol", &["Symbols", "Special Characters"], |app| match &app.dialog {
|
||||
Some(Dialog::Insert(d)) => match &**d {
|
||||
crate::dialogs_insert::InsertDialog::Symbol(f) => f.tab as usize,
|
||||
_ => 9,
|
||||
},
|
||||
_ => 9,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn borders_tabs_switch_pages() {
|
||||
check("borders", &["Borders", "Page Border", "Shading"], |app| match &app.dialog {
|
||||
Some(Dialog::Borders { form }) => form.tab as usize,
|
||||
_ => 9,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn autocorrect_tabs_switch_pages() {
|
||||
check("autoCorrect", &["AutoCorrect", "AutoFormat As You Type", "Math AutoCorrect"], |app| match &app.dialog {
|
||||
Some(Dialog::Review(d)) => match &**d {
|
||||
crate::dialogs_review::ReviewDialog::AutoCorrect(f) => f.tab as usize,
|
||||
_ => 9,
|
||||
},
|
||||
_ => 9,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn customize_ribbon_tabs_switch_pages() {
|
||||
check("customizeRibbon", &["Ribbon", "Quick Access Toolbar"], |app| match &app.dialog {
|
||||
Some(Dialog::CustomizeRibbon { form }) => (form.page == crate::dialogs_ribbon::Page::QuickAccess) as usize,
|
||||
_ => 9,
|
||||
});
|
||||
}
|
||||
@@ -530,3 +530,24 @@ fn a_long_combo_list_builds_only_the_rows_in_view() {
|
||||
})
|
||||
.drop_without_applying_deltas();
|
||||
}
|
||||
|
||||
/// The tab strip exposes each tab as a button with its selected state, and a click on an
|
||||
/// unselected tab reports its index.
|
||||
#[test]
|
||||
fn dialog_tabs_expose_the_selected_state_and_report_clicks() {
|
||||
use egui_kittest::kittest::{NodeT, Queryable};
|
||||
let mut h = egui_kittest::Harness::builder().with_size(vec2(300.0, 60.0)).build_ui_state(
|
||||
|ui, st: &mut (usize, Option<usize>)| {
|
||||
if let Some(i) = dialog_tabs(ui, &["One".to_string(), "Two".to_string()], st.0) {
|
||||
st.1 = Some(i);
|
||||
}
|
||||
},
|
||||
(0usize, None),
|
||||
);
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.get_by_label("One").accesskit_node().toggled(), Some(egui::accesskit::Toggled::True));
|
||||
assert_eq!(h.get_by_label("Two").accesskit_node().toggled(), Some(egui::accesskit::Toggled::False));
|
||||
h.get_by_label("Two").click();
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().1, Some(1));
|
||||
}
|
||||
Reference in new issue
Block a user