From 1b765e294a13af1ed72e159ce4507ba5099958d9 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Tue, 30 Jan 2024 20:28:00 +0100 Subject: [PATCH] move headerbar into main window --- src/components/header_bar/header_bar.rs | 180 ------------------------ src/components/header_bar/header_bar.ui | 140 ------------------ src/components/header_bar/mod.rs | 15 -- src/components/mod.rs | 2 - src/components/window/window.rs | 161 ++++++++++++++++----- src/components/window/window.ui | 180 ++++++++++++++++++++---- src/tile/mod.rs | 9 ++ src/tile/tile/mod.rs | 16 +++ src/tile/tile/tile.rs | 47 +++++++ src/tile/tile_header/mod.rs | 1 + src/tile/tile_header/tile_header.rs | 0 src/tile/tile_view/mod.rs | 16 +++ src/tile/tile_view/tile_view.rs | 17 +++ src/tile/zoom_controls/zoom_controls.ui | 2 - 14 files changed, 384 insertions(+), 402 deletions(-) delete mode 100644 src/components/header_bar/header_bar.rs delete mode 100644 src/components/header_bar/header_bar.ui delete mode 100644 src/components/header_bar/mod.rs create mode 100644 src/tile/tile/mod.rs create mode 100644 src/tile/tile/tile.rs create mode 100644 src/tile/tile_header/mod.rs create mode 100644 src/tile/tile_header/tile_header.rs create mode 100644 src/tile/tile_view/mod.rs create mode 100644 src/tile/tile_view/tile_view.rs diff --git a/src/components/header_bar/header_bar.rs b/src/components/header_bar/header_bar.rs deleted file mode 100644 index 8a0b067..0000000 --- a/src/components/header_bar/header_bar.rs +++ /dev/null @@ -1,180 +0,0 @@ -use std::cell::{Cell, RefCell}; - -use adw::subclass::prelude::*; -use glib::clone; -use glib::{self, Properties, StaticTypeExt}; -use gtk::{prelude::*, template_callbacks}; -use tracing::info; - -use crate::settings::{Settings, StylePreference}; -use crate::tile::StyleSwitcher; -use crate::tile::ZoomControls; - -#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] -#[template(resource = "/io/github/vhdirk/Terms/gtk/header_bar.ui")] -#[properties(wrapper_type = super::HeaderBar)] -pub struct HeaderBar { - pub settings: Settings, - - #[template_child] - pub revealer: TemplateChild, - - #[template_child] - pub title_widget: TemplateChild, - - #[template_child] - pub header_bar: TemplateChild, - - #[template_child] - pub header_box: TemplateChild, - - #[property(get, set, construct_only)] - pub tab_bar: RefCell, - - #[template_child] - pub menu_button: TemplateChild, - - #[template_child] - pub style_switcher: TemplateChild, - - #[property(get, set, nullable)] - pub title: RefCell>, - - #[property(get, set)] - pub fullscreened: Cell, - - #[property(get, set, construct, default = 100)] - pub zoom: Cell, - - #[property(get, set, nullable)] - pub overlay: RefCell>, - - #[property(get, set, nullable)] - pub container: RefCell>, -} - -#[glib::object_subclass] -impl ObjectSubclass for HeaderBar { - const NAME: &'static str = "TermsHeaderBar"; - type Type = super::HeaderBar; - type ParentType = adw::Bin; - - fn class_init(klass: &mut Self::Class) { - StyleSwitcher::ensure_type(); - ZoomControls::ensure_type(); - klass.bind_template(); - klass.bind_template_callbacks(); - klass.set_css_name("headerbar"); - } - - fn instance_init(obj: &glib::subclass::InitializingObject) { - obj.init_template(); - } -} - -#[glib::derived_properties] -impl ObjectImpl for HeaderBar { - fn constructed(&self) { - self.parent_constructed(); - - self.setup(); - } -} - -impl WidgetImpl for HeaderBar {} -impl BinImpl for HeaderBar {} - -#[gtk::template_callbacks] -impl HeaderBar { - fn setup(&self) { - self.settings.bind_show_menu_button(&*self.menu_button, "visible").get_only().build(); - - self.obj() - .bind_property("fullscreened", &*self.header_bar, "show-end-title-buttons") - .invert_boolean() - .sync_create() - .build(); - - self.settings.bind_style_preference(&*self.style_switcher, "preference").build(); - - self.settings.bind_show_headerbar(&*self.revealer, "reveal-child").get_only().build(); - - self.revealer.connect_child_revealed_notify(clone!(@weak self as this => move |r| { - this.on_reveal_changed(r.is_child_revealed()); - })); - - self.obj().connect_root_notify(clone!(@weak self as this => move |obj| { - if let Some(window) = obj.root().and_then(|root| root.clone().downcast::().ok()) { - window.bind_property("title", obj, "title").sync_create().build(); - } - })); - - self.set_integrated_tab_bar(); - - self.settings - .connect_headerbar_integrated_tabbar_changed(clone!(@weak self as this => move |_| { - this.set_integrated_tab_bar(); - })); - - self.tab_bar.borrow().connect_view_notify(clone!(@weak self as this => move |tabbar| { - this.set_integrated_tab_bar(); - if let Some(tab_view) = tabbar.view() { - info!("tab view: {:?}", tab_view); - tab_view.connect_n_pages_notify( move |_| { - this.set_integrated_tab_bar(); - }); - } - })); - } - - fn on_reveal_changed(&self, revealed: bool) { - println!("on reveal changed: {:?}", revealed); - } - - fn set_floating(&self, float: bool) { - // if (self.is_floating.get() && float) { - // return; - // } - - // this.setting_header_bar_to_floating = true; - - // if (should_float && this.header_bar_revealer.parent != this.overlay) { - // // ... - // yield this.wait_for_header_bar_animation (); - // this.layout_box.remove (this.header_bar_revealer); - // this.overlay.add_overlay (this.header_bar_revealer); - // } - // else if (!should_float && this.header_bar_revealer.parent != this.layout_box) { - // // ... - // this.overlay.remove_overlay (this.header_bar_revealer); - // this.layout_box.prepend (this.header_bar_revealer); - // } - - // this.setting_header_bar_to_floating = false; - } - - fn set_integrated_tab_bar(&self) { - let tab_bar = self.tab_bar.borrow(); - - if self.settings.headerbar_integrated_tabbar() { - if self.header_bar.title_widget() != Some(tab_bar.clone().into()) { - tab_bar.unparent(); - self.header_bar.set_title_widget(Some(&*tab_bar)); - } - tab_bar.set_halign(gtk::Align::Fill); - tab_bar.set_hexpand(true); - tab_bar.set_autohide(false); - tab_bar.set_can_focus(false); - tab_bar.set_css_classes(&["inline", "integrated"]); - } else { - self.header_bar.set_title_widget(Some(&*self.title_widget)); - self.header_box.append(&*tab_bar); - - tab_bar.set_halign(gtk::Align::Fill); - tab_bar.set_hexpand(true); - tab_bar.set_autohide(true); - tab_bar.set_can_focus(false); - tab_bar.set_css_classes(&[]); - } - } -} diff --git a/src/components/header_bar/header_bar.ui b/src/components/header_bar/header_bar.ui deleted file mode 100644 index 112e532..0000000 --- a/src/components/header_bar/header_bar.ui +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - -
- - style-switcher - -
-
- - zoom-controls - -
-
- - new-tab - New _Tab - win.new-tab - action-disabled - - - new-window - New _Window - app.new-window - action-disabled - -
-
- - _Preferences - win.edit-preferences - -
-
- - About Terms - app.about - - - Quit - app.quit - -
-
- - -
diff --git a/src/components/header_bar/mod.rs b/src/components/header_bar/mod.rs deleted file mode 100644 index bf7a5d6..0000000 --- a/src/components/header_bar/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -mod header_bar; -use header_bar as imp; - -glib::wrapper! { - pub struct HeaderBar(ObjectSubclass) - @extends gtk::Widget, adw::Bin, - @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Actionable; -} - -impl HeaderBar { - pub fn new() -> Self { - let obj: Self = glib::Object::builder().build(); - obj - } -} diff --git a/src/components/mod.rs b/src/components/mod.rs index 9f5f986..4eb1667 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,4 +1,3 @@ -mod header_bar; mod preferences_window; mod process_manager; mod search_toolbar; @@ -12,7 +11,6 @@ mod terminal_tab; mod theme_thumbnail; mod window; -pub use header_bar::*; pub use preferences_window::*; pub use process_manager::*; pub use search_toolbar::*; diff --git a/src/components/window/window.rs b/src/components/window/window.rs index f731148..de63d04 100644 --- a/src/components/window/window.rs +++ b/src/components/window/window.rs @@ -10,6 +10,7 @@ use tracing::*; use crate::components::PreferencesWindow; use crate::config::PROFILE; use crate::settings::Settings; +use crate::tile::{StyleSwitcher, ZoomControls}; use crate::util::EnvMap; use super::*; @@ -33,13 +34,25 @@ pub struct Window { env: RefCell>, #[template_child] - pub header_bar: TemplateChild, + pub title_widget: TemplateChild, #[template_child] - pub overlay: TemplateChild, + pub header_bar: TemplateChild, #[template_child] - pub container: TemplateChild, + pub header_box: TemplateChild, + + #[template_child] + pub menu_button: TemplateChild, + + #[template_child] + pub style_switcher: TemplateChild, + + #[property(get, set, construct, default = 100)] + pub zoom: Cell, + + #[template_child] + pub toasts: TemplateChild, #[template_child] pub tab_view: TemplateChild, @@ -47,6 +60,9 @@ pub struct Window { #[template_child] pub tab_bar: TemplateChild, + #[template_child] + pub toolbar_view: TemplateChild, + selected_page_signals: glib::SignalGroup, active_tab_signals: glib::SignalGroup, active_tab_bindings: glib::BindingGroup, @@ -60,10 +76,16 @@ impl Default for Window { command: Default::default(), env: Default::default(), header_bar: Default::default(), - overlay: Default::default(), - container: Default::default(), + toasts: Default::default(), tab_view: Default::default(), tab_bar: Default::default(), + header_box: Default::default(), + title_widget: Default::default(), + menu_button: Default::default(), + style_switcher: Default::default(), + zoom: Default::default(), + toolbar_view: Default::default(), + selected_page_signals: glib::SignalGroup::new::(), active_tab_signals: glib::SignalGroup::new::(), active_tab_bindings: glib::BindingGroup::new(), @@ -78,6 +100,8 @@ impl ObjectSubclass for Window { type ParentType = adw::ApplicationWindow; fn class_init(klass: &mut Self::Class) { + StyleSwitcher::ensure_type(); + ZoomControls::ensure_type(); klass.bind_template(); klass.bind_template_callbacks(); @@ -133,6 +157,16 @@ impl Window { info!("selected page: pinned"); }); + self.selected_page_signals.connect_notify_local( + Some("title"), + clone!(@weak self as this =>move |obj, param| { + info!("selected page: title"); + if let Some(page) = obj.downcast_ref::() { + this.obj().set_title(Some(&page.title())) + } + }), + ); + self.active_tab_signals.connect_bind_local(move |sg, obj| { info!("active tab: bind"); }); @@ -141,15 +175,63 @@ impl Window { // info!("active tab: bind"); // }); - self.active_tab_signals.connect_notify_local(Some("zoom"), move |sg, obj| { + self.active_tab_signals.connect_notify_local(Some("zoom"), move |obj, param| { info!("active tab: zoom"); }); + + self.active_tab_signals.connect_notify_local( + Some("directory"), + clone!(@weak self as this => move |obj, param| { + info!("active tab: directory"); + if let Some(tab) = obj.downcast_ref::() { + this.directory.set(tab.directory()); + this.obj().notify_directory(); + } + }), + ); + + self.settings.bind_show_menu_button(&*self.menu_button, "visible").get_only().build(); + + self.obj() + .bind_property("fullscreened", &*self.header_bar, "show-end-title-buttons") + .invert_boolean() + .sync_create() + .build(); + + self.settings.bind_style_preference(&*self.style_switcher, "preference").build(); + + self.settings + .bind_show_headerbar(&*self.toolbar_view, "extend-content-to-top-edge") + .get_only() + .invert_boolean() + .build(); + self.settings.bind_show_headerbar(&*self.toolbar_view, "reveal-top-bars").get_only().build(); + + self.obj().connect_root_notify(clone!(@weak self as this => move |obj| { + if let Some(window) = obj.root().and_then(|root| root.clone().downcast::().ok()) { + window.bind_property("title", obj, "title").sync_create().build(); + } + })); + + self.set_integrated_tab_bar(); + + self.settings + .connect_headerbar_integrated_tabbar_changed(clone!(@weak self as this => move |_| { + this.set_integrated_tab_bar(); + })); + + self.tab_bar.connect_view_notify(clone!(@weak self as this => move |tabbar| { + this.set_integrated_tab_bar(); + if let Some(tab_view) = tabbar.view() { + info!("tab view: {:?}", tab_view); + tab_view.connect_n_pages_notify( move |_| { + this.set_integrated_tab_bar(); + }); + } + })); } fn setup_widgets(&self) { - self.header_bar.set_container(Some(&*self.container)); - self.header_bar.set_overlay(Some(&*self.overlay)); - if self.settings.remember_window_size() { self.restore_window_size(); } @@ -180,9 +262,9 @@ impl Window { this.settings.set_was_maximized(w.is_maximized()); })); - self.obj().connect_fullscreened_notify(clone!(@weak self as this => move |w| { - this.header_bar.set_fullscreened(w.is_fullscreened()); - })); + // self.obj().connect_fullscreened_notify(clone!(@weak self as this => move |w| { + // this.header_bar.set_fullscreened(w.is_fullscreened()); + // })); self.tab_view .connect_close_page(clone!(@weak self as this => @default-return false, move |tv, _| { @@ -194,9 +276,8 @@ impl Window { self.tab_view.connect_selected_page_notify(clone!(@weak self as this => move |tab_view| { if let Some(page) = tab_view.selected_page() { - this.update_title(&page); + this.obj().set_title(Some(&page.title())) } - })); } @@ -267,29 +348,7 @@ impl Window { if let Some(title) = title { tab_page.set_title(title); } - this.update_title(&tab_page); })); - - let tab_page = page.clone(); - tab.connect_directory_notify(clone!(@weak self as this, @weak tab_page => move |t| { - if this.tab_view.selected_page() == Some(tab_page) { - this.update_directory(t.directory()); - } - })); - } - - fn update_directory(&self, directory: Option) { - *self.directory.borrow_mut() = directory; - self.obj().notify_directory(); - } - - fn update_title(&self, page: &TabPage) { - if self.tab_view.selected_page().as_ref() == Some(page) { - info!("set window title {:?}", page.title()); - self.obj().set_title(Some(&page.title())) - } else { - info!("page does not equal selected"); - } } fn zoom_out(&self) { @@ -379,6 +438,7 @@ impl Window { fn on_page_attached(&self) {} #[template_callback] fn on_page_detached(&self) {} + #[template_callback] fn on_create_window(&self) -> Option { self.obj().application().and_then(|app| { @@ -393,4 +453,33 @@ impl Window { } #[template_callback] fn on_setup_menu(&self) {} + + #[template_callback] + fn on_tab_overview_open(&self) {} + + #[template_callback] + fn on_create_tab(&self) {} + + fn set_integrated_tab_bar(&self) { + if self.settings.headerbar_integrated_tabbar() { + if self.header_bar.title_widget() != Some(self.tab_bar.clone().into()) { + self.tab_bar.unparent(); + self.header_bar.set_title_widget(Some(&*self.tab_bar)); + } + self.tab_bar.set_halign(gtk::Align::Fill); + self.tab_bar.set_hexpand(true); + self.tab_bar.set_autohide(false); + self.tab_bar.set_can_focus(false); + self.tab_bar.set_css_classes(&["inline", "integrated"]); + } else { + self.header_bar.set_title_widget(Some(&*self.title_widget)); + self.header_box.append(&*self.tab_bar); + + self.tab_bar.set_halign(gtk::Align::Fill); + self.tab_bar.set_hexpand(true); + self.tab_bar.set_autohide(true); + self.tab_bar.set_can_focus(false); + self.tab_bar.set_css_classes(&[]); + } + } } diff --git a/src/components/window/window.ui b/src/components/window/window.ui index c3a1af4..8f1e6b4 100644 --- a/src/components/window/window.ui +++ b/src/components/window/window.ui @@ -4,6 +4,49 @@ + +
+ + style-switcher + +
+
+ + zoom-controls + +
+
+ + new-tab + New _Tab + win.new-tab + action-disabled + + + new-window + New _Window + app.new-window + action-disabled + +
+
+ + _Preferences + win.edit-preferences + +
+
+ + About Terms + app.about + + + Quit + app.quit + +
+
+
@@ -61,39 +104,122 @@ terms_main_window - - - - vertical - - - - - terms_tab_bar - true - true - tab_view - + + true + + + tab_view + + + + + + + vertical + 0 + center + + + + true + + + + splitbutton + + + + tab-new-symbolic + New Tab + win.new-tab + false + + + + + vertical + + + + + + + pan-down-symbolic + + + + + + + + + + true + Terms + + + terms_tab_bar + true + true + tab_view + + + + + + + Menu + open-menu-symbolic + + + + main_menu + + + + + + + + + + + + + + + view-grid-symbolic + Show Open Tabs + + false + + - + - - - - - - - - - tab_menu + + + + + + + + + + + tab_menu + + - + - + diff --git a/src/tile/mod.rs b/src/tile/mod.rs index daf3cfd..04c1dfe 100644 --- a/src/tile/mod.rs +++ b/src/tile/mod.rs @@ -3,3 +3,12 @@ pub use zoom_controls::*; mod style_switcher; pub use style_switcher::*; + +mod tile; +pub use tile::*; + +mod tile_header; +pub use tile_header::*; + +mod tile_view; +pub use tile_view::*; diff --git a/src/tile/tile/mod.rs b/src/tile/tile/mod.rs new file mode 100644 index 0000000..cfdcc35 --- /dev/null +++ b/src/tile/tile/mod.rs @@ -0,0 +1,16 @@ +mod tile; +use tile as imp; + +use glib::{closure_local, ObjectExt}; + +glib::wrapper! { + pub struct Tile(ObjectSubclass) + @extends gtk::Widget, adw::Bin, + @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget; +} + +impl Tile { + pub fn new() -> Self { + glib::Object::builder().build() + } +} diff --git a/src/tile/tile/tile.rs b/src/tile/tile/tile.rs new file mode 100644 index 0000000..c884cc6 --- /dev/null +++ b/src/tile/tile/tile.rs @@ -0,0 +1,47 @@ +use std::cell::{Cell, RefCell}; + +use adw::subclass::prelude::*; +use glib::prelude::*; +use glib::Properties; + +#[derive(Debug, Default, Properties)] +#[properties(wrapper_type=super::Tile)] +pub struct Tile { + #[property(get, set, construct)] + selected: Cell, + + #[property(get, set, construct_only, nullable)] + title: RefCell>, + + #[property(get, set, construct)] + needs_attention: Cell, + // #[property(get, set, construct)] + // live_thumbnail: Cell, + + // PAGE_PROP_PARENT, + // PAGE_PROP_SELECTED, + // PAGE_PROP_TOOLTIP, + // PAGE_PROP_ICON, + // PAGE_PROP_LOADING, + // PAGE_PROP_INDICATOR_ICON, + // PAGE_PROP_INDICATOR_TOOLTIP, + // PAGE_PROP_INDICATOR_ACTIVATABLE, + // PAGE_PROP_KEYWORD, + // PAGE_PROP_THUMBNAIL_XALIGN, + // PAGE_PROP_THUMBNAIL_YALIGN, + // PAGE_PROP_LIVE_THUMBNAIL, +} + +#[glib::object_subclass] +impl ObjectSubclass for Tile { + const NAME: &'static str = "TileTile"; + type Type = super::Tile; + type ParentType = adw::Bin; +} + +#[glib::derived_properties] +impl ObjectImpl for Tile {} +impl WidgetImpl for Tile {} +impl BinImpl for Tile {} + +impl Tile {} diff --git a/src/tile/tile_header/mod.rs b/src/tile/tile_header/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/tile/tile_header/mod.rs @@ -0,0 +1 @@ + diff --git a/src/tile/tile_header/tile_header.rs b/src/tile/tile_header/tile_header.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/tile/tile_view/mod.rs b/src/tile/tile_view/mod.rs new file mode 100644 index 0000000..230fb5a --- /dev/null +++ b/src/tile/tile_view/mod.rs @@ -0,0 +1,16 @@ +mod tile_view; +use tile_view as imp; + +use glib::{closure_local, ObjectExt}; + +glib::wrapper! { + pub struct TileView(ObjectSubclass) + @extends gtk::Widget, adw::Bin, + @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget; +} + +impl TileView { + pub fn new() -> Self { + glib::Object::builder().build() + } +} diff --git a/src/tile/tile_view/tile_view.rs b/src/tile/tile_view/tile_view.rs new file mode 100644 index 0000000..b34b501 --- /dev/null +++ b/src/tile/tile_view/tile_view.rs @@ -0,0 +1,17 @@ +use adw::subclass::prelude::*; + +#[derive(Debug, Default)] +pub struct TileView {} + +#[glib::object_subclass] +impl ObjectSubclass for TileView { + const NAME: &'static str = "TileTileView"; + type Type = super::TileView; + type ParentType = adw::Bin; +} + +impl ObjectImpl for TileView {} +impl WidgetImpl for TileView {} +impl BinImpl for TileView {} + +impl TileView {} diff --git a/src/tile/zoom_controls/zoom_controls.ui b/src/tile/zoom_controls/zoom_controls.ui index 8b2ace0..2fce091 100644 --- a/src/tile/zoom_controls/zoom_controls.ui +++ b/src/tile/zoom_controls/zoom_controls.ui @@ -9,10 +9,8 @@ -