diff --git a/outlay-gtk/src/main.rs b/outlay-gtk/src/main.rs index 9dbb320..fa5ebab 100644 --- a/outlay-gtk/src/main.rs +++ b/outlay-gtk/src/main.rs @@ -1,3 +1,5 @@ +mod window; + use adw::prelude::*; use adw::Application; @@ -13,12 +15,6 @@ fn main() { } fn build_ui(app: &Application) { - let window = adw::ApplicationWindow::builder() - .application(app) - .title("Outlay") - .default_width(900) - .default_height(600) - .build(); - - window.present(); + let main_window = window::MainWindow::new(app); + main_window.window.present(); } diff --git a/outlay-gtk/src/window.rs b/outlay-gtk/src/window.rs new file mode 100644 index 0000000..2691737 --- /dev/null +++ b/outlay-gtk/src/window.rs @@ -0,0 +1,122 @@ +use adw::prelude::*; + +pub struct MainWindow { + pub window: adw::ApplicationWindow, + pub split_view: adw::NavigationSplitView, + pub content_stack: gtk::Stack, +} + +struct SidebarItem { + id: &'static str, + label: &'static str, + icon: &'static str, +} + +const SIDEBAR_ITEMS: &[SidebarItem] = &[ + SidebarItem { id: "log", label: "Log", icon: "list-add-symbolic" }, + SidebarItem { id: "history", label: "History", icon: "document-open-recent-symbolic" }, + SidebarItem { id: "charts", label: "Charts", icon: "utilities-system-monitor-symbolic" }, + SidebarItem { id: "budgets", label: "Budgets", icon: "wallet2-symbolic" }, + SidebarItem { id: "recurring", label: "Recurring", icon: "view-refresh-symbolic" }, + SidebarItem { id: "settings", label: "Settings", icon: "emblem-system-symbolic" }, +]; + +impl MainWindow { + pub fn new(app: &adw::Application) -> Self { + let content_stack = gtk::Stack::new(); + content_stack.set_transition_type(gtk::StackTransitionType::Crossfade); + + for item in SIDEBAR_ITEMS { + let page = adw::StatusPage::builder() + .title(item.label) + .icon_name(item.icon) + .build(); + content_stack.add_named(&page, Some(item.id)); + } + + let sidebar_list = gtk::ListBox::new(); + sidebar_list.set_selection_mode(gtk::SelectionMode::Single); + sidebar_list.add_css_class("navigation-sidebar"); + + for item in SIDEBAR_ITEMS { + let row = Self::make_sidebar_row(item); + sidebar_list.append(&row); + } + + let content_stack_ref = content_stack.clone(); + sidebar_list.connect_row_selected(move |_, row| { + if let Some(row) = row { + let idx = row.index() as usize; + if idx < SIDEBAR_ITEMS.len() { + content_stack_ref.set_visible_child_name(SIDEBAR_ITEMS[idx].id); + } + } + }); + + // Select the first row by default + if let Some(first_row) = sidebar_list.row_at_index(0) { + sidebar_list.select_row(Some(&first_row)); + } + + let sidebar_scroll = gtk::ScrolledWindow::builder() + .hscrollbar_policy(gtk::PolicyType::Never) + .vexpand(true) + .child(&sidebar_list) + .build(); + + let sidebar_toolbar = adw::ToolbarView::new(); + sidebar_toolbar.add_top_bar(&adw::HeaderBar::new()); + sidebar_toolbar.set_content(Some(&sidebar_scroll)); + + let sidebar_page = adw::NavigationPage::builder() + .title("Outlay") + .child(&sidebar_toolbar) + .build(); + + let content_toolbar = adw::ToolbarView::new(); + content_toolbar.add_top_bar(&adw::HeaderBar::new()); + content_toolbar.set_content(Some(&content_stack)); + + let content_page = adw::NavigationPage::builder() + .title("Outlay") + .child(&content_toolbar) + .build(); + + let split_view = adw::NavigationSplitView::new(); + split_view.set_sidebar(Some(&sidebar_page)); + split_view.set_content(Some(&content_page)); + + let window = adw::ApplicationWindow::builder() + .application(app) + .title("Outlay") + .default_width(900) + .default_height(600) + .content(&split_view) + .build(); + + MainWindow { + window, + split_view, + content_stack, + } + } + + fn make_sidebar_row(item: &SidebarItem) -> gtk::ListBoxRow { + let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 12); + hbox.set_margin_top(8); + hbox.set_margin_bottom(8); + hbox.set_margin_start(12); + hbox.set_margin_end(12); + + let icon = gtk::Image::from_icon_name(item.icon); + let label = gtk::Label::new(Some(item.label)); + label.set_halign(gtk::Align::Start); + + hbox.append(&icon); + hbox.append(&label); + + let row = gtk::ListBoxRow::new(); + row.set_child(Some(&hbox)); + row + } +}