use std::sync::Arc;
use std::thread;
use crate::{
compat::{self, mpsc},
private, service, Error, Tray,
};
pub trait TrayMethods: Tray + private::Sealed {
fn spawn(self) -> Result<Handle<Self>, Error> {
TrayServiceBuilder::new(self).spawn()
}
#[doc(hidden)]
#[deprecated(
note = "use `disable_dbus_name(true).spawn()` instead",
since = "0.3.4"
)]
fn spawn_without_dbus_name(self) -> Result<Handle<Self>, Error> {
self.disable_dbus_name(true).spawn()
}
fn disable_dbus_name(self, disable: bool) -> TrayServiceBuilder<Self> {
TrayServiceBuilder::new(self).disable_dbus_name(disable)
}
fn assume_sni_available(self, assume_available: bool) -> TrayServiceBuilder<Self> {
TrayServiceBuilder::new(self).assume_sni_available(assume_available)
}
}
pub struct TrayServiceBuilder<T: Tray> {
tray: T,
own_name: bool,
assume_sni_available: bool,
}
impl<T: Tray> TrayServiceBuilder<T> {
fn new(tray: T) -> Self {
Self {
tray,
own_name: true,
assume_sni_available: false,
}
}
pub fn spawn(self) -> Result<Handle<T>, Error> {
spawn_with_options(self.tray, self.own_name, self.assume_sni_available)
}
pub fn disable_dbus_name(self, disable: bool) -> Self {
Self {
own_name: !disable,
..self
}
}
pub fn assume_sni_available(self, assume_available: bool) -> Self {
Self {
assume_sni_available: assume_available,
..self
}
}
}
fn spawn_with_options<T: Tray>(
tray: T,
own_name: bool,
assume_sni_available: bool,
) -> Result<Handle<T>, Error> {
let (handle_tx, handle_rx) = mpsc::unbounded_channel();
let service = service::Service::new(tray);
let service_loop = compat::block_on(service::run(
service.clone(),
handle_rx,
own_name,
assume_sni_available,
))?;
thread::spawn(move || {
compat::block_on(service_loop);
});
Ok(Handle(crate::Handle {
service: Arc::downgrade(&service),
sender: handle_tx,
}))
}
impl<T: Tray> TrayMethods for T {}
pub struct Handle<T>(crate::Handle<T>);
impl<T> Handle<T> {
pub fn update<R, F: FnOnce(&mut T) -> R>(&self, f: F) -> Option<R> {
compat::block_on(self.0.update(f))
}
pub fn shutdown(&self) -> ShutdownAwaiter {
ShutdownAwaiter(self.0.shutdown())
}
pub fn is_closed(&self) -> bool {
self.0.is_closed()
}
}
pub struct ShutdownAwaiter(crate::ShutdownAwaiter);
impl ShutdownAwaiter {
pub fn wait(self) {
compat::block_on(self.0)
}
}
impl<T> Clone for Handle<T> {
fn clone(&self) -> Self {
Handle(self.0.clone())
}
}