From 8aada1c2fc6eb354d5fb10918a1a26dfe7100ec5 Mon Sep 17 00:00:00 2001 From: Alessandro Date: Sat, 21 Sep 2024 14:34:17 -0700 Subject: [PATCH] Basic Rust layout (#761) * Implement a simple 3 pane layout * Experiment with a bit of a file structure * Create initial sidebar imp --- src/canvas/canvas.rs | 16 +++++++ src/layout/mod.rs | 17 ++++++++ src/layout/sidebar/layers.rs | 48 +++++++++++++++++++++ src/layout/sidebar/mod.rs | 18 ++++++++ src/layout/sidebar/options.rs | 48 +++++++++++++++++++++ src/main.rs | 1 + src/window.rs | 78 +++++++++++++++++++++++++---------- 7 files changed, 205 insertions(+), 21 deletions(-) create mode 100644 src/canvas/canvas.rs create mode 100644 src/layout/mod.rs create mode 100644 src/layout/sidebar/layers.rs create mode 100644 src/layout/sidebar/mod.rs create mode 100644 src/layout/sidebar/options.rs diff --git a/src/canvas/canvas.rs b/src/canvas/canvas.rs new file mode 100644 index 00000000..d9f3f6ef --- /dev/null +++ b/src/canvas/canvas.rs @@ -0,0 +1,16 @@ +/** + * This file is part of Akira. + * + * Copyright (c) 2024 Alessandro Castellani + * + * Akira 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. + * + * Akira 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 + * Akira. If not, see . + */ diff --git a/src/layout/mod.rs b/src/layout/mod.rs new file mode 100644 index 00000000..01f5ade2 --- /dev/null +++ b/src/layout/mod.rs @@ -0,0 +1,17 @@ +/** + * This file is part of Akira. + * + * Copyright (c) 2024 Alessandro Castellani + * + * Akira 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. + * + * Akira 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 + * Akira. If not, see . + */ +pub mod sidebar; diff --git a/src/layout/sidebar/layers.rs b/src/layout/sidebar/layers.rs new file mode 100644 index 00000000..d8c01b52 --- /dev/null +++ b/src/layout/sidebar/layers.rs @@ -0,0 +1,48 @@ +/** + * This file is part of Akira. + * + * Copyright (c) 2024 Alessandro Castellani + * + * Akira 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. + * + * Akira 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 + * Akira. If not, see . + */ +use gtk::glib; +use gtk::subclass::prelude::*; + +mod imp { + use super::*; + + #[derive(Debug, Default)] + pub struct Layers {} + + #[glib::object_subclass] + impl ObjectSubclass for Layers { + const NAME: &'static str = "Layers"; + type Type = super::Layers; + type ParentType = gtk::Grid; + } + + impl ObjectImpl for Layers {} + impl WidgetImpl for Layers {} + impl GridImpl for Layers {} +} + +glib::wrapper! { + pub struct Layers(ObjectSubclass) @extends gtk::Widget, gtk::Grid; +} + +impl Default for Layers { + fn default() -> Self { + glib::Object::builder() + .property("width-request", 200) + .build() + } +} diff --git a/src/layout/sidebar/mod.rs b/src/layout/sidebar/mod.rs new file mode 100644 index 00000000..72c8e998 --- /dev/null +++ b/src/layout/sidebar/mod.rs @@ -0,0 +1,18 @@ +/** + * This file is part of Akira. + * + * Copyright (c) 2024 Alessandro Castellani + * + * Akira 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. + * + * Akira 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 + * Akira. If not, see . + */ +pub mod layers; +pub mod options; diff --git a/src/layout/sidebar/options.rs b/src/layout/sidebar/options.rs new file mode 100644 index 00000000..2ca2357f --- /dev/null +++ b/src/layout/sidebar/options.rs @@ -0,0 +1,48 @@ +/** + * This file is part of Akira. + * + * Copyright (c) 2024 Alessandro Castellani + * + * Akira 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. + * + * Akira 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 + * Akira. If not, see . + */ +use gtk::glib; +use gtk::subclass::prelude::*; + +mod imp { + use super::*; + + #[derive(Debug, Default)] + pub struct Options {} + + #[glib::object_subclass] + impl ObjectSubclass for Options { + const NAME: &'static str = "Options"; + type Type = super::Options; + type ParentType = gtk::Grid; + } + + impl ObjectImpl for Options {} + impl WidgetImpl for Options {} + impl GridImpl for Options {} +} + +glib::wrapper! { + pub struct Options(ObjectSubclass) @extends gtk::Widget, gtk::Grid; +} + +impl Default for Options { + fn default() -> Self { + glib::Object::builder() + .property("width-request", 200) + .build() + } +} diff --git a/src/main.rs b/src/main.rs index b3c27b5e..65a8df23 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ */ mod application; mod config; +mod layout; mod window; use config::{APP_ID, GETTEXT_PACKAGE, LOCALEDIR}; diff --git a/src/window.rs b/src/window.rs index 14932579..f6996fdf 100644 --- a/src/window.rs +++ b/src/window.rs @@ -20,6 +20,7 @@ use gtk::{gio, gio::Settings, glib, prelude::*, ApplicationWindow}; use once_cell::sync::OnceCell; use crate::config::APP_ID; +use crate::layout::sidebar::*; mod imp { use super::*; @@ -44,27 +45,8 @@ mod imp { obj.setup_settings(); obj.load_window_size(); - - let mode_switch = granite::ModeSwitch::builder() - .primary_icon_name("display-brightness-symbolic") - .secondary_icon_name("weather-clear-night-symbolic") - .primary_icon_tooltip_text(gettext("Light Background")) - .secondary_icon_tooltip_text(gettext("Dark Background")) - .valign(gtk::Align::Center) - .build(); - - let gtk_settings = gtk::Settings::default().expect("Unable to get GtkSettings object"); - mode_switch - .bind_property("active", >k_settings, "gtk-application-prefer-dark-theme") - .bidirectional() - .build(); - - let header_bar = gtk::HeaderBar::builder().show_title_buttons(true).build(); - - header_bar.style_context().add_class("default-decoration"); - header_bar.pack_end(&mode_switch); - - obj.set_titlebar(Some(&header_bar)); + obj.build_headerbar(); + obj.build_body(); } } @@ -132,6 +114,60 @@ impl AppWindow { self.maximize(); } } + + fn build_headerbar(&self) { + let mode_switch = granite::ModeSwitch::builder() + .primary_icon_name("display-brightness-symbolic") + .secondary_icon_name("weather-clear-night-symbolic") + .primary_icon_tooltip_text(gettext("Light Background")) + .secondary_icon_tooltip_text(gettext("Dark Background")) + .valign(gtk::Align::Center) + .build(); + + let gtk_settings = gtk::Settings::default().expect("Unable to get GtkSettings object"); + mode_switch + .bind_property("active", >k_settings, "gtk-application-prefer-dark-theme") + .bidirectional() + .build(); + + let header_bar = gtk::HeaderBar::builder().show_title_buttons(true).build(); + + header_bar.add_css_class("default-decoration"); + header_bar.pack_end(&mode_switch); + + self.set_titlebar(Some(&header_bar)); + } + + fn build_body(&self) { + let main_area = gtk::Grid::builder() + .orientation(gtk::Orientation::Vertical) + .build(); + let options = options::Options::default(); + let layers = layers::Layers::default(); + + let pane1 = gtk::Paned::builder() + .orientation(gtk::Orientation::Horizontal) + .resize_start_child(false) + .resize_end_child(true) + .shrink_start_child(false) + .shrink_end_child(false) + .build(); + let pane2 = gtk::Paned::builder() + .orientation(gtk::Orientation::Horizontal) + .resize_start_child(true) + .resize_end_child(false) + .shrink_start_child(true) + .shrink_end_child(false) + .build(); + + pane1.set_end_child(Some(&pane2)); + pane1.set_start_child(Some(&options)); + + pane2.set_start_child(Some(&main_area)); + pane2.set_end_child(Some(&layers)); + + self.set_child(Some(&pane1)); + } } #[cfg(test)]