//! The role set every surface paints from. //! //! Roles are named for what they do, not for a container ladder. `surface_active` //! is the selected panel and the hover fill; it is not "surface container //! highest", because nothing in Lumbridge has to reason about how many //! containers deep it is. //! //! Two rules the rest of the application depends on: //! //! - **Provenance roles are distinct from state roles.** Decision 0012 says a //! usage value is coloured by where it came from, never by how alarming it is. //! They are separate fields here so a theme cannot quietly collapse the two, //! and a test asserts the five stay pairwise distinguishable. //! - **Nothing is derived lazily.** A `Palette` is computed once when the theme //! changes and then only read, so a render pass never runs the bisection. use crate::color::Srgb; /// Every colour the interface is allowed to use. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Palette { /// The application frame: window background, sidebar, footer, tab gutter. pub chrome: Srgb, /// The work surface: panel bodies, terminals, editors. pub surface: Srgb, /// One step off the surface: unselected tabs, inline cards. pub surface_raised: Srgb, /// Two steps: the selected panel, hover fills, chip backgrounds. pub surface_active: Srgb, /// Floating above everything: the command palette, popovers, menus. pub surface_overlay: Srgb, /// The seam where the frame meets the content. pub surface_between: Srgb, pub border: Srgb, /// A divider that should be felt rather than seen. pub border_quiet: Srgb, pub text: Srgb, /// Secondary text. The theme's own comment colour, so it is legible against /// the surface by construction rather than by our guess. pub muted: Srgb, /// Focus rings, selection, the active tab underline. pub accent: Srgb, /// Black or white, whichever reads on `accent`. pub on_accent: Srgb, pub success: Srgb, pub danger: Srgb, /// A danger fill quiet enough to sit behind text. pub danger_container: Srgb, /// Needs a human. Paired with a glyph, never used alone. pub attention: Srgb, pub attention_wash: Srgb, /// Tooltips and inverted chips. pub inverse_surface: Srgb, pub on_inverse: Srgb, pub scrim: Srgb, pub is_dark: bool, } impl Palette { /// The colour a usage reading is drawn in, by where the number came from. /// /// Decision 0012's rule made explicit: the argument is a provenance, and /// there is no way to pass a value in, so this cannot accidentally become /// "red when low". #[must_use] pub const fn provenance(&self, provenance: Provenance) -> Srgb { match provenance { Provenance::Provider => self.success, Provenance::Harness => self.accent, Provenance::Local => self.text, Provenance::Estimated => self.attention, Provenance::Unavailable => self.muted, } } /// The five provenance colours, for the distinctness test. #[must_use] pub const fn provenance_roles(&self) -> [Srgb; 5] { [ self.success, self.accent, self.text, self.attention, self.muted, ] } } /// Where a usage number came from. /// /// A structural mirror of `lumbridge_core::UsageProvenance`, kept here so this /// crate stays free of a dependency on the ledger. The UI maps between them. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Provenance { Provider, Harness, Local, Estimated, Unavailable, }