Create Duration and Distance structures to handle rendering
These structures handle parsing and rendering of a Duration and a Distance, allowing that knowledge to be centralized and reused. Then I'm using those structures in a variety of places in order to ensure that the information gets rendered consistently.
This commit is contained in:
parent
798fbff320
commit
2d476f266c
|
@ -418,7 +418,7 @@ where
|
|||
biking_button.connect_clicked({
|
||||
let view_model = view_model.clone();
|
||||
move |_| {
|
||||
let workout = view_model.new_record(RecordType::Walk);
|
||||
let workout = view_model.new_record(RecordType::BikeRide);
|
||||
add_row(workout);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -17,10 +17,10 @@ You should have received a copy of the GNU General Public License along with Fit
|
|||
use crate::types::{
|
||||
DistanceFormatter, DurationFormatter, FormatOption, ParseError, TimeFormatter, WeightFormatter,
|
||||
};
|
||||
use dimensioned::si;
|
||||
use gtk::prelude::*;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
pub type Renderer<T> = dyn Fn(&T) -> String;
|
||||
pub type Parser<T> = dyn Fn(&str) -> Result<T, ParseError>;
|
||||
pub type OnUpdate<T> = dyn Fn(Option<T>);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with Fit
|
|||
// use dimensioned::si;
|
||||
use crate::{
|
||||
components::{distance_field, duration_field, time_field},
|
||||
types::{DistanceFormatter, DurationFormatter, TimeFormatter},
|
||||
types::{DistanceFormatter, DurationFormatter, FormatOption, TimeFormatter},
|
||||
};
|
||||
use dimensioned::si;
|
||||
use ft_core::{RecordType, TimeDistance};
|
||||
|
@ -28,20 +28,17 @@ use gtk::{prelude::*, subclass::prelude::*};
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
pub fn time_distance_summary(
|
||||
distance: si::Meter<f64>,
|
||||
duration: si::Second<f64>,
|
||||
distance: DistanceFormatter,
|
||||
duration: DurationFormatter,
|
||||
) -> Option<gtk::Label> {
|
||||
let text = match (distance > si::M, duration > si::S) {
|
||||
let text = match (*distance > si::M, *duration > si::S) {
|
||||
(true, true) => Some(format!(
|
||||
"{} kilometers of biking in {} minutes",
|
||||
distance.value_unsafe / 1000.,
|
||||
duration.value_unsafe / 60.
|
||||
"{} of biking in {}",
|
||||
distance.format(FormatOption::Full),
|
||||
duration.format(FormatOption::Full)
|
||||
)),
|
||||
(true, false) => Some(format!(
|
||||
"{} kilometers of biking",
|
||||
distance.value_unsafe / 1000.
|
||||
)),
|
||||
(false, true) => Some(format!("{} seconds of biking", duration.value_unsafe / 60.)),
|
||||
(true, false) => Some(format!("{} of biking", distance.format(FormatOption::Full))),
|
||||
(false, true) => Some(format!("{} of biking", duration.format(FormatOption::Full))),
|
||||
(false, false) => None,
|
||||
};
|
||||
|
||||
|
@ -75,7 +72,7 @@ pub fn time_distance_detail(type_: ft_core::RecordType, record: ft_core::TimeDis
|
|||
.label(
|
||||
record
|
||||
.distance
|
||||
.map(|dist| format!("{}", dist))
|
||||
.map(|dist| DistanceFormatter::from(dist).format(FormatOption::Abbreviated))
|
||||
.unwrap_or("".to_owned()),
|
||||
)
|
||||
.build(),
|
||||
|
@ -87,7 +84,9 @@ pub fn time_distance_detail(type_: ft_core::RecordType, record: ft_core::TimeDis
|
|||
.label(
|
||||
record
|
||||
.duration
|
||||
.map(|duration| format!("{}", duration))
|
||||
.map(|duration| {
|
||||
DurationFormatter::from(duration).format(FormatOption::Abbreviated)
|
||||
})
|
||||
.unwrap_or("".to_owned()),
|
||||
)
|
||||
.build(),
|
||||
|
|
|
@ -14,8 +14,10 @@ General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::{app::App, types::WeightFormatter};
|
||||
use dimensioned::si;
|
||||
use crate::{
|
||||
app::App,
|
||||
types::{DistanceFormatter, DurationFormatter, WeightFormatter},
|
||||
};
|
||||
use emseries::{Record, RecordId, Recordable};
|
||||
use ft_core::{RecordType, TimeDistance, TraxRecord};
|
||||
use std::{
|
||||
|
@ -166,9 +168,9 @@ impl DayDetailViewModel {
|
|||
*record = Some(new_record);
|
||||
}
|
||||
|
||||
pub fn biking_summary(&self) -> (si::Meter<f64>, si::Second<f64>) {
|
||||
pub fn biking_summary(&self) -> (DistanceFormatter, DurationFormatter) {
|
||||
self.records.read().unwrap().iter().fold(
|
||||
(0. * si::M, 0. * si::S),
|
||||
(DistanceFormatter::default(), DurationFormatter::default()),
|
||||
|(acc_distance, acc_duration), (_, record)| match record.data() {
|
||||
Some(Record {
|
||||
data:
|
||||
|
@ -178,11 +180,11 @@ impl DayDetailViewModel {
|
|||
..
|
||||
}) => (
|
||||
distance
|
||||
.map(|distance| acc_distance + distance)
|
||||
.map(|distance| acc_distance + DistanceFormatter::from(distance))
|
||||
.unwrap_or(acc_distance),
|
||||
(duration
|
||||
.map(|duration| acc_duration + duration)
|
||||
.unwrap_or(acc_duration)),
|
||||
duration
|
||||
.map(|duration| acc_duration + DurationFormatter::from(duration))
|
||||
.unwrap_or(acc_duration),
|
||||
),
|
||||
|
||||
_ => (acc_distance, acc_duration),
|
||||
|
|
Loading…
Reference in New Issue