From e87b332705401e52c3c697eb3921f21a9566eff4 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sat, 10 Feb 2024 11:38:25 -0500 Subject: [PATCH] Start building an internally editable date field --- fitnesstrax/app/src/components/date_field.rs | 75 ++++++++++++++++++++ fitnesstrax/app/src/components/mod.rs | 3 + fitnesstrax/app/src/views/historical_view.rs | 23 +++++- 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 fitnesstrax/app/src/components/date_field.rs diff --git a/fitnesstrax/app/src/components/date_field.rs b/fitnesstrax/app/src/components/date_field.rs new file mode 100644 index 0000000..6cc5335 --- /dev/null +++ b/fitnesstrax/app/src/components/date_field.rs @@ -0,0 +1,75 @@ +/* +Copyright 2024, Savanni D'Gerinel + +This file is part of FitnessTrax. + +FitnessTrax is free software: you can redistribute it and/or modify it under the terms of the GNU +General Public License as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +FitnessTrax is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +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 crate::types::ParseError; +use chrono::Datelike; +use gtk::prelude::*; +use std::{cell::RefCell, rc::Rc}; + +#[derive(Clone)] +pub struct DateField { + value: Rc>, + buffer: gtk::TextBuffer, + widget: gtk::TextView, +} + +impl DateField { + pub fn new(date: chrono::NaiveDate) -> Self { + let buffer = gtk::TextBuffer::new(None); + let tag = buffer.create_tag( + Some("placeholder"), + &[("foreground", &String::from("grey"))], + ); + + buffer.set_text("regular text placeholder text"); + let (start, end) = buffer.bounds(); + let mut placeholder_start = start.clone(); + placeholder_start.forward_chars(13); + + let placeholder_markup = buffer.tag_table().lookup("placeholder").unwrap(); + buffer.apply_tag(&placeholder_markup, &placeholder_start, &end); + + let widget = gtk::TextView::builder() + .buffer(&buffer) + .editable(true) + .can_focus(true) + .height_request(50) + .width_request(200) + .build(); + + let s = Self { + value: Rc::new(RefCell::new(date)), + buffer, + widget, + }; + + s.widget.buffer().connect_text_notify({ + let s = s.clone(); + move |buffer| s.on_update(buffer) + }); + + s + } + + pub fn widget(&self) -> gtk::Widget { + self.widget.clone().upcast::() + } + + fn on_update(&self, buffer: >k::TextBuffer) { + let (start, end) = buffer.bounds(); + println!("[on_update] {}", buffer.text(&start, &end, true)); + } +} diff --git a/fitnesstrax/app/src/components/mod.rs b/fitnesstrax/app/src/components/mod.rs index c1da4fd..d2f9d26 100644 --- a/fitnesstrax/app/src/components/mod.rs +++ b/fitnesstrax/app/src/components/mod.rs @@ -21,6 +21,9 @@ pub use action_group::ActionGroup; mod day; pub use day::{DayDetail, DayEdit, DaySummary}; +mod date_field; +pub use date_field::DateField; + mod singleton; pub use singleton::{Singleton, SingletonImpl}; diff --git a/fitnesstrax/app/src/views/historical_view.rs b/fitnesstrax/app/src/views/historical_view.rs index ead6184..a7accc4 100644 --- a/fitnesstrax/app/src/views/historical_view.rs +++ b/fitnesstrax/app/src/views/historical_view.rs @@ -15,7 +15,10 @@ You should have received a copy of the GNU General Public License along with Fit */ use crate::{ - app::App, components::DaySummary, types::DayInterval, view_models::DayDetailViewModel, + app::App, + components::{DateField, DaySummary}, + types::DayInterval, + view_models::DayDetailViewModel, }; use glib::Object; @@ -106,6 +109,22 @@ impl HistoricalView { *s.imp().app.borrow_mut() = Some(app); + let date_row = gtk::Box::builder() + .orientation(gtk::Orientation::Horizontal) + .build(); + date_row.append(&DateField::new(interval.start).widget()); + date_row.append(>k::Label::new(Some("to"))); + date_row.append(&DateField::new(interval.end).widget()); + + let quick_picker = gtk::Box::builder() + .orientation(gtk::Orientation::Horizontal) + .build(); + quick_picker.append(>k::Button::builder().label("last week").build()); + quick_picker.append(>k::Button::builder().label("last two weeks").build()); + quick_picker.append(>k::Button::builder().label("last month").build()); + quick_picker.append(>k::Button::builder().label("last six months").build()); + quick_picker.append(>k::Button::builder().label("last year").build()); + let mut model = gio::ListStore::new::(); model.extend(interval.days().map(Date::new)); s.imp() @@ -122,6 +141,8 @@ impl HistoricalView { } }); + s.append(&date_row); + s.append(&quick_picker); s.append(&s.imp().list_view); s