gio/
action_entry.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, Variant, VariantTy, VariantType};
4
5use crate::{ActionMap, SimpleAction};
6
7/// This struct defines a single action.  It is for use with
8/// [`ActionMapExtManual::add_action_entries()`][crate::prelude::ActionMapExtManual::add_action_entries()].
9///
10/// The order of the items in the structure are intended to reflect
11/// frequency of use.  It is permissible to use an incomplete initialiser
12/// in order to leave some of the later values as `NULL`.  All values
13/// after @name are optional.  Additional optional fields may be added in
14/// the future.
15///
16/// See [`ActionMapExtManual::add_action_entries()`][crate::prelude::ActionMapExtManual::add_action_entries()] for an example.
17#[doc(alias = "GActionEntry")]
18pub struct ActionEntry<O>
19where
20    O: IsA<ActionMap>,
21{
22    name: String,
23    parameter_type: Option<VariantType>,
24    state: Option<Variant>,
25    #[allow(clippy::type_complexity)]
26    pub(crate) activate: Option<Box<dyn Fn(&O, &SimpleAction, Option<&Variant>) + 'static>>,
27    #[allow(clippy::type_complexity)]
28    pub(crate) change_state: Option<Box<dyn Fn(&O, &SimpleAction, Option<&Variant>) + 'static>>,
29}
30
31impl<O> ActionEntry<O>
32where
33    O: IsA<ActionMap>,
34{
35    pub fn name(&self) -> &str {
36        &self.name
37    }
38
39    pub fn parameter_type(&self) -> Option<&VariantTy> {
40        self.parameter_type.as_deref()
41    }
42
43    pub fn state(&self) -> Option<&Variant> {
44        self.state.as_ref()
45    }
46
47    pub fn builder(name: &str) -> ActionEntryBuilder<O> {
48        ActionEntryBuilder::new(name)
49    }
50}
51
52impl<O> std::fmt::Debug for ActionEntry<O>
53where
54    O: IsA<ActionMap>,
55{
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        f.debug_struct("ActionEntry")
58            .field("name", &self.name())
59            .field("parameter_type", &self.parameter_type())
60            .field("state", &self.state())
61            .finish()
62    }
63}
64
65#[derive(Debug)]
66pub struct ActionEntryBuilder<O>(ActionEntry<O>)
67where
68    O: IsA<ActionMap>;
69
70impl<O> ActionEntryBuilder<O>
71where
72    O: IsA<ActionMap>,
73{
74    pub fn new(name: &str) -> Self {
75        Self(ActionEntry {
76            name: name.to_owned(),
77            parameter_type: Default::default(),
78            state: Default::default(),
79            activate: Default::default(),
80            change_state: Default::default(),
81        })
82    }
83
84    pub fn parameter_type(mut self, parameter_type: Option<&VariantTy>) -> Self {
85        self.0.parameter_type = parameter_type.map(|vt| vt.to_owned());
86        self
87    }
88
89    pub fn state(mut self, state: Variant) -> Self {
90        self.0.state = Some(state);
91        self
92    }
93
94    pub fn activate<F: Fn(&O, &SimpleAction, Option<&Variant>) + 'static>(
95        mut self,
96        callback: F,
97    ) -> Self {
98        self.0.activate = Some(Box::new(callback));
99        self
100    }
101
102    pub fn change_state<F: Fn(&O, &SimpleAction, Option<&Variant>) + 'static>(
103        mut self,
104        callback: F,
105    ) -> Self {
106        self.0.change_state = Some(Box::new(callback));
107        self
108    }
109
110    pub fn build(self) -> ActionEntry<O> {
111        self.0
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118    use crate::prelude::*;
119
120    #[test]
121    fn action_entry() {
122        let app = crate::Application::new(None, Default::default());
123
124        app.add_action_entries(vec![
125            ActionEntry::builder("close")
126                .activate(move |_app, _, _| {
127                    //Do something
128                })
129                .build(),
130            ActionEntry::builder("enable")
131                .state(true.to_variant())
132                .change_state(move |_app, _, _| {
133                    //Do something
134                })
135                .build(),
136        ]);
137        assert!(app.lookup_action("close").is_some());
138        assert!(app.lookup_action("enable").is_some());
139    }
140}