diff --git a/gpx-rs/engine/src/engine/command/edit/new_track.rs b/gpx-rs/engine/src/engine/command/edit/new_track.rs index ff90ee736..b6642a88d 100644 --- a/gpx-rs/engine/src/engine/command/edit/new_track.rs +++ b/gpx-rs/engine/src/engine/command/edit/new_track.rs @@ -12,11 +12,22 @@ impl Apply for NewTrack { impl Editor for NewTrack { fn file(&mut self, file: &mut File) -> Edit { - file.trk.push(Track::default()); + let mut track = Track::default(); + track.info.color = common(file, |t| &t.info.color); + track.info.opacity = common(file, |t| &t.info.opacity); + track.info.width = common(file, |t| &t.info.width); + file.trk.push(track); Edit::Changed } } +/// Returns the value of a style attribute if all existing tracks agree on it. +fn common(file: &File, get: impl Fn(&Track) -> &Option) -> Option { + let mut tracks = file.trk.iter(); + let first = get(tracks.next()?); + tracks.all(|t| get(t) == first).then(|| first.clone())? +} + #[cfg(test)] mod tests { use crate::{New, engine::command::fixture::Fixture}; @@ -33,4 +44,22 @@ mod tests { assert_eq!(file.trk.len(), 2); assert_ne!(file.trk[0].id, file.trk[1].id); } + + #[test] + fn test_new_track_inherits_agreeing_style_only() { + let mut fx = Fixture::default(); + New { name: "file" }.apply(&mut fx.state()).unwrap(); + NewTrack.apply(&mut fx.state()).unwrap(); + NewTrack.apply(&mut fx.state()).unwrap(); + let file = std::rc::Rc::make_mut(fx.files.values_mut().next().unwrap()); + for (i, trk) in file.trk.iter_mut().enumerate() { + trk.info.color = Some("ff0000".into()); + trk.info.opacity = Some(0.5 + i as f64 * 0.1); + } + NewTrack.apply(&mut fx.state()).unwrap(); + let info = &fx.files.values().next().unwrap().trk[2].info; + assert_eq!(info.color.as_deref(), Some("ff0000")); + assert_eq!(info.opacity, None); + assert_eq!(info.width, None); + } }