From 4efbba96bbdf3dddeb0a853310b08a5281d2f8a0 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Fri, 20 Jan 2023 16:51:07 -0330 Subject: remove Volume trait --- src/main.rs | 47 +++++++++++++++++------------- src/volume.rs | 91 ++++++++++++++++++++++------------------------------------- 2 files changed, 61 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 2c1fa85..4c6cf43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,45 +1,38 @@ use iced::{ - widget::{column, row, text, text_input}, + widget::{column, pick_list, row, text, text_input}, Element, Sandbox, Settings, }; -use volute::volume::{CubicMetre, Volume}; +use volute::volume::{self, CubicMetre}; pub fn main() -> iced::Result { App::run(Settings::default()) } +#[derive(Default)] struct App { - displacement: Box, + displacement: CubicMetre, ui: UI, } #[derive(Default)] struct UI { displacement: String, + displacement_unit: volume::Unit, } impl App { fn set_displacement(&mut self, displacement: &str) { if displacement.len() == 0 { - self.displacement.set(0.0); + self.displacement.0 = 0.0; self.ui.displacement = "".to_string(); - } else if let Ok(d) = displacement.parse::() { - self.displacement.set(d); + } else if let Ok(val) = displacement.parse::() { + self.displacement = CubicMetre::from_unit(self.ui.displacement_unit, val); self.ui.displacement = String::from(displacement); } } } -impl Default for App { - fn default() -> Self { - Self { - displacement: Box::new(CubicMetre::default()), - ui: UI::default(), - } - } -} - impl Sandbox for App { type Message = Message; @@ -53,17 +46,32 @@ impl Sandbox for App { fn update(&mut self, message: Message) { match message { - Message::DisplacementChanged(displacement) => { + Message::Displacement(displacement) => { self.set_displacement(&displacement); } + Message::DisplacementUnit(unit) => { + self.ui.displacement = format!( + "{:.2}", + volume::convert( + self.ui.displacement.parse::().unwrap(), + self.ui.displacement_unit, + unit, + ) + ); + self.ui.displacement_unit = unit; + } } } fn view(&self) -> Element { column![row![ text("Displacement:"), - text_input("2.0", &self.ui.displacement, Message::DisplacementChanged), - text(self.displacement.unit()), + text_input("2.0", &self.ui.displacement, Message::Displacement), + pick_list( + &volume::Unit::ALL[..], + Some(self.ui.displacement_unit), + Message::DisplacementUnit, + ), ]] .into() } @@ -71,5 +79,6 @@ impl Sandbox for App { #[derive(Debug, Clone)] pub enum Message { - DisplacementChanged(String), + Displacement(String), + DisplacementUnit(volume::Unit), } diff --git a/src/volume.rs b/src/volume.rs index 675dfaa..933ae49 100644 --- a/src/volume.rs +++ b/src/volume.rs @@ -3,22 +3,17 @@ use std::{ ops::Mul, }; -pub trait Volume { - /// Returns the volume in SI units (cubic metres). - fn si(self) -> CubicMetre; - - fn set(&mut self, val: f64); - - fn unit(&self) -> Unit; - - fn convert(self, unit: Unit) -> Box; -} - +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] pub enum Unit { + #[default] CubicMetre, Litre, } +impl Unit { + pub const ALL: [Self; 2] = [Self::CubicMetre, Self::Litre]; +} + impl Display for Unit { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( @@ -33,62 +28,29 @@ impl Display for Unit { } #[derive(Debug, Default, PartialEq)] -pub struct CubicMetre(f64); +pub struct CubicMetre(pub f64); -impl Volume for CubicMetre { - fn si(self) -> CubicMetre { - self - } - - fn set(&mut self, val: f64) { - self.0 = val; - } - - fn unit(&self) -> Unit { - Unit::CubicMetre - } - - fn convert(self, unit: Unit) -> Box { +impl CubicMetre { + pub fn from_unit>(unit: Unit, value: F) -> Self { match unit { - Unit::CubicMetre => Box::new(self), - Unit::Litre => Box::new(Litre::from(self)), + Unit::CubicMetre => Self(value.into()), + Unit::Litre => Self::from(Litre(value.into())), } } } impl From for CubicMetre { fn from(value: Litre) -> Self { - value.si() + Self(value.0 * 10_f64.powf(-3.)) } } #[derive(Debug, PartialEq)] struct Litre(f64); -impl Volume for Litre { - fn si(self) -> CubicMetre { - CubicMetre(self.0 * 10_f64.powf(-3.)) - } - - fn set(&mut self, val: f64) { - self.0 = val - } - - fn unit(&self) -> Unit { - Unit::Litre - } - - fn convert(self, unit: Unit) -> Box { - match unit { - Unit::CubicMetre => Box::new(CubicMetre::from(self)), - Unit::Litre => Box::new(self), - } - } -} - -impl From for Litre { - fn from(value: i32) -> Self { - Self(value as f64) +impl> From for Litre { + fn from(value: F) -> Self { + Self(value.into()) } } @@ -98,21 +60,34 @@ impl From for Litre { } } -impl Mul for Litre { +impl> Mul for Litre { type Output = Self; - fn mul(self, rhs: f64) -> Self::Output { - Self(self.0 * rhs) + fn mul(self, rhs: F) -> Self::Output { + Self(self.0 * rhs.into()) + } +} + +pub fn convert>(val: F, from: Unit, to: Unit) -> f64 { + match from { + Unit::CubicMetre => match to { + Unit::CubicMetre => val.into(), + Unit::Litre => Litre::from(CubicMetre(val.into())).0, + }, + Unit::Litre => match to { + Unit::Litre => val.into(), + Unit::CubicMetre => CubicMetre::from(Litre(val.into())).0, + }, } } #[cfg(test)] mod tests { - use crate::volume::{CubicMetre, Litre, Volume}; + use super::{CubicMetre, Litre}; #[test] fn litre_to_cubic_metre() { - assert_eq!(Litre(1000.).si(), CubicMetre(1.)) + assert_eq!(CubicMetre::from(Litre(1000.)), CubicMetre(1.)) } #[test] -- cgit v1.2.3