Compare commits
8 Commits
56a8133dd5
...
1d8653a0f5
Author | SHA1 | Date |
---|---|---|
Savanni D'Gerinel | 1d8653a0f5 | |
Savanni D'Gerinel | d0cb3e3b19 | |
Savanni D'Gerinel | e2850e3427 | |
Savanni D'Gerinel | 81ec202abf | |
Savanni D'Gerinel | 504780855c | |
Savanni D'Gerinel | acdf9ec150 | |
Savanni D'Gerinel | 0ebdcd7c2a | |
Savanni D'Gerinel | baf652173c |
|
@ -27,7 +27,7 @@ use std::{
|
||||||
env,
|
env,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
use ui::{welcome_modal, Modal};
|
use ui::welcome_modal;
|
||||||
|
|
||||||
const APP_ID_DEV: &str = "com.luminescent-dreams.fitnesstrax.dev";
|
const APP_ID_DEV: &str = "com.luminescent-dreams.fitnesstrax.dev";
|
||||||
const APP_ID_PROD: &str = "com.luminescent-dreams.fitnesstrax";
|
const APP_ID_PROD: &str = "com.luminescent-dreams.fitnesstrax";
|
||||||
|
@ -48,6 +48,8 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is the view to show if the application has not yet been configured. It will walk the user
|
||||||
|
/// through the most critical setup steps so that we can move on to the other views in the app.
|
||||||
pub struct UnconfiguredViewPrivate {}
|
pub struct UnconfiguredViewPrivate {}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
|
@ -73,14 +75,19 @@ impl UnconfiguredView {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
|
|
||||||
|
// Replace this with the welcome screen that we set up in the fitnesstrax/unconfigured-page
|
||||||
|
// branch.
|
||||||
let label = gtk::Label::builder()
|
let label = gtk::Label::builder()
|
||||||
.label("Database is not configured.")
|
.label("Welcome to FitnessTrax")
|
||||||
.build();
|
.build();
|
||||||
s.append(&label);
|
s.append(&label);
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The historical view will show a window into the main database. It will show some version of
|
||||||
|
/// daily summaries, daily details, and will provide all functions the user may need for editing
|
||||||
|
/// records.
|
||||||
pub struct HistoricalViewPrivate {}
|
pub struct HistoricalViewPrivate {}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
|
@ -114,43 +121,13 @@ impl HistoricalView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// window setup...
|
/// The application window, or the main window, is the main user interface for the app. Almost
|
||||||
// main window with all of its layout
|
/// everything occurs here.
|
||||||
// modals that overlay atop the main window and capture focus
|
|
||||||
// menus
|
|
||||||
// There is more than one view for the main window. There's the view for data entry, then another
|
|
||||||
// view for showing graphs. Then a third view, or maybe a modal, for editing a day.
|
|
||||||
//
|
|
||||||
// So, the ordinary data view is the history the metrics, and the calendar. Scrollable, and items
|
|
||||||
// within the scrolling area can be clicked upon in order to open the edit.
|
|
||||||
//
|
|
||||||
// I don't need to model the whole thing at once. The graphs will be some time out, and so I can
|
|
||||||
// model just the main view, which consists of metrics, the data, and the calendar. Day entries
|
|
||||||
// should be summaries of the day, expandable to the details.
|
|
||||||
//
|
|
||||||
// Then there is the view which notifies the user that the database has not been configured.
|
|
||||||
|
|
||||||
/// These are the possible states of the main application view.
|
|
||||||
enum MainView {
|
|
||||||
/// The application is not configured yet. This is a basic background widget to take up the
|
|
||||||
/// space when there is no data to be shown.
|
|
||||||
Unconfigured(UnconfiguredView),
|
|
||||||
|
|
||||||
/// The Historical view shows a history of records and whatnot.
|
|
||||||
Historical(HistoricalView),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The application window, or the main window, is the main user interface for the app.
|
|
||||||
struct AppWindow {
|
struct AppWindow {
|
||||||
app: App,
|
app: App,
|
||||||
window: adw::ApplicationWindow,
|
window: adw::ApplicationWindow,
|
||||||
overlay: gtk::Overlay,
|
layout: gtk::Box,
|
||||||
|
current_view: RefCell<gtk::Widget>,
|
||||||
current_view: RefCell<MainView>,
|
|
||||||
|
|
||||||
// We have to keep around a reference to the modal so that we know what to remove from the
|
|
||||||
// overlay.
|
|
||||||
modal: RefCell<Option<gtk::Widget>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppWindow {
|
impl AppWindow {
|
||||||
|
@ -167,38 +144,10 @@ impl AppWindow {
|
||||||
.height_request(600)
|
.height_request(600)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// GTK overlays aren't all that well documented. The Overlay object needs to be the
|
|
||||||
// content/child of the window. The main content should then be added to the overlay as
|
|
||||||
// `set_child`. The overlays/modals should be added as `add_overlay` and then removed with
|
|
||||||
// `remove_overlay`.
|
|
||||||
let overlay = gtk::Overlay::new();
|
|
||||||
window.set_content(Some(&overlay));
|
|
||||||
|
|
||||||
let current_view = if app.database.read().unwrap().is_none() {
|
let current_view = if app.database.read().unwrap().is_none() {
|
||||||
let view = UnconfiguredView::new();
|
UnconfiguredView::new().upcast()
|
||||||
/*
|
|
||||||
overlay.set_child(Some(&view));
|
|
||||||
|
|
||||||
// I have to access the overlay directly here because I haven't fully constructed Self
|
|
||||||
// yet, and so I don't have access to `open_modal` yet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
MainView::Unconfigured(view)
|
|
||||||
} else {
|
} else {
|
||||||
let view = HistoricalView::new();
|
HistoricalView::new().upcast()
|
||||||
/*
|
|
||||||
overlay.set_child(Some(&view));
|
|
||||||
*/
|
|
||||||
|
|
||||||
MainView::Historical(view)
|
|
||||||
};
|
|
||||||
|
|
||||||
let s = Self {
|
|
||||||
app,
|
|
||||||
window: window.clone(),
|
|
||||||
overlay,
|
|
||||||
current_view: RefCell::new(current_view),
|
|
||||||
modal: RefCell::new(None),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let stylesheet = String::from_utf8(
|
let stylesheet = String::from_utf8(
|
||||||
|
@ -217,53 +166,38 @@ impl AppWindow {
|
||||||
let context = window.style_context();
|
let context = window.style_context();
|
||||||
context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER);
|
context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER);
|
||||||
|
|
||||||
|
let header = adw::HeaderBar::builder()
|
||||||
|
.title_widget(>k::Label::new(Some("FitnessTrax")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let layout = gtk::Box::builder()
|
||||||
|
.orientation(gtk::Orientation::Vertical)
|
||||||
|
.build();
|
||||||
|
layout.append(&header);
|
||||||
|
layout.append(¤t_view);
|
||||||
|
|
||||||
|
window.set_content(Some(&layout));
|
||||||
window.present();
|
window.present();
|
||||||
|
|
||||||
s.redraw();
|
let s = Self {
|
||||||
|
app,
|
||||||
s
|
window,
|
||||||
|
layout,
|
||||||
/*
|
current_view: RefCell::new(current_view),
|
||||||
let current_view = if app.database.read().unwrap().is_none() {
|
|
||||||
let view = UnconfiguredView::new();
|
|
||||||
overlay.set_child(Some(&view));
|
|
||||||
|
|
||||||
// I have to access the overlay directly here because I haven't fully constructed Self
|
|
||||||
// yet, and so I don't have access to `open_modal` yet.
|
|
||||||
overlay.add_overlay(&welcome_modal(|path| {
|
|
||||||
// When a path gets selected, I want to set the path in the configuration system,
|
|
||||||
// and I want to open the database. After that, this window should be redrawn with
|
|
||||||
// its new state. So the view state also needs to change.
|
|
||||||
println!("path: {}", path.to_str().unwrap())
|
|
||||||
}));
|
|
||||||
|
|
||||||
MainView::Unconfigured(view)
|
|
||||||
} else {
|
|
||||||
let view = HistoricalView::new();
|
|
||||||
overlay.set_child(Some(&view));
|
|
||||||
|
|
||||||
MainView::HistoricalView(view)
|
|
||||||
};
|
};
|
||||||
*/
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
fn redraw(&self) {
|
// Switch views.
|
||||||
match *self.current_view.borrow() {
|
//
|
||||||
MainView::Unconfigured(ref view) => {
|
// This function only replaces the old view with the one which matches the current view state.
|
||||||
self.overlay.set_child(Some(view));
|
// It is responsible for ensuring that the new view goes into the layout in the correct
|
||||||
|
// position.
|
||||||
let modal = welcome_modal(|path| {
|
fn change_view(&self, view: gtk::Widget) {
|
||||||
// When a path gets selected, I want to set the path in the configuration system,
|
let mut current_view = self.current_view.borrow_mut();
|
||||||
// and I want to open the database. After that, this window should be redrawn with
|
self.layout.remove(&*current_view);
|
||||||
// its new state. So the view state also needs to change.
|
*current_view = view;
|
||||||
println!("path: {}", path.to_str().unwrap())
|
self.layout.append(&*current_view);
|
||||||
});
|
|
||||||
|
|
||||||
self.overlay.add_overlay(&modal);
|
|
||||||
*self.modal.borrow_mut() = Some(modal.upcast());
|
|
||||||
}
|
|
||||||
MainView::Historical(ref view) => self.overlay.set_child(Some(view)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,11 +219,6 @@ fn main() {
|
||||||
|
|
||||||
println!("database path: {}", settings.string("series-path"));
|
println!("database path: {}", settings.string("series-path"));
|
||||||
|
|
||||||
let adw_app = adw::Application::builder()
|
|
||||||
.application_id(app_id)
|
|
||||||
.resource_base_path(RESOURCE_BASE_PATH)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let app = App::new();
|
let app = App::new();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue