Render and be able to edit bike rides (and sorta other time distance workouts) #169
|
@ -17,10 +17,13 @@ You should have received a copy of the GNU General Public License along with Fit
|
||||||
// use chrono::NaiveDate;
|
// use chrono::NaiveDate;
|
||||||
// use ft_core::TraxRecord;
|
// use ft_core::TraxRecord;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{steps_editor, weight_field, ActionGroup, Steps, WeightLabel},
|
components::{
|
||||||
|
steps_editor, time_distance_summary, weight_field, ActionGroup, Steps, WeightLabel,
|
||||||
|
},
|
||||||
types::WeightFormatter,
|
types::WeightFormatter,
|
||||||
view_models::DayDetailViewModel,
|
view_models::DayDetailViewModel,
|
||||||
};
|
};
|
||||||
|
use ft_core::TimeDistanceActivity;
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
use gtk::{prelude::*, subclass::prelude::*};
|
use gtk::{prelude::*, subclass::prelude::*};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -97,8 +100,12 @@ impl DaySummary {
|
||||||
label.set_label(&format!("{} steps", s));
|
label.set_label(&format!("{} steps", s));
|
||||||
}
|
}
|
||||||
row.append(&label);
|
row.append(&label);
|
||||||
|
|
||||||
self.append(&row);
|
self.append(&row);
|
||||||
|
|
||||||
|
let biking_summary = view_model.time_distance_summary(TimeDistanceActivity::BikeRide);
|
||||||
|
if let Some(label) = time_distance_summary(biking_summary.0, biking_summary.1) {
|
||||||
|
self.append(&label);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ mod text_entry;
|
||||||
pub use text_entry::{weight_field, TextEntry};
|
pub use text_entry::{weight_field, TextEntry};
|
||||||
|
|
||||||
mod time_distance;
|
mod time_distance;
|
||||||
pub use time_distance::TimeDistanceView;
|
pub use time_distance::{time_distance_summary, TimeDistanceView};
|
||||||
|
|
||||||
mod weight;
|
mod weight;
|
||||||
pub use weight::WeightLabel;
|
pub use weight::WeightLabel;
|
||||||
|
|
|
@ -17,11 +17,33 @@ You should have received a copy of the GNU General Public License along with Fit
|
||||||
// use crate::components::{EditView, ParseError, TextEntry};
|
// use crate::components::{EditView, ParseError, TextEntry};
|
||||||
// use chrono::{Local, NaiveDate};
|
// use chrono::{Local, NaiveDate};
|
||||||
// use dimensioned::si;
|
// use dimensioned::si;
|
||||||
|
use dimensioned::si;
|
||||||
use ft_core::TimeDistance;
|
use ft_core::TimeDistance;
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
use gtk::{prelude::*, subclass::prelude::*};
|
use gtk::{prelude::*, subclass::prelude::*};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
pub fn time_distance_summary(
|
||||||
|
distance: si::Meter<f64>,
|
||||||
|
duration: si::Second<f64>,
|
||||||
|
) -> Option<gtk::Label> {
|
||||||
|
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.
|
||||||
|
)),
|
||||||
|
(true, false) => Some(format!(
|
||||||
|
"{} kilometers of biking",
|
||||||
|
distance.value_unsafe / 1000.
|
||||||
|
)),
|
||||||
|
(false, true) => Some(format!("{} seconds of biking", duration.value_unsafe / 60.)),
|
||||||
|
(false, false) => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
text.map(|text| gtk::Label::new(Some(&text)))
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TimeDistanceViewPrivate {
|
pub struct TimeDistanceViewPrivate {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|
|
@ -36,16 +36,6 @@ enum RecordState<T: Clone + Recordable> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + emseries::Recordable> RecordState<T> {
|
impl<T: Clone + emseries::Recordable> RecordState<T> {
|
||||||
#[allow(unused)]
|
|
||||||
fn id(&self) -> Option<&RecordId> {
|
|
||||||
match self {
|
|
||||||
RecordState::Original(ref r) => Some(&r.id),
|
|
||||||
RecordState::New(ref r) => None,
|
|
||||||
RecordState::Updated(ref r) => Some(&r.id),
|
|
||||||
RecordState::Deleted(ref r) => Some(&r.id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn exists(&self) -> bool {
|
fn exists(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
RecordState::Original(_) => true,
|
RecordState::Original(_) => true,
|
||||||
|
@ -55,6 +45,16 @@ impl<T: Clone + emseries::Recordable> RecordState<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
fn data(&self) -> Option<&Record<T>> {
|
||||||
|
match self {
|
||||||
|
RecordState::Original(ref r) => Some(r),
|
||||||
|
RecordState::New(ref r) => None,
|
||||||
|
RecordState::Updated(ref r) => Some(r),
|
||||||
|
RecordState::Deleted(ref r) => Some(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_value(&mut self, value: T) {
|
fn set_value(&mut self, value: T) {
|
||||||
*self = match self {
|
*self = match self {
|
||||||
RecordState::Original(r) => RecordState::Updated(Record {
|
RecordState::Original(r) => RecordState::Updated(Record {
|
||||||
|
|
Loading…
Reference in New Issue