#![doc(html_logo_url = "https://relm4.org/icons/relm4_logo.svg")]
#![doc(html_favicon_url = "https://relm4.org/icons/relm4_org.svg")]
#![warn(
missing_debug_implementations,
missing_docs,
rust_2018_idioms,
unreachable_pub,
unused_qualifications,
clippy::cargo,
clippy::must_use_candidate,
clippy::used_underscore_binding
)]
#![allow(clippy::multiple_crate_versions)]
#![cfg_attr(docsrs, feature(doc_cfg))]
mod app;
mod channel;
mod extensions;
pub(crate) mod late_initialization;
mod runtime_util;
pub mod abstractions;
pub mod actions;
pub mod binding;
pub mod component;
pub mod factory;
pub mod loading_widgets;
pub mod shared_state;
pub mod typed_view;
pub use channel::ComponentSender;
pub use channel::*;
pub use component::worker::{Worker, WorkerController, WorkerHandle};
pub use component::{
Component, ComponentBuilder, ComponentController, ComponentParts, Controller, MessageBroker,
SimpleComponent,
};
pub use extensions::*;
pub use shared_state::{Reducer, Reducible, SharedState};
pub use shutdown::ShutdownReceiver;
pub use app::RelmApp;
pub use tokio::task::JoinHandle;
use gtk::prelude::{Cast, IsA};
use once_cell::sync::{Lazy, OnceCell};
use runtime_util::{GuardedReceiver, RuntimeSenders, ShutdownOnDrop};
use std::cell::Cell;
use std::future::Future;
use tokio::runtime::Runtime;
pub static RELM_THREADS: OnceCell<usize> = OnceCell::new();
pub static RELM_BLOCKING_THREADS: OnceCell<usize> = OnceCell::new();
pub mod prelude;
pub use gtk;
#[cfg(feature = "css")]
#[cfg_attr(docsrs, doc(cfg(feature = "css")))]
pub use relm4_css as css;
#[cfg(feature = "macros")]
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
pub use relm4_macros::*;
#[cfg(feature = "libadwaita")]
#[cfg_attr(docsrs, doc(cfg(feature = "libadwaita")))]
pub use adw;
#[cfg(feature = "libpanel")]
#[cfg_attr(docsrs, doc(cfg(feature = "libpanel")))]
pub use panel;
pub use once_cell;
pub use tokio;
thread_local! {
static MAIN_APPLICATION: Cell<Option<gtk::Application>> = Cell::default();
}
fn set_main_application(app: impl IsA<gtk::Application>) {
MAIN_APPLICATION.with(move |cell| cell.set(Some(app.upcast())));
}
fn init() {
gtk::init().unwrap();
#[cfg(feature = "libadwaita")]
adw::init().unwrap();
}
#[must_use]
pub fn main_application() -> gtk::Application {
#[cfg(feature = "libadwaita")]
fn new_application() -> gtk::Application {
adw::Application::default().upcast()
}
#[cfg(not(feature = "libadwaita"))]
fn new_application() -> gtk::Application {
gtk::Application::default()
}
MAIN_APPLICATION.with(|cell| {
let app = cell.take().unwrap_or_else(new_application);
cell.set(Some(app.clone()));
app
})
}
#[cfg(feature = "libadwaita")]
#[cfg_attr(docsrs, doc(cfg(feature = "libadwaita")))]
#[must_use]
pub fn main_adw_application() -> adw::Application {
main_application().downcast().unwrap()
}
pub fn spawn_local<F, Out>(func: F) -> gtk::glib::JoinHandle<Out>
where
F: Future<Output = Out> + 'static,
Out: 'static,
{
gtk::glib::MainContext::ref_thread_default().spawn_local(func)
}
pub fn spawn_local_with_priority<F, Out>(
priority: gtk::glib::Priority,
func: F,
) -> gtk::glib::JoinHandle<Out>
where
F: Future<Output = Out> + 'static,
Out: 'static,
{
gtk::glib::MainContext::ref_thread_default().spawn_local_with_priority(priority, func)
}
static RUNTIME: Lazy<Runtime> = Lazy::new(|| {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.worker_threads(*RELM_THREADS.get_or_init(|| 1))
.max_blocking_threads(*RELM_BLOCKING_THREADS.get_or_init(|| 512))
.build()
.unwrap()
});
pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
RUNTIME.spawn(future)
}
pub fn spawn_blocking<F, R>(func: F) -> JoinHandle<R>
where
F: FnOnce() -> R + Send + 'static,
R: Send + 'static,
{
RUNTIME.spawn_blocking(func)
}
pub fn set_global_css_with_priority(style_data: &str, priority: u32) {
let display = gtk::gdk::Display::default().unwrap();
let provider = gtk::CssProvider::new();
#[allow(deprecated)]
provider.load_from_data(style_data);
#[allow(deprecated)]
gtk::StyleContext::add_provider_for_display(&display, &provider, priority);
}
pub fn set_global_css(style_data: &str) {
set_global_css_with_priority(style_data, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION);
}
pub fn set_global_css_from_file_with_priority<P: AsRef<std::path::Path>>(
path: P,
priority: u32,
) -> Result<(), std::io::Error> {
std::fs::read_to_string(path)
.map(|bytes| set_global_css_with_priority(&bytes, priority))
.map_err(|err| {
tracing::error!("Couldn't load global CSS from file: {}", err);
err
})
}
pub fn set_global_css_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<(), std::io::Error> {
set_global_css_from_file_with_priority(path, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION)
}