glib

Attribute Macro flags

Source
#[flags]
Expand description

Attribute macro for defining flags using the bitflags crate. This macro will also define a GFlags::type_ function and the glib::Value traits.

The expected GType name has to be passed as macro attribute. The name and nick of each flag can also be optionally defined. Default name is the flag identifier in CamelCase and default nick is the identifier in kebab-case. Combined flags should not be registered with the GType system and so need to be tagged with the #[flags_value(skip)] attribute.

§Example

use glib::prelude::*;
use glib::subclass::prelude::*;

#[glib::flags(name = "MyFlags")]
enum MyFlags {
    #[flags_value(name = "Flag A", nick = "nick-a")]
    A = 0b00000001,
    #[flags_value(name = "Flag B")]
    B = 0b00000010,
    #[flags_value(skip)]
    AB = Self::A.bits() | Self::B.bits(),
    C = 0b00000100,
}

The flags can be registered as a dynamic type by setting the macro helper attribute flags_dynamic:

use glib::prelude::*;
use glib::subclass::prelude::*;

#[glib::flags(name = "MyFlags")]
#[flags_dynamic]
enum MyFlags {
    ...
}

As a dynamic type, the flags must be explicitly registered when the system loads the implementation (see TypePlugin and TypeModule). Therefore, whereas the flags can be registered only once as a static type, they can be registered several times as a dynamic type.

The flags registered as a dynamic type are never unregistered. The system calls TypePluginExt::unuse to unload the implementation. If the TypePlugin subclass is a TypeModule, the flags registered as a dynamic type are marked as unloaded and must be registered again when the module is reloaded.

The macro helper attribute flags_dynamic provides two behaviors when registering the flags as a dynamic type:

  • lazy registration: by default the flags are registered as a dynamic type when the system loads the implementation (e.g. when the module is loaded). Optionally setting lazy_registration to true postpones registration on the first use (when static_type() is called for the first time):
#[glib::flags(name = "MyFlags")]
#[flags_dynamic(lazy_registration = true)]
enum MyFlags {
    ...
}
  • registration within TypeModule subclass or within TypePlugin subclass: the flags are usually registered as a dynamic type within a TypeModule subclass:
#[glib::flags(name = "MyModuleFlags")]
#[flags_dynamic]
enum MyModuleFlags {
    ...
}
...
#[derive(Default)]
pub struct MyModule;
...
impl TypeModuleImpl for MyModule {
    fn load(&self) -> bool {
        // registers flags as dynamic types.
        let my_module = self.obj();
        let type_module: &glib::TypeModule = my_module.upcast_ref();
        MyModuleFlags::on_implementation_load(type_module)
    }
    ...
}

Optionally setting plugin_type allows to register the flags as a dynamic type within a TypePlugin subclass that is not a TypeModule:

#[glib::flags(name = "MyModuleFlags")]
#[flags_dynamic(plugin_type = MyPlugin)]
enum MyModuleFlags {
    ...
}
...
#[derive(Default)]
pub struct MyPlugin;
...
impl TypePluginImpl for MyPlugin {
    fn use_plugin(&self) {
        // register flags as dynamic types.
        let my_plugin = self.obj();
        MyPluginFlags::on_implementation_load(my_plugin.as_ref());
    }
    ...
}