diff --git a/fitnesstrax/app/src/components/day.rs b/fitnesstrax/app/src/components/day.rs
index b121a4c..8c2321a 100644
--- a/fitnesstrax/app/src/components/day.rs
+++ b/fitnesstrax/app/src/components/day.rs
@@ -17,7 +17,10 @@ You should have received a copy of the GNU General Public License along with Fit
// use chrono::NaiveDate;
// use ft_core::TraxRecord;
use crate::{
- components::{steps_editor, time_distance_summary, weight_editor, ActionGroup, Steps, Weight},
+ components::{
+ steps_editor, text_entry::distance_field, time_distance_summary, weight_editor,
+ ActionGroup, Steps, Weight,
+ },
view_models::DayDetailViewModel,
};
use dimensioned::si;
diff --git a/fitnesstrax/app/src/components/mod.rs b/fitnesstrax/app/src/components/mod.rs
index 858f7d9..7485059 100644
--- a/fitnesstrax/app/src/components/mod.rs
+++ b/fitnesstrax/app/src/components/mod.rs
@@ -27,7 +27,9 @@ mod steps;
pub use steps::{steps_editor, Steps};
mod text_entry;
-pub use text_entry::{ParseError, TextEntry};
+pub use text_entry::{
+ distance_field, duration_field, time_field, weight_field, ParseError, TextEntry,
+};
mod time_distance;
pub use time_distance::{time_distance_detail, time_distance_summary};
diff --git a/fitnesstrax/app/src/components/text_entry.rs b/fitnesstrax/app/src/components/text_entry.rs
index 12c0a6c..c3fc96b 100644
--- a/fitnesstrax/app/src/components/text_entry.rs
+++ b/fitnesstrax/app/src/components/text_entry.rs
@@ -14,6 +14,7 @@ General Public License for more details.
You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see .
*/
+use dimensioned::si;
use gtk::prelude::*;
use std::{cell::RefCell, rc::Rc};
@@ -27,7 +28,6 @@ type Parser = dyn Fn(&str) -> Result;
pub struct TextEntry {
value: Rc>>,
widget: gtk::Entry,
- #[allow(unused)]
renderer: Rc>,
parser: Rc>,
}
@@ -109,3 +109,67 @@ impl TextEntry {
self.widget.clone().upcast::()
}
}
+
+pub fn weight_field(
+ weight: Option>,
+ on_update: OnUpdate,
+) -> TextEntry>
+where
+ OnUpdate: Fn(si::Kilogram) + 'static,
+{
+ TextEntry::new(
+ "0 kg",
+ weight,
+ |val: &si::Kilogram| val.to_string(),
+ move |v: &str| {
+ let new_weight = v.parse::().map(|w| w * si::KG).map_err(|_| ParseError);
+ match new_weight {
+ Ok(w) => {
+ on_update(w);
+ Ok(w)
+ }
+ Err(err) => Err(err),
+ }
+ },
+ )
+}
+
+pub fn time_field(value: chrono::NaiveTime) -> TextEntry {
+ TextEntry::new(
+ "hh:mm",
+ Some(value),
+ |v| v.format("%H:%M").to_string(),
+ |s| chrono::NaiveTime::parse_from_str(s, "%H:%M").map_err(|_| ParseError),
+ )
+}
+
+pub fn distance_field(value: Option>) -> TextEntry> {
+ TextEntry::new(
+ "0 km",
+ value,
+ |v| format!("{} km", v.value_unsafe / 1000.),
+ |s| {
+ let digits = take_digits(s.to_owned());
+ let value = digits.parse::().map_err(|_| ParseError)?;
+ println!("value: {}", value);
+ Ok(value * 1000. * si::M)
+ },
+ )
+}
+
+pub fn duration_field(value: Option>) -> TextEntry> {
+ TextEntry::new(
+ "0 minutes",
+ value,
+ |v| format!("{} minutes", v.value_unsafe / 1000.),
+ |s| {
+ let digits = take_digits(s.to_owned());
+ let value = digits.parse::().map_err(|_| ParseError)?;
+ Ok(value * 60. * si::S)
+ },
+ )
+}
+
+fn take_digits(s: String) -> String {
+ s.chars().take_while(|t| t.is_digit(10)).collect::()
+}
diff --git a/fitnesstrax/app/src/components/time_distance.rs b/fitnesstrax/app/src/components/time_distance.rs
index 201b284..f7fe9d7 100644
--- a/fitnesstrax/app/src/components/time_distance.rs
+++ b/fitnesstrax/app/src/components/time_distance.rs
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with Fit
// use crate::components::{EditView, ParseError, TextEntry};
// use chrono::{Local, NaiveDate};
// use dimensioned::si;
+use crate::components::distance_field;
use dimensioned::si;
use ft_core::{RecordType, TimeDistance};
use glib::Object;
@@ -102,5 +103,54 @@ pub fn time_distance_detail(type_: ft_core::RecordType, record: ft_core::TimeDis
)
.build(),
);
+
layout
}
+
+#[derive(Default)]
+pub struct TimeDistanceEditPrivate {
+ type_: RefCell