Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(combobox): implement text wrap for selected text #2272

Merged
merged 5 commits into from Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -18,6 +18,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
* Added `egui::gui_zoom` module with helpers for scaling the whole GUI of an app ([#2239](https://github.com/emilk/egui/pull/2239)).
* You can now put one interactive widget on top of another, and only one will get interaction at a time ([#2244](https://github.com/emilk/egui/pull/2244)).
* Add `ui.centered`.
* Added possibility to enable text wrap for the selected text of `egui::ComboBox` ([#2272](https://github.com/emilk/egui/pull/2244))

### Changed 🔧
* Panels always have a separator line, but no stroke on other sides. Their spacing has also changed slightly ([#2261](https://github.com/emilk/egui/pull/2261)).
Expand Down
31 changes: 28 additions & 3 deletions crates/egui/src/containers/combo_box.rs
Expand Up @@ -28,6 +28,7 @@ pub struct ComboBox {
selected_text: WidgetText,
width: Option<f32>,
icon: Option<IconPainter>,
wrap_enabled: bool,
}

impl ComboBox {
Expand All @@ -39,6 +40,7 @@ impl ComboBox {
selected_text: Default::default(),
width: None,
icon: None,
wrap_enabled: false,
}
}

Expand All @@ -51,6 +53,7 @@ impl ComboBox {
selected_text: Default::default(),
width: None,
icon: None,
wrap_enabled: false,
}
}

Expand All @@ -62,6 +65,7 @@ impl ComboBox {
selected_text: Default::default(),
width: None,
icon: None,
wrap_enabled: false,
}
}

Expand Down Expand Up @@ -112,6 +116,12 @@ impl ComboBox {
self
}

/// Controls whether text wrap is used for the selected text
pub fn wrap(mut self, wrap: bool) -> Self {
self.wrap_enabled = wrap;
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 @@ -134,6 +144,7 @@ impl ComboBox {
selected_text,
width,
icon,
wrap_enabled,
} = self;

let button_id = ui.make_persistent_id(id_source);
Expand All @@ -142,7 +153,14 @@ impl ComboBox {
if let Some(width) = width {
ui.spacing_mut().slider_width = width; // yes, this is ugly. Will remove later.
}
let mut ir = combo_box_dyn(ui, button_id, selected_text, menu_contents, icon);
let mut ir = combo_box_dyn(
ui,
button_id,
selected_text,
menu_contents,
icon,
wrap_enabled,
);
if let Some(label) = label {
ir.response
.widget_info(|| WidgetInfo::labeled(WidgetType::ComboBox, label.text()));
Expand Down Expand Up @@ -209,16 +227,23 @@ fn combo_box_dyn<'c, R>(
selected_text: WidgetText,
menu_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
icon: Option<IconPainter>,
wrap_enabled: bool,
) -> InnerResponse<Option<R>> {
let popup_id = button_id.with("popup");

let is_popup_open = ui.memory().is_popup_open(popup_id);
let button_response = button_frame(ui, button_id, is_popup_open, Sense::click(), |ui| {
// We don't want to change width when user selects something new
let full_minimum_width = ui.spacing().slider_width;
let full_minimum_width = wrap_enabled
.then(|| ui.available_width() - ui.spacing().item_spacing.x * 2.0)
.unwrap_or_else(|| ui.spacing().slider_width);
let icon_size = Vec2::splat(ui.spacing().icon_width);
let wrap_width = wrap_enabled
.then(|| ui.available_width() - ui.spacing().item_spacing.x - icon_size.x)
.unwrap_or(f32::INFINITY);

let galley = selected_text.into_galley(ui, Some(false), f32::INFINITY, TextStyle::Button);
let galley =
selected_text.into_galley(ui, Some(wrap_enabled), wrap_width, TextStyle::Button);

let width = galley.size().x + ui.spacing().item_spacing.x + icon_size.x;
let width = width.at_least(full_minimum_width);
Expand Down