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
// Take a look at the license at the top of the repository in the LICENSE file.

use glib::{clone, prelude::*};

use crate::{prelude::*, ActionEntry, ActionMap, SimpleAction};

mod sealed {
    pub trait Sealed {}
    impl<T: super::IsA<super::ActionMap>> Sealed for T {}
}

pub trait ActionMapExtManual: sealed::Sealed + IsA<ActionMap> {
    /// A convenience function for creating multiple #GSimpleAction instances
    /// and adding them to a #GActionMap.
    ///
    /// Each action is constructed as per one #GActionEntry.
    ///
    ///
    ///
    /// **⚠️ The following code is in C ⚠️**
    ///
    /// ```C
    /// static void
    /// activate_quit (GSimpleAction *simple,
    ///                GVariant      *parameter,
    ///                gpointer       user_data)
    /// {
    ///   exit (0);
    /// }
    ///
    /// static void
    /// activate_print_string (GSimpleAction *simple,
    ///                        GVariant      *parameter,
    ///                        gpointer       user_data)
    /// {
    ///   g_print ("%s\n", g_variant_get_string (parameter, NULL));
    /// }
    ///
    /// static GActionGroup *
    /// create_action_group (void)
    /// {
    ///   const GActionEntry entries[] = {
    ///     { "quit",         activate_quit              },
    ///     { "print-string", activate_print_string, "s" }
    ///   };
    ///   GSimpleActionGroup *group;
    ///
    ///   group = g_simple_action_group_new ();
    ///   g_action_map_add_action_entries (G_ACTION_MAP (group), entries, G_N_ELEMENTS (entries), NULL);
    ///
    ///   return G_ACTION_GROUP (group);
    /// }
    /// ```
    /// ## `entries`
    /// a pointer to
    ///           the first item in an array of #GActionEntry structs
    #[doc(alias = "g_action_map_add_action_entries")]
    fn add_action_entries(&self, entries: impl IntoIterator<Item = ActionEntry<Self>>) {
        for entry in entries.into_iter() {
            let action = if let Some(state) = entry.state() {
                SimpleAction::new_stateful(entry.name(), entry.parameter_type(), state)
            } else {
                SimpleAction::new(entry.name(), entry.parameter_type())
            };
            let action_map = self.as_ref();
            if let Some(callback) = entry.activate {
                action.connect_activate(clone!(@weak action_map =>  move |action, state| {
                    // safe to unwrap as O: IsA<ActionMap>
                    callback(action_map.downcast_ref::<Self>().unwrap(), action, state);
                }));
            }
            if let Some(callback) = entry.change_state {
                action.connect_change_state(clone!(@weak action_map => move |action, state| {
                    // safe to unwrap as O: IsA<ActionMap>
                    callback(action_map.downcast_ref::<Self>().unwrap(), action, state);
                }));
            }
            self.as_ref().add_action(&action);
        }
    }
}

impl<O: IsA<ActionMap>> ActionMapExtManual for O {}