Add `Ui::columns_const()` (#4764)
# Changes
- Adds a new function `egui::Ui::columns_const()`, which is the same as
`egui::Ui::columns()` except that it uses a `const` parameter for the
column count.
- Backed by an array `[Ui; NUM_COL] instead of a `Vec<Ui>`, so fewer
allocations
- Inner closure takes in an array reference, instead of a slice
reference. This makes it possible to use pattern destructuring on the
columns, as shown in the example, and makes it more ergonomic to use
# Example
```rust
// ORIGINAL
ui.columns(2, |cols| {
cols[0].label("one");
cols[1].label("two");
});
// NEW
ui.columns_const(|[a,b]| {
a.label("one");
b.label("two");
});
```
# Checks
- [X] `cargo fmt`
- [X] `cargo clippy`
- [X] `./scripts/check.sh`
- [X] Docs
- [ ] Review
This commit is contained in:
parent
1adc3d8865
commit
1bee7bfefa
|
|
@ -2389,6 +2389,58 @@ impl Ui {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Temporarily split a [`Ui`] into several columns.
|
||||||
|
///
|
||||||
|
/// The same as [`Self::columns()`], but uses a constant for the column count.
|
||||||
|
/// This allows for compile-time bounds checking, and makes the compiler happy.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # egui::__run_test_ui(|ui| {
|
||||||
|
/// ui.columns_const(|[col_1, col_2]| {
|
||||||
|
/// col_1.label("First column");
|
||||||
|
/// col_2.label("Second column");
|
||||||
|
/// });
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn columns_const<const NUM_COL: usize, R>(
|
||||||
|
&mut self,
|
||||||
|
add_contents: impl FnOnce(&mut [Self; NUM_COL]) -> R,
|
||||||
|
) -> R {
|
||||||
|
// TODO(emilk): ensure there is space
|
||||||
|
let spacing = self.spacing().item_spacing.x;
|
||||||
|
let total_spacing = spacing * (NUM_COL as f32 - 1.0);
|
||||||
|
let column_width = (self.available_width() - total_spacing) / (NUM_COL as f32);
|
||||||
|
let top_left = self.cursor().min;
|
||||||
|
|
||||||
|
let mut columns = std::array::from_fn(|col_idx| {
|
||||||
|
let pos = top_left + vec2((col_idx as f32) * (column_width + spacing), 0.0);
|
||||||
|
let child_rect = Rect::from_min_max(
|
||||||
|
pos,
|
||||||
|
pos2(pos.x + column_width, self.max_rect().right_bottom().y),
|
||||||
|
);
|
||||||
|
let mut column_ui =
|
||||||
|
self.child_ui(child_rect, Layout::top_down_justified(Align::LEFT), None);
|
||||||
|
column_ui.set_width(column_width);
|
||||||
|
column_ui
|
||||||
|
});
|
||||||
|
let result = add_contents(&mut columns);
|
||||||
|
|
||||||
|
let mut max_column_width = column_width;
|
||||||
|
let mut max_height = 0.0;
|
||||||
|
for column in &columns {
|
||||||
|
max_column_width = max_column_width.max(column.min_rect().width());
|
||||||
|
max_height = column.min_size().y.max(max_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we fit everything next frame:
|
||||||
|
let total_required_width = total_spacing + max_column_width * (NUM_COL as f32);
|
||||||
|
|
||||||
|
let size = vec2(self.available_width().max(total_required_width), max_height);
|
||||||
|
self.advance_cursor_after_rect(Rect::from_min_size(top_left, size));
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Create something that can be drag-and-dropped.
|
/// Create something that can be drag-and-dropped.
|
||||||
///
|
///
|
||||||
/// The `id` needs to be globally unique.
|
/// The `id` needs to be globally unique.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue