diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index ec39222a4..8ecaf9ac2 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -46,7 +46,7 @@ use lightcraft_catalog::{Catalog, Filter, Op, PhotoId, Sort}; use lightcraft_develop::DevelopSettings; pub use media::{RenderJob, SourceLevel}; use serde_json::Value; -pub use view::{Browse, FilterChip, LibrarySource, Selection, filter_chips}; +pub use view::{Browse, FilterChip, LibrarySource, Selection, SelectionState, filter_chips}; pub use {lightcraft_catalog as catalog, lightcraft_develop as develop, lightcraft_gpu as gpu, lightcraft_pipeline as pipeline}; #[derive(Debug, thiserror::Error)] diff --git a/crates/engine/src/view.rs b/crates/engine/src/view.rs index 757adfe94..49d7462b3 100644 --- a/crates/engine/src/view.rs +++ b/crates/engine/src/view.rs @@ -74,7 +74,27 @@ pub struct Selection { pub active: Option, } +/// How a photo relates to the selection: what every view draws (grid cell, filmstrip cell…). +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum SelectionState { + NotSelected, + /// Selected, but not the photo the loupe and panels act on. + Selected, + /// The most-selected photo. + Active, +} + impl Selection { + /// What views draw for `id`: active, selected or neither (one answer for grid, filmstrip, …). + pub fn state_of(&self, id: PhotoId) -> SelectionState { + if self.active == Some(id) { + SelectionState::Active + } else if self.contains(id) { + SelectionState::Selected + } else { + SelectionState::NotSelected + } + } pub fn single(id: PhotoId) -> Selection { Selection { ids: vec![id], active: Some(id) } } @@ -203,3 +223,18 @@ fn date_label(d: &str) -> String { _ => d.to_string(), } } + +#[cfg(test)] +mod selection_state_tests { + use super::*; + use lightcraft_catalog::PhotoId; + + #[test] + fn select_all_marks_the_others_selected_and_one_active() { + let ids: Vec = (1..=3).map(PhotoId).collect(); + let s = Selection { ids: ids.clone(), active: Some(ids[0]) }; + assert_eq!(s.state_of(ids[0]), SelectionState::Active); + assert_eq!(s.state_of(ids[1]), SelectionState::Selected); + assert_eq!(s.state_of(PhotoId(9)), SelectionState::NotSelected); + } +}