Combo boxes has a scroll area

Closes https://github.com/emilk/egui/issues/75
This commit is contained in:
Emil Ernerfeldt 2020-12-25 13:18:47 +01:00
parent d3eba239ed
commit 38e36fd806
3 changed files with 21 additions and 13 deletions

View file

@ -30,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Made some more fields of `RawInput` optional. * Made some more fields of `RawInput` optional.
* `Slider` and `DragValue` uses fewer decimals by default. See the full precision by hovering over the value. * `Slider` and `DragValue` uses fewer decimals by default. See the full precision by hovering over the value.
* `egui::App`: added `fn name(&self)` and `fn clear_color(&self)`. * `egui::App`: added `fn name(&self)` and `fn clear_color(&self)`.
* Combo boxes has scroll bars when needed.
### Fixed 🐛 ### Fixed 🐛

View file

@ -23,6 +23,8 @@ pub fn combo_box(
selected: impl Into<Label>, selected: impl Into<Label>,
menu_contents: impl FnOnce(&mut Ui), menu_contents: impl FnOnce(&mut Ui),
) -> Response { ) -> Response {
const MAX_COMBO_HEIGHT: f32 = 128.0;
let popup_id = button_id.with("popup"); let popup_id = button_id.with("popup");
let selected = selected.into(); let selected = selected.into();
@ -61,10 +63,12 @@ pub fn combo_box(
let frame_margin = frame.margin; let frame_margin = frame.margin;
frame.show(ui, |ui| { frame.show(ui, |ui| {
ui.with_layout(Layout::top_down_justified(Align::left()), |ui| { ui.with_layout(Layout::top_down_justified(Align::left()), |ui| {
ui.set_min_width(button_response.rect.width() - 2.0 * frame_margin.x); let width = button_response.rect.width() - 2.0 * frame_margin.x;
menu_contents(ui); ui.set_min_width(width);
ui.set_max_width(width);
ScrollArea::from_max_height(MAX_COMBO_HEIGHT).show(ui, menu_contents);
});
}); });
})
}); });
if ui.input().key_pressed(Key::Escape) || ui.input().mouse.click && !button_response.clicked if ui.input().key_pressed(Key::Escape) || ui.input().mouse.click && !button_response.clicked

View file

@ -102,13 +102,15 @@ impl ScrollArea {
max_scroll_bar_width * ui.ctx().animate_bool(id, state.show_scroll) max_scroll_bar_width * ui.ctx().animate_bool(id, state.show_scroll)
}; };
let available_outer = ui.available_rect_before_wrap();
let outer_size = vec2( let outer_size = vec2(
ui.available_width(), available_outer.width(),
ui.available_size_before_wrap().y.at_most(max_height), available_outer.height().at_most(max_height),
); );
let inner_size = outer_size - vec2(current_scroll_bar_width, 0.0); let inner_size = outer_size - vec2(current_scroll_bar_width, 0.0);
let inner_rect = Rect::from_min_size(ui.available_rect_before_wrap().min, inner_size); let inner_rect = Rect::from_min_size(available_outer.min, inner_size);
let mut content_ui = ui.child_ui( let mut content_ui = ui.child_ui(
Rect::from_min_size( Rect::from_min_size(
@ -153,13 +155,14 @@ impl Prepared {
let content_size = content_ui.min_size(); let content_size = content_ui.min_size();
let inner_rect = Rect::from_min_size( let width = if inner_rect.width().is_finite() {
inner_rect.min, inner_rect.width().max(content_size.x) // Expand width to fit content
vec2( } else {
inner_rect.width().max(content_size.x), // Expand width to fit content // ScrollArea is in an infinitely wide parent
inner_rect.height(), content_size.x
), };
);
let inner_rect = Rect::from_min_size(inner_rect.min, vec2(width, inner_rect.height()));
let outer_rect = Rect::from_min_size( let outer_rect = Rect::from_min_size(
inner_rect.min, inner_rect.min,