use std::sync::Arc; use druid::im::Vector; use druid::{Data, Lens}; use super::{ModInfo, NexusInfo, State}; pub(crate) struct SelectedModLens; impl Lens>> for SelectedModLens { #[tracing::instrument(name = "SelectedModLens::with", skip_all)] fn with>) -> V>(&self, data: &State, f: F) -> V { let info = data .selected_mod_index .and_then(|i| data.mods.get(i).cloned()); f(&info) } #[tracing::instrument(name = "SelectedModLens::with_mut", skip_all)] fn with_mut>) -> V>(&self, data: &mut State, f: F) -> V { match data.selected_mod_index { Some(i) => { let mut info = data.mods.get_mut(i).cloned(); let ret = f(&mut info); if let Some(new) = info { // TODO: Figure out a way to check for equality and // only update when needed data.mods.set(i, new); } else { data.selected_mod_index = None; } ret } None => f(&mut None), } } } /// A Lens that maps an `im::Vector` to `im::Vector<(usize, T)>`, /// where each element in the destination vector includes its index in the /// source vector. pub(crate) struct IndexedVectorLens; impl Lens, Vector<(usize, T)>> for IndexedVectorLens { #[tracing::instrument(name = "IndexedVectorLens::with", skip_all)] fn with) -> V>(&self, values: &Vector, f: F) -> V { let indexed = values .iter() .enumerate() .map(|(i, val)| (i, val.clone())) .collect(); f(&indexed) } #[tracing::instrument(name = "IndexedVectorLens::with_mut", skip_all)] fn with_mut) -> V>( &self, values: &mut Vector, f: F, ) -> V { let mut indexed = values .iter() .enumerate() .map(|(i, val)| (i, val.clone())) .collect(); let ret = f(&mut indexed); *values = indexed.into_iter().map(|(_i, val)| val).collect(); ret } } /// A Lens that first checks a key in a mod's `NexusInfo`, then falls back to /// the regular one. pub(crate) struct NexusInfoLens where L: Lens, R: Lens, { value: L, fallback: R, _marker: std::marker::PhantomData, } impl NexusInfoLens where L: Lens, R: Lens, { pub fn new(value: L, fallback: R) -> Self { Self { value, fallback, _marker: std::marker::PhantomData, } } } impl Lens for NexusInfoLens where L: Lens, R: Lens, { fn with V>(&self, data: &ModInfo, f: F) -> V { if let Some(nexus) = &data.nexus { self.value.with(nexus, f) } else { self.fallback.with(data, f) } } fn with_mut V>(&self, data: &mut ModInfo, f: F) -> V { if let Some(nexus) = &mut data.nexus { self.value.with_mut(nexus, f) } else { self.fallback.with_mut(data, f) } } }