From 83d2cb249fd15afeb1fa096649583ec00422bae3 Mon Sep 17 00:00:00 2001 From: Lucy Date: Tue, 15 Feb 2022 18:24:24 -0500 Subject: [PATCH] Add a loading overlay for while the mode is being changed --- applets/cosmic-applet-graphics/src/main.rs | 162 +++++++++++++------ applets/cosmic-applet-graphics/src/style.css | 4 + 2 files changed, 118 insertions(+), 48 deletions(-) create mode 100644 applets/cosmic-applet-graphics/src/style.css diff --git a/applets/cosmic-applet-graphics/src/main.rs b/applets/cosmic-applet-graphics/src/main.rs index 97deb0ab..13b982bd 100644 --- a/applets/cosmic-applet-graphics/src/main.rs +++ b/applets/cosmic-applet-graphics/src/main.rs @@ -11,7 +11,14 @@ pub mod mode_box; pub mod profile; use self::{dbus::PowerDaemonProxy, graphics::Graphics, mode_box::ModeSelection}; -use gtk4::{gio::ApplicationFlags, prelude::*, Label, ListBox, ListBoxRow, Orientation, Separator}; +use gtk4::{ + gdk::Display, + gio::ApplicationFlags, + glib::{self, clone, MainContext, PRIORITY_DEFAULT}, + prelude::*, + Align, CssProvider, Label, ListBox, ListBoxRow, Orientation, Overlay, Separator, Spinner, + StyleContext, STYLE_PROVIDER_PRIORITY_APPLICATION, +}; use once_cell::sync::Lazy; use tokio::runtime::Runtime; @@ -47,6 +54,14 @@ fn row_clicked(_: &ListBox, row: &ListBoxRow) { } fn build_ui(application: >k4::Application) { + let provider = CssProvider::new(); + provider.load_from_data(include_bytes!("style.css")); + StyleContext::add_provider_for_display( + &Display::default().expect("Could not connect to a display."), + &provider, + STYLE_PROVIDER_PRIORITY_APPLICATION, + ); + let window = gtk4::ApplicationWindow::builder() .application(application) .title("COSMIC Graphics Applet") @@ -56,60 +71,111 @@ fn build_ui(application: >k4::Application) { let current_graphics = RT .block_on(get_current_graphics()) .expect("failed to connect to system76-power"); + let (tx, rx) = MainContext::channel::(PRIORITY_DEFAULT); view! { - main_box = gtk4::Box { - set_orientation: Orientation::Vertical, - set_spacing: 10, - set_margin_top: 20, - set_margin_bottom: 20, - set_margin_start: 24, - set_margin_end: 24, - append: mode_label = &Label { - set_text: "Graphics Mode" + main_overlay = Overlay { + add_overlay: loading_box = >k4::Box { + append: loading_explain_box = >k4::Box { + set_orientation: Orientation::Vertical, + set_halign: Align::Center, + set_valign: Align::Center, + append: loading_spinner = &Spinner { + set_halign: Align::Center, + }, + append: loading_explain = &Label { + set_label: "Please wait while your graphics mode is set...", + set_halign: Align::Center, + }, + }, + set_halign: Align::Center, + set_valign: Align::Center, + set_hexpand: true, + set_vexpand: true, + set_visible: false, + add_css_class: "loading-overlay", }, - append: separator = &Separator { - set_orientation: Orientation::Horizontal - }, - append: graphics_modes_list = &ListBox { - connect_row_activated: row_clicked, - append: integrated_selector = &ModeSelection { - set_title: "Integrated Graphics", - set_description: "Disables external displays. Requires Restart.", - set_active: (current_graphics == Graphics::Integrated), - connect_toggled: |_| { - RT.block_on(set_graphics(Graphics::Integrated)).expect("failed to set graphics"); - } + set_child: main_box = Some(>k4::Box) { + set_orientation: Orientation::Vertical, + set_spacing: 10, + set_margin_top: 20, + set_margin_bottom: 20, + set_margin_start: 24, + set_margin_end: 24, + append: mode_label = &Label { + set_text: "Graphics Mode" }, - append: nvidia_selector = &ModeSelection { - set_title: "NVIDIA Graphics", - set_group: Some(&integrated_selector), - set_active: (current_graphics == Graphics::Nvidia), - connect_toggled: |_| { - RT.block_on(set_graphics(Graphics::Nvidia)).expect("failed to set graphics"); - } - }, - append: hybrid_selector = &ModeSelection { - set_title: "Hybrid Graphics", - set_description: "Requires Restart.", - set_group: Some(&integrated_selector), - set_active: (current_graphics == Graphics::Hybrid), - connect_toggled: |_| { - RT.block_on(set_graphics(Graphics::Hybrid)).expect("failed to set graphics"); - } - }, - append: compute_selector = &ModeSelection { - set_title: "Compute Graphics", - set_description: "Disables external displays. Requires Restart.", - set_group: Some(&integrated_selector), - set_active: (current_graphics == Graphics::Compute), - connect_toggled: |_| { - RT.block_on(set_graphics(Graphics::Compute)).expect("failed to set graphics"); - } + append: separator = &Separator { + set_orientation: Orientation::Horizontal }, + append: graphics_modes_list = &ListBox { + connect_row_activated: row_clicked, + append: integrated_selector = &ModeSelection { + set_title: "Integrated Graphics", + set_description: "Disables external displays. Requires Restart.", + set_active: (current_graphics == Graphics::Integrated), + connect_toggled: clone!(@strong tx => move |_| { + tx.send(true).expect("failed to send to main context"); + let tx = tx.clone(); + RT.spawn(async move { + set_graphics(Graphics::Integrated).await.expect("failed to set graphics mode"); + tx.send(false).expect("failed to send to main context"); + }); + }) + }, + append: nvidia_selector = &ModeSelection { + set_title: "NVIDIA Graphics", + set_group: Some(&integrated_selector), + set_active: (current_graphics == Graphics::Nvidia), + connect_toggled: clone!(@strong tx => move |_| { + tx.send(true).expect("failed to send to main context"); + let tx = tx.clone(); + RT.spawn(async move { + set_graphics(Graphics::Nvidia).await.expect("failed to set graphics mode"); + tx.send(false).expect("failed to send to main context"); + }); + }) + }, + append: hybrid_selector = &ModeSelection { + set_title: "Hybrid Graphics", + set_description: "Requires Restart.", + set_group: Some(&integrated_selector), + set_active: (current_graphics == Graphics::Hybrid), + connect_toggled: clone!(@strong tx => move |_| { + tx.send(true).expect("failed to send to main context"); + let tx = tx.clone(); + RT.spawn(async move { + set_graphics(Graphics::Hybrid).await.expect("failed to set graphics mode"); + tx.send(false).expect("failed to send to main context"); + }); + }) + }, + append: compute_selector = &ModeSelection { + set_title: "Compute Graphics", + set_description: "Disables external displays. Requires Restart.", + set_group: Some(&integrated_selector), + set_active: (current_graphics == Graphics::Compute), + connect_toggled: clone!(@strong tx => move |_| { + tx.send(true).expect("failed to send to main context"); + let tx = tx.clone(); + RT.spawn(async move { + set_graphics(Graphics::Compute).await.expect("failed to set graphics mode"); + tx.send(false).expect("failed to send to main context"); + }); + }) + }, + } } } } - window.set_child(Some(&main_box)); + rx.attach( + None, + clone!(@weak loading_box, @weak loading_spinner => @default-return Continue(true), move |val| { + loading_box.set_visible(val); + loading_spinner.set_spinning(val); + Continue(true) + }), + ); + window.set_child(Some(&main_overlay)); window.show(); } diff --git a/applets/cosmic-applet-graphics/src/style.css b/applets/cosmic-applet-graphics/src/style.css new file mode 100644 index 00000000..ca16e327 --- /dev/null +++ b/applets/cosmic-applet-graphics/src/style.css @@ -0,0 +1,4 @@ +.loading-overlay { + background-color: #2f2f2f; + opacity: 0.85; +}