zng_wgt_toggle/cmd.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
//! Commands that control toggle.
use parking_lot::Mutex;
use std::{fmt, sync::Arc};
use zng_var::AnyVarValue;
use zng_wgt::prelude::*;
use super::SELECTOR;
command! {
/// Represents the **toggle** action.
///
/// # Handlers
///
/// * [`checked`]: The property toggles for no param and or sets to the `bool` param or to
/// the `Option<bool>` param coercing `None` to `false`.
///
/// * [`checked_opt`]: The property cycles or toggles depending on [`tristate`] for no params, otherwise
/// it sets the `bool` or `Option<bool>` param.
///
/// * [`value`]: The property toggles select/unselect the value for no params, otherwise it selects the value
/// for param `true` or `Some(true)` and deselects the value for param `false` or `None::<bool>`. Note that you
/// can also use the [`SELECT_CMD`] for value.
///
/// [`checked`]: fn@super::checked
/// [`checked_opt`]: fn@super::checked_opt
/// [`tristate`]: fn@super::tristate
/// [`value`]: fn@super::value
pub static TOGGLE_CMD;
/// Represents the **select** action.
///
/// # Handlers
///
/// * [`value`]: The property selects the value if the command has no param.
///
/// * [`selector`]: The property applies the [`SelectOp`] param.
///
/// [`value`]: fn@super::value
/// [`selector`]: fn@super::selector
pub static SELECT_CMD;
}
/// Represents a select operation that can be send to [`selector`] using [`SELECT_CMD`].
///
/// [`selector`]: fn@super::selector
#[derive(Clone)]
pub struct SelectOp {
op: Arc<Mutex<dyn FnMut() + Send>>,
}
impl fmt::Debug for SelectOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SelectOp").finish_non_exhaustive()
}
}
impl SelectOp {
/// New (de)select operation.
///
/// The [`selector`] property handles [`SELECT_CMD`] by calling `op` during event handling.
/// You can use [`SELECTOR`] to get and set the selection.
///
/// [`selector`]: fn@super::selector
pub fn new(op: impl FnMut() + Send + 'static) -> Self {
Self {
op: Arc::new(Mutex::new(op)),
}
}
/// Select the `value`.
pub fn select(value: Box<dyn AnyVarValue>) -> Self {
let mut value = Some(value);
Self::new(move || {
if let Some(value) = value.take() {
if let Err(e) = SELECTOR.get().select(value) {
tracing::error!("select error: {e}");
}
}
})
}
/// Deselect the `value`.
pub fn deselect(value: Box<dyn AnyVarValue>) -> Self {
Self::new(move || {
if let Err(e) = SELECTOR.get().deselect(&*value) {
tracing::error!("deselect error: {e}");
}
})
}
/// Run the operation.
pub fn call(&self) {
(self.op.lock())()
}
}