Skip to content

Commit

Permalink
Add ComboBox::close_behavior (#5305)
Browse files Browse the repository at this point in the history
Exposed the underlying PopupCloseBehavior of ComboBox in order to allow
more control of ComboBox behavior.

This allows ComboBox to be used rather than manually managing a popup
directly, while also gaining the convenience features of ComboBox such
as popup auto-sizing.

* [x] I have followed the instructions in the PR template
  • Loading branch information
avalsch authored Oct 29, 2024
1 parent ce05b59 commit 9891648
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 15 deletions.
21 changes: 19 additions & 2 deletions crates/egui/src/containers/combo_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub struct ComboBox {
height: Option<f32>,
icon: Option<IconPainter>,
wrap_mode: Option<TextWrapMode>,
close_behavior: Option<PopupCloseBehavior>,
}

impl ComboBox {
Expand All @@ -58,6 +59,7 @@ impl ComboBox {
height: None,
icon: None,
wrap_mode: None,
close_behavior: None,
}
}

Expand All @@ -72,6 +74,7 @@ impl ComboBox {
height: None,
icon: None,
wrap_mode: None,
close_behavior: None,
}
}

Expand All @@ -85,6 +88,7 @@ impl ComboBox {
height: None,
icon: None,
wrap_mode: None,
close_behavior: None,
}
}

Expand Down Expand Up @@ -173,7 +177,6 @@ impl ComboBox {
#[inline]
pub fn wrap(mut self) -> Self {
self.wrap_mode = Some(TextWrapMode::Wrap);

self
}

Expand All @@ -184,6 +187,15 @@ impl ComboBox {
self
}

/// Controls the close behavior for the popup.
///
/// By default, `PopupCloseBehavior::CloseOnClick` will be used.
#[inline]
pub fn close_behavior(mut self, close_behavior: PopupCloseBehavior) -> Self {
self.close_behavior = Some(close_behavior);
self
}

/// Show the combo box, with the given ui code for the menu contents.
///
/// Returns `InnerResponse { inner: None }` if the combo box is closed.
Expand All @@ -208,6 +220,7 @@ impl ComboBox {
height,
icon,
wrap_mode,
close_behavior,
} = self;

let button_id = ui.make_persistent_id(id_salt);
Expand All @@ -220,6 +233,7 @@ impl ComboBox {
menu_contents,
icon,
wrap_mode,
close_behavior,
(width, height),
);
if let Some(label) = label {
Expand Down Expand Up @@ -301,6 +315,7 @@ fn combo_box_dyn<'c, R>(
menu_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
icon: Option<IconPainter>,
wrap_mode: Option<TextWrapMode>,
close_behavior: Option<PopupCloseBehavior>,
(width, height): (Option<f32>, Option<f32>),
) -> InnerResponse<Option<R>> {
let popup_id = ComboBox::widget_to_popup_id(button_id);
Expand All @@ -325,6 +340,8 @@ fn combo_box_dyn<'c, R>(

let wrap_mode = wrap_mode.unwrap_or_else(|| ui.wrap_mode());

let close_behavior = close_behavior.unwrap_or(PopupCloseBehavior::CloseOnClick);

let margin = ui.spacing().button_padding;
let button_response = button_frame(ui, button_id, is_popup_open, Sense::click(), |ui| {
let icon_spacing = ui.spacing().icon_spacing;
Expand Down Expand Up @@ -396,7 +413,7 @@ fn combo_box_dyn<'c, R>(
popup_id,
&button_response,
above_or_below,
PopupCloseBehavior::CloseOnClick,
close_behavior,
|ui| {
ScrollArea::vertical()
.max_height(height)
Expand Down
38 changes: 25 additions & 13 deletions examples/popups/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,33 @@ fn main() -> Result<(), eframe::Error> {
struct MyApp {
checkbox: bool,
number: u8,
numbers: [bool; 10],
}

impl eframe::App for MyApp {
fn update(&mut self, ctx: &eframe::egui::Context, _frame: &mut eframe::Frame) {
CentralPanel::default().show(ctx, |ui| {
ui.label("PopupCloseBehavior::CloseOnClickAway popup");
ui.label("PopupCloseBehavior::CloseOnClick popup");
ComboBox::from_label("ComboBox")
.selected_text(format!("{}", self.number))
.show_ui(ui, |ui| {
for num in 0..10 {
ui.selectable_value(&mut self.number, num, format!("{num}"));
}
});

ui.label("PopupCloseBehavior::CloseOnClickOutside popup");
ComboBox::from_label("Ignore Clicks")
.close_behavior(PopupCloseBehavior::CloseOnClickOutside)
.selected_text("Select Numbers")
.show_ui(ui, |ui| {
ui.label("This popup will be open even if you click the checkboxes");
for (i, num) in self.numbers.iter_mut().enumerate() {
ui.checkbox(num, format!("Checkbox {}", i + 1));
}
});

ui.label("PopupCloseBehavior::IgnoreClicks popup");
let response = ui.button("Open");
let popup_id = Id::new("popup_id");

Expand All @@ -31,22 +52,13 @@ impl eframe::App for MyApp {
ui,
popup_id,
&response,
PopupCloseBehavior::CloseOnClickOutside,
PopupCloseBehavior::IgnoreClicks,
|ui| {
ui.set_min_width(300.0);
ui.label("This popup will be open even if you click the checkbox");
ui.set_min_width(310.0);
ui.label("This popup will be open until you press the button again");
ui.checkbox(&mut self.checkbox, "Checkbox");
},
);

ui.label("PopupCloseBehavior::CloseOnClick popup");
ComboBox::from_label("ComboBox")
.selected_text(format!("{}", self.number))
.show_ui(ui, |ui| {
for num in 0..10 {
ui.selectable_value(&mut self.number, num, format!("{num}"));
}
});
});
}
}

0 comments on commit 9891648

Please sign in to comment.