Skip to content

Instantly share code, notes, and snippets.

@matthewjberger
Last active July 8, 2024 19:09
Show Gist options
  • Save matthewjberger/0485fe9f94a489f46acb30efc579d4f8 to your computer and use it in GitHub Desktop.
Save matthewjberger/0485fe9f94a489f46acb30efc579d4f8 to your computer and use it in GitHub Desktop.
egui enum dropdown selection in rust
// This is a macro that can generate the egui enum dropdown pattern for a c-style Rust enum
// meaning it contains only fieldless, unit variants
#[macro_export]
macro_rules! generate_enum {
(
$name:ident {
$($variant:ident),* $(,)?
}
) => {
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize, PartialEq)]
pub enum $name {
#[default]
$($variant),*
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
$(Self::$variant => write!(f, "{}", stringify!($variant)),)*
}
}
}
impl $name {
pub fn ui(&self, ui: &mut egui::Ui) {
ui.label(format!("{}", self));
}
pub fn ui_mut(&mut self, ui: &mut egui::Ui) {
egui::ComboBox::from_id_source(ui.next_auto_id())
.selected_text(format!("{}", self))
.show_ui(ui, |ui| {
$(
if ui.selectable_value(self, $name::$variant, stringify!($variant)).clicked() {
*self = $name::$variant;
}
)*
});
}
}
}
}
generate_enum! {
Color {
Red,
Green,
Blue,
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub enum Color {
#[default]
Red,
Green,
Blue,
}
impl Color {
pub fn variant_names() -> Vec<String> {
vec![
Color::Red.to_string(),
Color::Green.to_string(),
Color::Blue.to_string(),
]
}
}
impl std::fmt::Display for Color {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Color::Red => write!(f, "{}", "Red"),
Color::Green => write!(f, "{}", "Green"),
Color::Blue => write!(f, "{}", "Blue"),
}
}
}
impl Color {
pub fn ui(&mut self, ui: &mut egui::Ui) {
ui.label(format!("{self}"));
}
pub fn ui_mut(&mut self, ui: &mut egui::Ui) {
egui::ComboBox::from_id_source(ui.next_auto_id())
.selected_text(format!("{self}"))
.show_ui(ui, |ui| {
Color::variant_names().iter().for_each(|variant| {
ui.vertical(|ui| match variant {
_ if variant == &Color::Red.to_string() => {
if ui
.selectable_value(self, Color::Red, Color::Red.to_string())
.clicked()
{
*self = Color::Red;
}
}
_ if variant == &Color::Green.to_string() => {
if ui
.selectable_value(self, Color::Green, Color::Green.to_string())
.clicked()
{
*self = Color::Green;
}
}
_ if variant == &Color::Blue.to_string() => {
if ui
.selectable_value(self, Color::Blue, Color::Blue.to_string())
.clicked()
{
*self = Color::Blue;
}
}
_ => {}
});
});
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment