diff --git a/crates/snowbound/src/art.rs b/crates/snowbound/src/art.rs index 68988569e7a511920eb7a1a344236255dcdb2063..871e3baa0d7638bff072976e03731c2c29026eea 100644 --- a/crates/snowbound/src/art.rs +++ b/crates/snowbound/src/art.rs @@ -110,7 +110,6 @@ pub const CLOSE_NOTEBOOK: &[&str] = art!( pub const CODE: &[&str] = art!("icons/code"); pub const COMMAND_PALETTE: &[&str] = art!("icons/palette", "icons/badge-command"); pub const COPY_LINK: &[&str] = art!("icons/page", "icons/badge-link"); -pub const CUSTOMIZE_THEME: &[&str] = art!("icons/theme", "icons/badge-edit"); pub const CUSTOMIZE_TAGS: &[&str] = art!("icons/tag", "icons/badge-edit"); pub const DELETE: &[&str] = art!("icons/delete"); pub const EMPTY_RECYCLE_BIN: &[&str] = art!("icons/recycle-bin", "icons/badge-remove"); @@ -195,7 +194,6 @@ pub const SNAP_TO_GRID: &[&str] = art!("icons/snap-to-grid"); pub const STOP: &[&str] = art!("icons/stop"); pub const SUBPAGE: &[&str] = art!("icons/subpage"); pub const SYNC_NOW: &[&str] = art!("icons/sync-now"); -pub const THEME: &[&str] = art!("icons/theme"); pub const TO_DO: &[&str] = art!("icons/to-do"); pub const UPDATE: &[&str] = art!("icons/update"); pub const ZOOM_ACTUAL: &[&str] = art!("icons/zoom-actual"); diff --git a/crates/snowbound/src/background.rs b/crates/snowbound/src/background.rs index 5c117d2aea14d2a748d6bfb6c23282d707496472..4285d9bba55543073e7bc118acdae9e9a2066003 100644 --- a/crates/snowbound/src/background.rs +++ b/crates/snowbound/src/background.rs @@ -89,18 +89,21 @@ pub fn menu( let groups = [ ui::popup::Group { heading: "Page Color", + ruled: false, cells: 2 + PAGE_COLORS.len(), columns: COLUMNS, size: SWATCH, }, ui::popup::Group { heading: "Background", + ruled: false, cells: 2 + ART.len(), columns: 3, size: [TILE[0] + 8.0, TILE[1] + 8.0], }, ui::popup::Group { heading: "Rule Lines", + ruled: false, cells: 1 + RULE_LINES.len(), columns: COLUMNS, size: [RULES; 2], diff --git a/crates/snowbound/src/commands.rs b/crates/snowbound/src/commands.rs index 4efcb12cf2acbc6b160c06930414ff5ccbed9011..fc62ff27f030456b6b3afdd61db36866bcee7e71 100644 --- a/crates/snowbound/src/commands.rs +++ b/crates/snowbound/src/commands.rs @@ -596,7 +596,7 @@ pub const COMMANDS: &[Command] = &[ row!(Id::Style(8), "Quote", NONE, NONE), row!(Id::Style(9), "Code", NONE, NONE), row!(Id::Style(10), "Normal", NONE, NONE), - row!(Id::Themes, "Customize Theme", NONE, NONE), + row!(Id::Themes, "Customize Font Styles", NONE, NONE), row!(Id::CustomizeTags, "Customize Tags", NONE, NONE), row!( Id::RemoveTags, diff --git a/crates/snowbound/src/main.rs b/crates/snowbound/src/main.rs index 5a26893f1f838b6e0a7146f187cec972013cece1..34ad2534187cc2d2c6dfec016661dc09a3d4750a 100644 --- a/crates/snowbound/src/main.rs +++ b/crates/snowbound/src/main.rs @@ -5184,6 +5184,7 @@ fn list_gallery( let groups = [(headings[0], recent.len()), (headings[1], count + 1)].map(|(heading, cells)| { ui::popup::Group { heading, + ruled: false, cells, columns: 5, size, @@ -5228,6 +5229,7 @@ fn pen_gallery( const CELL: [f32; 2] = [40.0, 24.0]; let groups = [ui::popup::Group { heading: "Pens", + ruled: false, cells: pens.len(), columns: 5, size: CELL, @@ -5666,7 +5668,7 @@ fn artwork(id: commands::Id) -> Option<&'static [&'static str]> { Cmd::Style(8) => art::QUOTE, Cmd::Style(9) => art::CODE, Cmd::Style(_) => art::NORMAL, - Cmd::Themes => art::CUSTOMIZE_THEME, + Cmd::Themes => art::STYLES, Cmd::OpenShared => art::OPEN_SHARED, Cmd::LiveShare => art::LIVE_SHARE, Cmd::MarkdownShortcuts => art::MARKDOWN, diff --git a/crates/snowbound/src/menus.rs b/crates/snowbound/src/menus.rs index 04d0cc247e1110a9c8bbbc8b1a3abea2ef5913f5..c1670c2cbae061f65fbc443775ad098df7483f65 100644 --- a/crates/snowbound/src/menus.rs +++ b/crates/snowbound/src/menus.rs @@ -151,7 +151,7 @@ impl Action { Action::NewGroup => art::NEW_SECTION_GROUP, Action::Reveal => art::FOLDER, Action::Close => art::CLOSE_NOTEBOOK, - Action::Theme => art::THEME, + Action::Theme => art::STYLES, Action::Colors => art::SECTION_COLOR, Action::Sync => art::SYNC_NOW, Action::NewNotebook => art::NEW_NOTEBOOK, @@ -334,6 +334,11 @@ impl State { (action, item) }; let nowhere = || self.destinations(target).is_empty(); + // Last on a page, section or notebook, under a rule. + let styles = || { + let title = commands::command(commands::Id::Themes).title; + item(Action::Theme, title, false, true) + }; match target { // OneNote's Move or Copy takes a page out of the bin; nothing else changes it. Target::Page { path, .. } if crate::recycle::binned(path) => vec![ @@ -360,11 +365,11 @@ impl State { item(Action::NewPage, "New Page", false, true), // OneNote offers this beside New Page, which is a plain + here. item(Action::NewSubpage, "New Subpage", false, false), - item(Action::Theme, "Theme", false, true), ]; // Levels and versions are known once the section is open. let Some(session) = self.session.as_ref().filter(|_| self.open(library, path)) else { + actions.push(styles()); return actions; }; let pages = &session.pages; @@ -393,6 +398,7 @@ impl State { session.page_versions(*space).is_empty(), true, ), + styles(), ]); actions } @@ -423,7 +429,7 @@ impl State { section_file(library, path).is_none(), false, ), - item(Action::Theme, "Theme", false, false), + styles(), ]); } actions @@ -493,12 +499,11 @@ impl State { library.folder().is_none(), true, ), - item(Action::Theme, "Theme", false, false), item( Action::RecycleBin, "Notebook Recycle Bin", library.catalog().is_none(), - true, + false, ), item( Action::Properties, @@ -506,6 +511,7 @@ impl State { library.catalog().is_none(), false, ), + styles(), ] } Target::Closed(_) | Target::Server(_) => { diff --git a/crates/snowbound/src/symbol.rs b/crates/snowbound/src/symbol.rs index a6181a3779f81a0be331a0d7ec59e16f7ae94441..279191c22e4acbba781933628f8fcdc4dca17122 100644 --- a/crates/snowbound/src/symbol.rs +++ b/crates/snowbound/src/symbol.rs @@ -82,12 +82,14 @@ pub fn gallery(ui: &mut Ui, id: Id, anchor: Anchor, symbols: &[char]) -> Option< let groups = [ ui::popup::Group { heading: "", + ruled: false, cells: symbols.len(), columns: 5, size: [SIZE; 2], }, ui::popup::Group { heading: "", + ruled: true, cells: 1, columns: 1, size: [5.0 * SIZE, 28.0], diff --git a/crates/snowbound/src/themes.rs b/crates/snowbound/src/themes.rs index 8d4c9dec6c6eb7f8cda74dd976d32dfab5194691..349dc7d497ef6ea2cbf3e9d9cd723fe0516ef0c1 100644 --- a/crates/snowbound/src/themes.rs +++ b/crates/snowbound/src/themes.rs @@ -1,8 +1,8 @@ //! Style themes in the app (`resources/styles.md`): the page wears its own theme, else its //! section's, else its notebook's, as its paragraph style objects; the Styles gallery -//! applies a style in the page's theme, and its Customize… opens the Themes dialog, which -//! edits a notebook's own themes with a live preview and gives one to the page, the section -//! or the notebook. +//! applies a style in the page's theme, and its Customize Font Styles opens the dialog of +//! that name, which edits a notebook's own themes with a live preview and gives one to the +//! page, the section or the notebook. use crate::{Library, State, filetime}; use accesskit::Role; @@ -255,12 +255,13 @@ impl State { ..Spec::default() }, ); + let named = crate::commands::command(crate::commands::Id::Themes).title; if let Some(node) = ui.access(id()) { - node.set_label("Themes"); + node.set_label(named); } let title = match &dialog.targets[..] { - [(scope, _)] => format!("Theme for {}", scope.name()), - _ => "Themes".to_owned(), + [(scope, _)] => format!("{named} for {}", scope.name()), + _ => named.to_owned(), }; ui.leaf( "title", @@ -770,12 +771,14 @@ pub(crate) fn gallery( .enumerate() .map(|(at, (name, _))| ui::popup::Group { heading: if at == 0 { &sheet.name } else { "" }, + ruled: false, cells: 1, columns: 1, size: row(shown_size(&sheet.styles[*name], GALLERY_LARGEST) * 1.25), }) .chain([ui::popup::Group { heading: "", + ruled: true, cells: 1, columns: 1, size: row(16.0), @@ -807,7 +810,7 @@ pub(crate) fn gallery( "customize", Spec { size: [fill(), fill()], - text: Some("Customize"), + text: Some(crate::commands::command(Cmd::Themes).title), ..Spec::default() }, ); diff --git a/crates/ui/src/popup.rs b/crates/ui/src/popup.rs index 54411e33d5c3bf75bbd766782755f2664bb91cf1..9877df46429111dc25210cb1eaacf449c6c10fd6 100644 --- a/crates/ui/src/popup.rs +++ b/crates/ui/src/popup.rs @@ -1038,6 +1038,8 @@ pub fn table_picker(ui: &mut Ui, id: Id, anchor: Anchor, size: [usize; 2]) -> Op #[derive(Clone, Copy, Debug)] pub struct Group<'a> { pub heading: &'a str, + /// Starts under a rule, as a gallery's command after its choices. + pub ruled: bool, pub cells: usize, pub columns: usize, pub size: [f32; 2], @@ -1096,7 +1098,29 @@ pub fn gallery( width + 2.0 * ui.theme.menu().pad, ); let mut index = 0; + let style = theme.menu(); for (number, group) in groups.iter().enumerate() { + if group.ruled { + ui.open( + ("rule", number), + Spec { + size: [fill(), px(style.rule_band)], + ..Spec::default() + }, + ); + ui.leaf( + "line", + Spec { + flags: Flags::FLOAT, + size: [fill(), px(1.0)], + position: [0.0, (style.rule_band - 1.0) / 2.0], + inset: [style.rule_inset, 0.0, style.rule_inset, 0.0], + fill: Some(style.rule), + ..Spec::default() + }, + ); + ui.close(); + } if !group.heading.is_empty() { ui.leaf( ("heading", number), diff --git a/crates/ui/src/tests.rs b/crates/ui/src/tests.rs index cf47717c99d6d3d91f4bddaca44d2cec11dd3f93..dc04cd03df62ac4d95c447a3ef6de1f9a09ef805 100644 --- a/crates/ui/src/tests.rs +++ b/crates/ui/src/tests.rs @@ -2911,6 +2911,7 @@ fn galleries_choose_across_their_groups_by_keys_and_clicks() { let gallery = Id::ROOT.child("gallery"); let groups = [("Recent", 2), ("Library", 5)].map(|(heading, cells)| popup::Group { heading, + ruled: false, cells, columns: 3, size: [30.0, 30.0],