Skip to content

Commit

Permalink
feat(combobox): implement text wrap for selected text (emilk#2272)
Browse files Browse the repository at this point in the history
* feat(combobox): implement text wrap for selected text

* chore(changelog): add line to changelog

* feat(combobox-text-wrap): make wrap boolean

- specifying a wrap width didn't really make sense so now it's boolean
- the selected text will now use the maximum available width while still
  respecting the spacing and icon coming after it

* feat(combobox-text-wrap): update changelog
  • Loading branch information
RobWalt authored and JohannesProgrammiert committed Jan 21, 2023
1 parent 5bce301 commit c88a3fd
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
* Implemented `Debug` for `egui::Context` ([#2248](https://github.com/emilk/egui/pull/2248)).
* 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)).
* Added `ui.centered`.
* Added possibility to enable text wrap for the selected text of `egui::ComboBox` ([#2272](https://github.com/emilk/egui/pull/2244))
* Added `Area::constrain` and `Window::constrain` which constrains area to the screen bounds. ([#2270](https://github.com/emilk/egui/pull/2270)).
* Added `Area::pivot` and `Window::pivot` which controls what part of the window to position. ([#2303](https://github.com/emilk/egui/pull/2303)).

Expand Down
31 changes: 28 additions & 3 deletions crates/egui/src/containers/combo_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub struct ComboBox {
selected_text: WidgetText,
width: Option<f32>,
icon: Option<IconPainter>,
wrap_enabled: bool,
}

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

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

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

Expand Down Expand Up @@ -124,6 +128,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 @@ -146,6 +156,7 @@ impl ComboBox {
selected_text,
width,
icon,
wrap_enabled,
} = self;

let button_id = ui.make_persistent_id(id_source);
Expand All @@ -154,7 +165,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 @@ -221,6 +239,7 @@ 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");

Expand All @@ -244,10 +263,16 @@ fn combo_box_dyn<'c, R>(

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

0 comments on commit c88a3fd

Please sign in to comment.