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 96 97 98 99 100
// Take a look at the license at the top of the repository in the LICENSE file.
use crate::{prelude::*, ActionEntry, ActionMap, SimpleAction};
use glib::{clone, Cast, IsA};
pub trait ActionMapExtManual {
/// A convenience function for creating multiple [`SimpleAction`][crate::SimpleAction] instances
/// and adding them to a [`ActionMap`][crate::ActionMap].
///
/// Each action is constructed as per one [`ActionEntry`][crate::ActionEntry].
///
///
///
/// **⚠️ 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 [`ActionEntry`][crate::ActionEntry] structs
#[doc(alias = "g_action_map_add_action_entries")]
fn add_action_entries(
&self,
entries: impl IntoIterator<Item = ActionEntry<Self>>,
) -> Result<(), glib::BoolError>
where
Self: IsA<ActionMap>;
}
impl<O: IsA<ActionMap>> ActionMapExtManual for O {
fn add_action_entries(
&self,
entries: impl IntoIterator<Item = ActionEntry<Self>>,
) -> Result<(), glib::BoolError> {
for entry in entries.into_iter() {
let parameter_type = if let Some(param_type) = entry.parameter_type() {
Some(glib::VariantType::new(param_type)?)
} else {
None
};
let action = if let Some(state) = entry.state() {
let state = glib::Variant::parse(None, state).map_err(|e| {
glib::bool_error!(
"Invalid state passed to gio::ActionEntry {} {}",
entry.name(),
e
)
})?;
SimpleAction::new_stateful(entry.name(), parameter_type.as_deref(), &state)
} else {
SimpleAction::new(entry.name(), parameter_type.as_deref())
};
let action_map = self.as_ref();
if let Some(callback) = entry.activate {
action.connect_activate(clone!(@strong action_map => move |action, state| {
// safe to unwrap as O: IsA<ActionMap>
callback(action_map.downcast_ref::<O>().unwrap(), action, state);
}));
}
if let Some(callback) = entry.change_state {
action.connect_change_state(clone!(@strong action_map => move |action, state| {
// safe to unwrap as O: IsA<ActionMap>
callback(action_map.downcast_ref::<O>().unwrap(), action, state);
}));
}
self.as_ref().add_action(&action);
}
Ok(())
}
}