diff --git a/fitnesstrax/app/src/components/day.rs b/fitnesstrax/app/src/components/day.rs index 25a4b5b..066b0f1 100644 --- a/fitnesstrax/app/src/components/day.rs +++ b/fitnesstrax/app/src/components/day.rs @@ -1,5 +1,5 @@ /* -Copyright 2023, Savanni D'Gerinel +Copyright 2023-2024, Savanni D'Gerinel This file is part of FitnessTrax. @@ -22,6 +22,8 @@ use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; use std::cell::RefCell; +use super::weight::WeightEdit; + pub struct DaySummaryPrivate { date: gtk::Label, weight: RefCell>, @@ -119,10 +121,17 @@ glib::wrapper! { } impl CommandRow { - fn new() -> Self { + fn new(on_edit: OnEdit) -> Self + where + OnEdit: Fn() + 'static, + { let s: Self = Object::builder().build(); s.set_halign(gtk::Align::End); - s.append(>k::Button::builder().label("Edit").build()); + + let edit_button = gtk::Button::builder().label("Edit").build(); + edit_button.connect_clicked(move |_| on_edit()); + s.append(&edit_button); + s } } @@ -159,21 +168,19 @@ glib::wrapper! { } impl DayDetail { - pub fn new( + pub fn new( date: chrono::NaiveDate, records: Vec>, - on_put_record: PutRecordFn, - on_update_record: UpdateRecordFn, + on_edit: OnEdit, ) -> Self where - PutRecordFn: Fn(ft_core::TraxRecord) + 'static, - UpdateRecordFn: Fn(Record) + 'static, + OnEdit: Fn() + 'static, { let s: Self = Object::builder().build(); s.set_orientation(gtk::Orientation::Vertical); s.set_hexpand(true); - s.append(&CommandRow::new()); + s.append(&CommandRow::new(on_edit)); /* let click_controller = gtk::GestureClick::new(); @@ -199,18 +206,8 @@ impl DayDetail { }); let weight_view = match weight_record { - Some((id, data)) => Weight::new(Some(data.clone()), move |weight| { - on_update_record(Record { - id: id.clone(), - data: ft_core::TraxRecord::Weight(ft_core::Weight { date, weight }), - }) - }), - None => Weight::new(None, move |weight| { - on_put_record(ft_core::TraxRecord::Weight(ft_core::Weight { - date, - weight, - })); - }), + Some((id, data)) => Weight::new(Some(data.clone())), + None => Weight::new(None), }; s.append(&weight_view.widget()); @@ -261,3 +258,77 @@ impl DayDetail { s } } + +pub struct DayEditPrivate { + date: gtk::Label, + weight: WeightEdit, +} + +impl Default for DayEditPrivate { + fn default() -> Self { + Self { + date: gtk::Label::new(None), + weight: WeightEdit::new(None), + } + } +} + +#[glib::object_subclass] +impl ObjectSubclass for DayEditPrivate { + const NAME: &'static str = "DayEdit"; + type Type = DayEdit; + type ParentType = gtk::Box; +} + +impl ObjectImpl for DayEditPrivate {} +impl WidgetImpl for DayEditPrivate {} +impl BoxImpl for DayEditPrivate {} + +glib::wrapper! { + pub struct DayEdit(ObjectSubclass) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable; +} + +impl DayEdit { + pub fn new( + date: chrono::NaiveDate, + records: Vec>, + on_put_record: PutRecordFn, + on_update_record: UpdateRecordFn, + ) -> Self + where + PutRecordFn: Fn(ft_core::TraxRecord) + 'static, + UpdateRecordFn: Fn(Record) + 'static, + { + let s: Self = Object::builder().build(); + + /*, move |weight| { + on_update_record(Record { + id: id.clone(), + data: ft_core::TraxRecord::Weight(ft_core::Weight { date, weight }), + }) + }*/ + + /*, move |weight| { + on_put_record(ft_core::TraxRecord::Weight(ft_core::Weight { + date, + weight, + })); + }*/ + + let weight_record = records.iter().find_map(|record| match record { + Record { + id, + data: ft_core::TraxRecord::Weight(record), + } => Some((id.clone(), record.clone())), + _ => None, + }); + + let weight_view = match weight_record { + Some((_id, data)) => WeightEdit::new(Some(data.clone())), + None => WeightEdit::new(None), + }; + s.append(&weight_view.widget()); + + s + } +} diff --git a/fitnesstrax/app/src/components/mod.rs b/fitnesstrax/app/src/components/mod.rs index fbc4e24..b5adeff 100644 --- a/fitnesstrax/app/src/components/mod.rs +++ b/fitnesstrax/app/src/components/mod.rs @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License along with Fit */ mod day; -pub use day::{DayDetail, DaySummary}; +pub use day::{DayDetail, DayEdit, DaySummary}; mod edit_view; pub use edit_view::EditView; diff --git a/fitnesstrax/app/src/components/weight.rs b/fitnesstrax/app/src/components/weight.rs index 25c3f56..69db27e 100644 --- a/fitnesstrax/app/src/components/weight.rs +++ b/fitnesstrax/app/src/components/weight.rs @@ -226,13 +226,7 @@ pub struct Weight { } impl Weight { - pub fn new( - weight: Option, - on_edit_finished: OnEditFinished, - ) -> Self - where - OnEditFinished: Fn(si::Kilogram) + 'static, - { + pub fn new(weight: Option) -> Self { let label = gtk::Label::builder() .css_classes(["card", "weight-view"]) .can_focus(true) @@ -250,3 +244,28 @@ impl Weight { self.label.clone().upcast() } } + +pub struct WeightEdit { + entry: TextEntry>, +} + +impl WeightEdit { + pub fn new(weight: Option) -> Self { + Self { + entry: TextEntry::new( + "0 kg", + weight.map(|w| w.weight), + |val: &si::Kilogram| val.to_string(), + |v: &str| v.parse::().map(|w| w * si::KG).map_err(|_| ParseError), + ), + } + } + + pub fn value(&self) -> Option> { + self.entry.value() + } + + pub fn widget(&self) -> gtk::Widget { + self.entry.widget() + } +} diff --git a/fitnesstrax/app/src/views/day_detail_view.rs b/fitnesstrax/app/src/views/day_detail_view.rs index 4c68304..65bc114 100644 --- a/fitnesstrax/app/src/views/day_detail_view.rs +++ b/fitnesstrax/app/src/views/day_detail_view.rs @@ -16,16 +16,20 @@ You should have received a copy of the GNU General Public License along with Fit use crate::{ app::App, - components::{DayDetail, Singleton, SingletonImpl}, + components::{DayDetail, DayEdit, Singleton, SingletonImpl}, }; use emseries::Record; use ft_core::TraxRecord; use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; +use std::cell::RefCell; #[derive(Default)] pub struct DayDetailViewPrivate { + app: RefCell>, container: Singleton, + date: RefCell, + records: RefCell>>, } #[glib::object_subclass] @@ -48,35 +52,82 @@ impl DayDetailView { pub fn new(date: chrono::NaiveDate, records: Vec>, app: App) -> Self { let s: Self = Object::builder().build(); + *s.imp().date.borrow_mut() = date; + *s.imp().records.borrow_mut() = records; + s.append(&s.imp().container); - s.imp().container.swap(&DayDetail::new( - date, - records, - { - let app = app.clone(); - move |record| { - let app = app.clone(); - glib::spawn_future_local({ - async move { - app.put_record(record).await; - } - }); + /* + s.imp() + .container + .swap(&DayDetail::new(date, records.clone(), { + let s = s.clone(); + let records = records.clone(); + move || { + s.imp().container.swap(&DayEdit::new( + date, + records, + s.on_put_record(), + // s.on_update_record(), + |_| {}, + )) } - }, - { - let app = app.clone(); - move |record| { - let app = app.clone(); - glib::spawn_future_local({ - async move { - app.update_record(record).await; - } - }); - } - }, - )); + })); + */ + + s.view(); s } + + fn view(&self) { + self.imp().container.swap(&DayDetail::new( + self.imp().date.borrow().clone(), + self.imp().records.borrow().clone(), + { + let s = self.clone(); + move || s.edit() + }, + )); + } + + fn edit(&self) { + self.imp().container.swap(&DayEdit::new( + self.imp().date.borrow().clone(), + self.imp().records.borrow().clone(), + |_| {}, + |_| {}, + )); + } + + fn on_put_record(&self) -> Box { + let app = self.imp().app.clone(); + Box::new(move |record| { + let app = app.clone(); + glib::spawn_future_local({ + async move { + match &*app.borrow() { + Some(app) => { + let _ = app.put_record(record).await; + } + None => {} + } + } + }); + }) + } + + /* + fn on_update_record(&self, record: TraxRecord) -> dyn Fn(ft_core::TraxRecord) { + let app = self.imp().app.clone(); + move |record| { + let app = app.clone(); + glib::spawn_future_local({ + async move { + app.update_record(record).await; + } + }); + } + } + */ }