/* 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 . */ //! ActionGroup and related structures use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; #[derive(Default)] pub struct ActionGroupPrivate; #[glib::object_subclass] impl ObjectSubclass for ActionGroupPrivate { const NAME: &'static str = "ActionGroup"; type Type = ActionGroup; type ParentType = gtk::Box; } impl ObjectImpl for ActionGroupPrivate {} impl WidgetImpl for ActionGroupPrivate {} impl BoxImpl for ActionGroupPrivate {} glib::wrapper! { pub struct ActionGroup(ObjectSubclass) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable; } impl ActionGroup { fn new(builder: ActionGroupBuilder) -> Self { let s: Self = Object::builder().build(); s.set_orientation(builder.orientation); let primary_button = builder.primary_action.button(); let secondary_button = builder.secondary_action.map(|action| action.button()); let tertiary_button = builder.tertiary_action.map(|action| action.button()); if let Some(button) = tertiary_button { s.append(&button); } s.set_halign(gtk::Align::End); if let Some(button) = secondary_button { s.append(&button); } s.append(&primary_button); s } pub fn builder() -> ActionGroupBuilder { ActionGroupBuilder { orientation: gtk::Orientation::Horizontal, primary_action: Action { label: "Ok".to_owned(), action: Box::new(|| {}), }, secondary_action: None, tertiary_action: None, } } } struct Action { label: String, action: Box, } impl Action { fn button(self) -> gtk::Button { let button = gtk::Button::builder().label(self.label).build(); button.connect_clicked(move |_| (self.action)()); button } } pub struct ActionGroupBuilder { orientation: gtk::Orientation, primary_action: Action, secondary_action: Option, tertiary_action: Option, } impl ActionGroupBuilder { pub fn orientation(mut self, orientation: gtk::Orientation) -> Self { self.orientation = orientation; self } pub fn primary_action(mut self, label: &str, action: A) -> Self where A: Fn() + 'static, { self.primary_action = Action { label: label.to_owned(), action: Box::new(action), }; self } pub fn secondary_action(mut self, label: &str, action: A) -> Self where A: Fn() + 'static, { self.secondary_action = Some(Action { label: label.to_owned(), action: Box::new(action), }); self } pub fn tertiary_action(mut self, label: &str, action: A) -> Self where A: Fn() + 'static, { self.tertiary_action = Some(Action { label: label.to_owned(), action: Box::new(action), }); self } pub fn build(self) -> ActionGroup { ActionGroup::new(self) } }