141 lines
3.4 KiB
Rust
141 lines
3.4 KiB
Rust
use gio::glib::clone;
|
|
|
|
use std::{collections::VecDeque, sync::LazyLock};
|
|
|
|
use gtk::{
|
|
builders::{BoxBuilder, ButtonBuilder, LabelBuilder},
|
|
prelude::{BoxExt, ButtonExt, ObjectExt, WidgetExt},
|
|
Box, Button, Label, Revealer, RevealerTransitionType
|
|
};
|
|
|
|
use crate::model::builder_traits::Product;
|
|
|
|
use tokio::{
|
|
task::{spawn, JoinHandle},
|
|
time::{sleep, Duration},
|
|
};
|
|
|
|
#[derive(Clone)]
|
|
pub struct InfoBar {
|
|
instance: Revealer,
|
|
}
|
|
|
|
pub struct InfoBarBuilder {
|
|
label: LabelBuilder,
|
|
r#box: BoxBuilder,
|
|
button: ButtonBuilder,
|
|
}
|
|
|
|
static mut TASKS_QUEUE: VecDeque<JoinHandle<()>> = VecDeque::new();
|
|
|
|
//
|
|
// Singleton pattern implementation
|
|
//
|
|
|
|
unsafe impl Send for InfoBar {}
|
|
unsafe impl Sync for InfoBar {}
|
|
|
|
static INFO_BAR_INSTANCE: LazyLock<InfoBar> = LazyLock::new(|| InfoBar {
|
|
instance: Revealer::new(),
|
|
});
|
|
|
|
impl InfoBar {
|
|
pub fn get_instance() -> &'static Self {
|
|
&INFO_BAR_INSTANCE
|
|
}
|
|
|
|
pub fn set_text_label(&self, text_label: Option<&str>) {
|
|
if let Some(text) = text_label {
|
|
let _ = &INFO_BAR_INSTANCE
|
|
.instance
|
|
.child()
|
|
.unwrap()
|
|
.first_child()
|
|
.unwrap()
|
|
.set_property("label", text);
|
|
}
|
|
}
|
|
|
|
pub fn set_reveal_child(&self, is_reveal: bool) {
|
|
let _ = &INFO_BAR_INSTANCE.instance.set_reveal_child(is_reveal);
|
|
}
|
|
|
|
pub fn show_infobar(&self, duration_secs: u64) {
|
|
if !INFO_BAR_INSTANCE.instance.reveals_child() {
|
|
INFO_BAR_INSTANCE.set_reveal_child(true);
|
|
}
|
|
|
|
let callback = spawn(async move {
|
|
sleep(Duration::from_secs(duration_secs)).await;
|
|
INFO_BAR_INSTANCE.set_reveal_child(false);
|
|
});
|
|
|
|
unsafe {
|
|
if !TASKS_QUEUE.is_empty() {
|
|
TASKS_QUEUE.pop_back().unwrap().abort();
|
|
}
|
|
|
|
TASKS_QUEUE.push_back(callback);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Builder pattern implementation
|
|
//
|
|
|
|
impl InfoBarBuilder {
|
|
pub fn build(self) -> &'static InfoBar {
|
|
let info_bar_label = self.label.build();
|
|
let info_bar_box = self.r#box.build();
|
|
let info_bar_close_btn = self.button.build();
|
|
|
|
info_bar_label.set_hexpand(true);
|
|
|
|
info_bar_box.append(&info_bar_label);
|
|
info_bar_box.append(&info_bar_close_btn);
|
|
|
|
let info_bar: &Revealer = &INFO_BAR_INSTANCE.instance;
|
|
|
|
info_bar.set_transition_type(RevealerTransitionType::SlideUp);
|
|
info_bar.set_transition_duration(200);
|
|
info_bar.set_child(Some(&info_bar_box));
|
|
info_bar.set_widget_name("infobar");
|
|
info_bar.set_css_classes(&[".warning"]);
|
|
|
|
info_bar_close_btn.connect_clicked(clone!(
|
|
#[strong]
|
|
info_bar,
|
|
move |_| info_bar.set_reveal_child(false)
|
|
));
|
|
|
|
&INFO_BAR_INSTANCE
|
|
}
|
|
|
|
pub fn set_text_label(mut self, text: &str) -> Self {
|
|
self.label = self.label.label(text);
|
|
|
|
self
|
|
}
|
|
|
|
pub fn set_button_icon(mut self, icon_name: &str) -> Self {
|
|
self.button = self.button.icon_name(icon_name);
|
|
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Product<InfoBarBuilder, Revealer> for InfoBar {
|
|
fn builder() -> InfoBarBuilder {
|
|
InfoBarBuilder {
|
|
label: Label::builder(),
|
|
r#box: Box::builder(),
|
|
button: Button::builder(),
|
|
}
|
|
}
|
|
|
|
fn get(&self) -> &'static Revealer {
|
|
&INFO_BAR_INSTANCE.instance
|
|
}
|
|
}
|