1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 21:00:03 -04:00

Calculate preferred size from Galley; Pass it back up the Uis, Frames, etc..

This commit is contained in:
Lucas Meurer
2025-03-04 22:51:55 +01:00
parent 80d218cf71
commit 166e8e2092
30 changed files with 198 additions and 92 deletions

View File

@@ -613,7 +613,7 @@ impl Prepared {
..
} = self;
state.size = Some(content_ui.placer().min_item_size());
state.size = Some(content_ui.intrinsic_size());
dbg!(state.size);

View File

@@ -18,7 +18,7 @@ pub(crate) struct InnerState {
open_height: Option<f32>,
}
/// This is a a building block for building collapsing regions.
/// This is a building block for building collapsing regions.
///
/// It is used by [`CollapsingHeader`] and [`crate::Window`], but can also be used on its own.
///
@@ -87,7 +87,7 @@ impl CollapsingState {
ui: &mut Ui,
button_size: Vec2,
) -> Response {
let (_id, rect) = ui.allocate_space(button_size);
let (_id, rect) = ui.allocate_space(button_size, Vec2::ZERO); // TODO
let response = ui.interact(rect, self.id, Sense::click());
response.widget_info(|| {
WidgetInfo::labeled(
@@ -117,7 +117,7 @@ impl CollapsingState {
icon_fn: impl FnOnce(&mut Ui, f32, &Response) + 'static,
) -> Response {
let size = vec2(ui.spacing().indent, ui.spacing().icon_width);
let (_id, rect) = ui.allocate_space(size);
let (_id, rect) = ui.allocate_space(size, Vec2::ZERO); // TODO
let response = ui.interact(rect, self.id, Sense::click());
if response.clicked() {
self.toggle(ui);
@@ -554,7 +554,7 @@ impl CollapsingHeader {
let mut desired_size = vec2(desired_width, galley.size().y + 2.0 * button_padding.y);
desired_size = desired_size.at_least(ui.spacing().interact_size);
let (_, rect) = ui.allocate_space(desired_size);
let (_, rect) = ui.allocate_space(desired_size, desired_size); // TODO
let mut header_response = ui.interact(rect, id, Sense::click());
let text_pos = pos2(

View File

@@ -340,7 +340,7 @@ fn combo_box_dyn<'c, R>(
let actual_width = (galley.size().x + icon_spacing + icon_size.x).at_least(minimum_width);
let actual_height = galley.size().y.max(icon_size.y);
let (_, rect) = ui.allocate_space(Vec2::new(actual_width, actual_height));
let (_, rect) = ui.allocate_space(Vec2::new(actual_width, actual_height), Vec2::ZERO); // TODO
let button_rect = ui.min_rect().expand2(ui.spacing().button_padding);
let response = ui.interact(button_rect, button_id, Sense::click());
// response.active |= is_popup_open;
@@ -444,7 +444,7 @@ fn button_frame(
);
}
ui.advance_cursor_after_rect(outer_rect);
ui.advance_cursor_after_rect(outer_rect, Vec2::ZERO); // TODO
response
}

View File

@@ -473,7 +473,11 @@ impl Prepared {
///
/// This can be called before or after [`Self::paint`].
pub fn allocate_space(&self, ui: &mut Ui) -> Response {
ui.allocate_rect(self.outer_rect(), Sense::hover())
ui.allocate_rect(
self.outer_rect(),
Sense::hover(),
self.content_ui.intrinsic_size() + self.frame.total_margin().sum(),
)
}
/// Paint the frame.

View File

@@ -568,8 +568,7 @@ impl<'a> Popup<'a> {
let mut response = area.show(&ctx, |ui| {
style.apply(ui.style_mut());
// frame.show(ui, content).inner
content(ui)
frame.show(ui, content).inner
});
let closed_by_click = match close_behavior {

View File

@@ -331,7 +331,10 @@ impl Resize {
size[d] = state.last_content_size[d];
}
}
ui.advance_cursor_after_rect(Rect::from_min_size(content_ui.min_rect().min, size));
ui.advance_cursor_after_rect(
Rect::from_min_size(content_ui.min_rect().min, size),
Vec2::ZERO,
); // TODO
// ------------------------------

View File

@@ -1245,7 +1245,7 @@ impl Prepared {
}
}
ui.advance_cursor_after_rect(outer_rect);
ui.advance_cursor_after_rect(outer_rect, Vec2::ZERO); // TODO
if show_scroll_this_frame != state.show_scroll {
ui.ctx().request_repaint();

View File

@@ -1,4 +1,4 @@
use emath::Align;
use emath::{Align, Vec2};
use crate::{Layout, Ui, UiBuilder};
@@ -84,7 +84,7 @@ impl Sides {
let result_left;
let result_right;
let left_rect = {
let (left_rect, left_preferred_size) = {
let left_max_rect = top_rect;
let mut left_ui = ui.new_child(
UiBuilder::new()
@@ -92,10 +92,10 @@ impl Sides {
.layout(Layout::left_to_right(Align::Center)),
);
result_left = add_left(&mut left_ui);
left_ui.min_rect()
(left_ui.min_rect(), left_ui.intrinsic_size())
};
let right_rect = {
let (right_rect, right_preferred_size) = {
let right_max_rect = top_rect.with_min_x(left_rect.max.x);
let mut right_ui = ui.new_child(
UiBuilder::new()
@@ -103,7 +103,7 @@ impl Sides {
.layout(Layout::right_to_left(Align::Center)),
);
result_right = add_right(&mut right_ui);
right_ui.min_rect()
(right_ui.min_rect(), right_ui.intrinsic_size())
};
let mut final_rect = left_rect.union(right_rect);
@@ -118,7 +118,12 @@ impl Sides {
final_rect.max.x = final_rect.max.x.max(left_rect.min.x + min_width);
}
ui.advance_cursor_after_rect(final_rect);
let preferred_size = Vec2::new(
left_preferred_size.x + spacing + right_preferred_size.x,
left_preferred_size.y.max(right_preferred_size.y),
);
ui.advance_cursor_after_rect(final_rect, preferred_size);
(result_left, result_right)
}

View File

@@ -1,8 +1,10 @@
//! Showing UI:s for egui/epaint types.
use crate::{
epaint, memory, pos2, remap_clamp, vec2, Color32, CursorIcon, FontFamily, FontId, Label, Mesh,
NumExt, Rect, Response, Sense, Shape, Slider, TextStyle, TextWrapMode, Ui, Widget,
};
use emath::Vec2;
pub fn font_family_ui(ui: &mut Ui, font_family: &mut FontFamily) {
let families = ui.fonts(|f| f.families());
@@ -42,7 +44,7 @@ pub(crate) fn font_texture_ui(ui: &mut Ui, [width, height]: [usize; 2]) -> Respo
if size.x > ui.available_width() {
size *= ui.available_width() / size.x;
}
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
let (rect, response) = ui.allocate_at_least(size, Sense::hover(), Vec2::ZERO); // TODO
let mut mesh = Mesh::default();
mesh.add_rect_with_uv(rect, [pos2(0.0, 0.0), pos2(1.0, 1.0)].into(), color);
ui.painter().add(Shape::mesh(mesh));
@@ -53,7 +55,7 @@ pub(crate) fn font_texture_ui(ui: &mut Ui, [width, height]: [usize; 2]) -> Respo
.on_hover_cursor(CursorIcon::ZoomIn)
.on_hover_ui_at_pointer(|ui| {
if let Some(pos) = ui.ctx().pointer_latest_pos() {
let (_id, zoom_rect) = ui.allocate_space(vec2(128.0, 128.0));
let (_id, zoom_rect) = ui.allocate_space(vec2(128.0, 128.0), Vec2::ZERO); // TODO
let u = remap_clamp(pos.x, rect.x_range(), 0.0..=tex_w);
let v = remap_clamp(pos.y, rect.y_range(), 0.0..=tex_h);

View File

@@ -46,7 +46,7 @@ pub(crate) struct Region {
/// The cursor can thus be `style.spacing.item_spacing` pixels outside of the `min_rect`.
pub(crate) cursor: Rect,
pub min_item_size: Vec2,
pub intrinsic_size: Vec2,
}
impl Region {
@@ -428,7 +428,7 @@ impl Layout {
min_rect: Rect::NOTHING, // temporary
max_rect,
cursor: self.initial_cursor(max_rect),
min_item_size: Vec2::default(),
intrinsic_size: Vec2::default(),
};
let seed = self.next_widget_position(&region);
region.min_rect = Rect::from_center_size(seed, Vec2::ZERO);
@@ -532,7 +532,7 @@ impl Layout {
mut cursor,
mut max_rect,
min_rect,
min_item_size,
intrinsic_size: min_item_size,
} = *region;
match self.main_dir {
@@ -594,7 +594,7 @@ impl Layout {
min_rect,
max_rect,
cursor,
min_item_size,
intrinsic_size: min_item_size,
};
self.next_frame_ignore_wrap(&region, child_size)

View File

@@ -563,7 +563,7 @@ impl SubMenuButton {
let mut desired_size = text_and_icon_size + 2.0 * button_padding;
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);
let (rect, response) = ui.allocate_at_least(desired_size, sense);
let (rect, response) = ui.allocate_at_least(desired_size, sense, Vec2::ZERO); // TODO
response.widget_info(|| {
crate::WidgetInfo::labeled(
crate::WidgetType::Button,

View File

@@ -1,4 +1,4 @@
use crate::{grid, vec2, Layout, Painter, Pos2, Rect, Region, Vec2};
use crate::{grid, vec2, Direction, Layout, Painter, Pos2, Rect, Region, Vec2};
#[cfg(debug_assertions)]
use crate::{Align2, Color32, Stroke};
@@ -163,7 +163,7 @@ impl Placer {
frame_rect: Rect,
widget_rect: Rect,
item_spacing: Vec2,
desired_size: Vec2,
intrinsic_size: Vec2,
) {
debug_assert!(!frame_rect.any_nan());
debug_assert!(!widget_rect.any_nan());
@@ -180,15 +180,27 @@ impl Placer {
);
}
self.region.min_item_size = self.region.min_item_size.max(desired_size);
if self.layout.is_horizontal() {
if self.region.intrinsic_size.x != 0.0 {
self.region.intrinsic_size.x += item_spacing.x;
}
self.region.intrinsic_size.x += intrinsic_size.x;
self.region.intrinsic_size.y = self.region.intrinsic_size.y.max(intrinsic_size.y);
} else {
if self.region.intrinsic_size.y != 0.0 {
self.region.intrinsic_size.y += item_spacing.y;
}
self.region.intrinsic_size.x = self.region.intrinsic_size.x.max(intrinsic_size.x);
self.region.intrinsic_size.y += intrinsic_size.y;
}
self.expand_to_include_rect(frame_rect); // e.g. for centered layouts: pretend we used whole frame
self.region.sanity_check();
}
pub(crate) fn min_item_size(&self) -> Vec2 {
self.region.min_item_size
pub(crate) fn intrinsic_size(&self) -> Vec2 {
self.region.intrinsic_size
}
/// Move to the next row in a grid layout or wrapping layout.

View File

@@ -2548,7 +2548,7 @@ impl Widget for &mut Stroke {
ui.color_edit_button_srgba(color);
// stroke preview:
let (_id, stroke_rect) = ui.allocate_space(ui.spacing().interact_size);
let (_id, stroke_rect) = ui.allocate_space(ui.spacing().interact_size, Vec2::ZERO); // TODO
let left = stroke_rect.left_center();
let right = stroke_rect.right_center();
ui.painter().line_segment([left, right], (*width, *color));

View File

@@ -1140,6 +1140,12 @@ impl Ui {
if self.should_close() {
response.set_close();
}
response.intrinsic_size = Some(self.intrinsic_size());
// self.ctx().debug_painter().debug_rect(
// Rect::from_min_size(self.min_rect().min, self.intrinsic_size()),
// Color32::GREEN,
// "",
// );
response
}
@@ -1296,8 +1302,13 @@ impl Ui {
/// ui.painter().rect_stroke(response.rect, 0.0, (1.0, egui::Color32::WHITE), egui::StrokeKind::Inside);
/// # });
/// ```
pub fn allocate_response(&mut self, desired_size: Vec2, sense: Sense) -> Response {
let (id, rect) = self.allocate_space(desired_size);
pub fn allocate_response(
&mut self,
desired_size: Vec2,
sense: Sense,
desired_size_2: Vec2,
) -> Response {
let (id, rect) = self.allocate_space(desired_size, desired_size_2);
let mut response = self.interact(rect, id, sense);
response.intrinsic_size = Some(desired_size);
response
@@ -1309,7 +1320,7 @@ impl Ui {
/// This means that if this is a narrow widget in a wide justified layout, then
/// the widget will react to interactions outside the returned [`Rect`].
pub fn allocate_exact_size(&mut self, desired_size: Vec2, sense: Sense) -> (Rect, Response) {
let response = self.allocate_response(desired_size, sense);
let response = self.allocate_response(desired_size, sense, desired_size); // TODO?
let rect = self
.placer
.align_size_within_rect(desired_size, response.rect);
@@ -1319,8 +1330,15 @@ impl Ui {
/// Allocate at least as much space as needed, and interact with that rect.
///
/// The returned [`Rect`] will be the same size as `Response::rect`.
pub fn allocate_at_least(&mut self, desired_size: Vec2, sense: Sense) -> (Rect, Response) {
let response = self.allocate_response(desired_size, sense);
// TODO: Is this still needed?
// TODO: Awful naming conflict
pub fn allocate_at_least(
&mut self,
desired_size: Vec2,
sense: Sense,
desired_size_2: Vec2,
) -> (Rect, Response) {
let response = self.allocate_response(desired_size, sense, desired_size_2);
(response.rect, response)
}
@@ -1345,11 +1363,11 @@ impl Ui {
/// let response = ui.interact(rect, id, egui::Sense::click());
/// # });
/// ```
pub fn allocate_space(&mut self, desired_size: Vec2) -> (Id, Rect) {
pub fn allocate_space(&mut self, desired_size: Vec2, desired_size_2: Vec2) -> (Id, Rect) {
#[cfg(debug_assertions)]
let original_available = self.available_size_before_wrap();
let rect = self.allocate_space_impl(desired_size);
let rect = self.allocate_space_impl(desired_size, desired_size_2);
#[cfg(debug_assertions)]
{
@@ -1396,14 +1414,19 @@ impl Ui {
/// Reserve this much space and move the cursor.
/// Returns where to put the widget.
fn allocate_space_impl(&mut self, desired_size: Vec2) -> Rect {
fn allocate_space_impl(&mut self, desired_size: Vec2, desired_size_2: Vec2) -> Rect {
// self.ctx().debug_painter().debug_rect(
// Rect::from_min_size(self.cursor().min, desired_size_2),
// Color32::YELLOW,
// "",
// );
let item_spacing = self.spacing().item_spacing;
let frame_rect = self.placer.next_space(desired_size, item_spacing);
debug_assert!(!frame_rect.any_nan());
let widget_rect = self.placer.justify_and_align(frame_rect, desired_size);
self.placer
.advance_after_rects(frame_rect, widget_rect, item_spacing, desired_size);
.advance_after_rects(frame_rect, widget_rect, item_spacing, desired_size_2);
register_rect(self, widget_rect);
@@ -1414,20 +1437,20 @@ impl Ui {
///
/// Ignore the layout of the [`Ui`]: just put my widget here!
/// The layout cursor will advance to past this `rect`.
pub fn allocate_rect(&mut self, rect: Rect, sense: Sense) -> Response {
pub fn allocate_rect(&mut self, rect: Rect, sense: Sense, intrinsic_size: Vec2) -> Response {
let rect = rect.round_ui();
let id = self.advance_cursor_after_rect(rect);
let id = self.advance_cursor_after_rect(rect, intrinsic_size);
self.interact(rect, id, sense)
}
/// Allocate a rect without interacting with it.
pub fn advance_cursor_after_rect(&mut self, rect: Rect) -> Id {
pub fn advance_cursor_after_rect(&mut self, rect: Rect, intrinsic_size: Vec2) -> Id {
debug_assert!(!rect.any_nan());
let rect = rect.round_ui();
let item_spacing = self.spacing().item_spacing;
self.placer
.advance_after_rects(rect, rect, item_spacing, rect.size());
.advance_after_rects(rect, rect, item_spacing, intrinsic_size);
register_rect(self, rect);
let id = Id::new(self.next_auto_id_salt);
@@ -1555,7 +1578,7 @@ impl Ui {
/// # });
/// ```
pub fn allocate_painter(&mut self, desired_size: Vec2, sense: Sense) -> (Response, Painter) {
let response = self.allocate_response(desired_size, sense);
let response = self.allocate_response(desired_size, sense, desired_size); // TODO?
let clip_rect = self.clip_rect().intersect(response.rect); // Make sure we don't paint out of bounds
let painter = self.painter().with_clip_rect(clip_rect);
(response, painter)
@@ -2414,24 +2437,17 @@ impl Ui {
self.next_auto_id_salt = next_auto_id_salt; // HACK: we want `scope` to only increment this once, so that `ui.scope` is equivalent to `ui.allocate_space`.
let ret = add_contents(&mut child_ui);
let mut response = child_ui.remember_min_rect();
self.advance_cursor_after_rect(child_ui.min_rect());
match self.layout().is_horizontal() {
true => {
response.intrinsic_size = Some(Vec2::new(
response.rect.width(),
self.placer.min_item_size().y,
));
}
false => {
response.intrinsic_size = Some(Vec2::new(
self.placer.min_item_size().x,
response.rect.height(),
));
}
}
self.advance_cursor_after_rect(
child_ui.min_rect(),
response.intrinsic_size.unwrap_or(response.rect.size()),
);
InnerResponse::new(ret, response)
}
pub(crate) fn intrinsic_size(&self) -> Vec2 {
self.placer.intrinsic_size()
}
/// Redirect shapes to another paint layer.
///
/// ```
@@ -2520,7 +2536,11 @@ impl Ui {
}
}
let response = self.allocate_rect(child_ui.min_rect(), Sense::hover());
let response = self.allocate_rect(
child_ui.min_rect(),
Sense::hover(),
child_ui.intrinsic_size(),
); // TODO
InnerResponse::new(ret, response)
}
@@ -2810,7 +2830,7 @@ impl Ui {
let total_required_width = total_spacing + max_column_width * (num_columns 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));
self.advance_cursor_after_rect(Rect::from_min_size(top_left, size), Vec2::ZERO); // TODO
result
}
@@ -2865,7 +2885,7 @@ impl Ui {
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));
self.advance_cursor_after_rect(Rect::from_min_size(top_left, size), Vec2::ZERO); // TODO
result
}

View File

@@ -295,7 +295,25 @@ impl Widget for Button<'_> {
}
desired_size = desired_size.at_least(min_size);
let (rect, mut response) = ui.allocate_at_least(desired_size, sense);
// TODO: Missing a lot
let mut desired_size_2 = galley
.as_ref()
.map_or(Vec2::ZERO, |galley| galley.desired_size());
let mut desired_right_galley_size = right_galley.as_ref().map_or(Vec2::ZERO, |galley| {
galley.desired_size() + Vec2::new(gap_before_right_text, 0.0)
});
desired_size_2.x += desired_right_galley_size.x;
desired_size_2.y = desired_size_2.y.max(desired_right_galley_size.y);
desired_size_2 += 2.0 * button_padding;
// dbg!(desired_size_2);
// ui.ctx().debug_painter().debug_rect(
// Rect::from_min_size(ui.cursor().min, desired_size_2),
// Color32::from_rgb(100, 0, 0),
// "",
// );
let (rect, mut response) = ui.allocate_at_least(desired_size, sense, desired_size_2);
response.widget_info(|| {
if let Some(galley) = &galley {
WidgetInfo::labeled(WidgetType::Button, ui.is_enabled(), galley.text())

View File

@@ -58,7 +58,7 @@ pub fn show_color(ui: &mut Ui, color: impl Into<Color32>, desired_size: Vec2) ->
}
fn show_color32(ui: &mut Ui, color: Color32, desired_size: Vec2) -> Response {
let (rect, response) = ui.allocate_at_least(desired_size, Sense::hover());
let (rect, response) = ui.allocate_at_least(desired_size, Sense::hover(), desired_size);
if ui.is_rect_visible(rect) {
show_color_at(ui.painter(), color, rect);
}
@@ -116,7 +116,8 @@ fn color_slider_1d(ui: &mut Ui, value: &mut f32, color_at: impl Fn(f32) -> Color
#![allow(clippy::identity_op)]
let desired_size = vec2(ui.spacing().slider_width, ui.spacing().interact_size.y);
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click_and_drag());
let (rect, response) =
ui.allocate_at_least(desired_size, Sense::click_and_drag(), desired_size);
if let Some(mpos) = response.interact_pointer_pos() {
*value = remap_clamp(mpos.x, rect.left()..=rect.right(), 0.0..=1.0);
@@ -183,7 +184,8 @@ fn color_slider_2d(
color_at: impl Fn(f32, f32) -> Color32,
) -> Response {
let desired_size = Vec2::splat(ui.spacing().slider_width);
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click_and_drag());
let (rect, response) =
ui.allocate_at_least(desired_size, Sense::click_and_drag(), desired_size);
if let Some(mpos) = response.interact_pointer_pos() {
*x_value = remap_clamp(mpos.x, rect.left()..=rect.right(), 0.0..=1.0);

View File

@@ -214,10 +214,10 @@ impl Label {
assert!(!galley.rows.is_empty(), "Galleys are never empty");
// collect a response from many rows:
let rect = galley.rows[0].rect.translate(vec2(pos.x, pos.y));
let mut response = ui.allocate_rect(rect, sense);
let mut response = ui.allocate_rect(rect, sense, galley.desired_size());
for row in galley.rows.iter().skip(1) {
let rect = row.rect.translate(vec2(pos.x, pos.y));
response |= ui.allocate_rect(rect, sense);
response |= ui.allocate_rect(rect, sense, galley.desired_size());
}
(pos, galley, response)
} else {

View File

@@ -48,7 +48,8 @@ impl Widget for SelectableLabel {
let mut desired_size = total_extra + galley.size();
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
let (rect, response) =
ui.allocate_at_least(desired_size, Sense::click(), galley.desired_size());
response.widget_info(|| {
WidgetInfo::selected(
WidgetType::SelectableLabel,

View File

@@ -108,7 +108,7 @@ impl Widget for Separator {
vec2(spacing, available_space.y)
};
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
let (rect, response) = ui.allocate_at_least(size, Sense::hover(), size);
if ui.is_rect_visible(response.rect) {
let stroke = ui.visuals().widgets.noninteractive.bg_stroke;

View File

@@ -650,7 +650,7 @@ impl Slider<'_> {
SliderOrientation::Horizontal => vec2(ui.spacing().slider_width, thickness),
SliderOrientation::Vertical => vec2(thickness, ui.spacing().slider_width),
};
ui.allocate_response(desired_size, Sense::drag())
ui.allocate_response(desired_size, Sense::drag(), desired_size)
}
/// Just the slider, no text

View File

@@ -541,7 +541,7 @@ impl TextEdit<'_> {
let desired_height = (desired_height_rows.at_least(1) as f32) * row_height;
let desired_inner_size = vec2(desired_inner_width, galley.size().y.max(desired_height));
let desired_outer_size = (desired_inner_size + margin.sum()).at_least(min_size);
let (auto_id, outer_rect) = ui.allocate_space(desired_outer_size);
let (auto_id, outer_rect) = ui.allocate_space(desired_outer_size, desired_outer_size);
let rect = outer_rect - margin; // inner rect (excluding frame/margin).
let id = id.unwrap_or_else(|| {
@@ -739,6 +739,7 @@ impl TextEdit<'_> {
ui.allocate_rect(
Rect::from_min_size(outer_rect.max, extra_size),
Sense::hover(),
response.intrinsic_size.unwrap(),
);
}
}

View File

@@ -1,3 +1,4 @@
use eframe::emath::Vec2;
use egui::util::History;
pub struct FrameHistory {
@@ -62,7 +63,7 @@ impl FrameHistory {
// TODO(emilk): we should not use `slider_width` as default graph width.
let height = ui.spacing().slider_width;
let size = vec2(ui.available_size_before_wrap().x, height);
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
let (rect, response) = ui.allocate_at_least(size, Sense::hover(), Vec2::ZERO); // TODO
let style = ui.style().noninteractive();
let graph_top_cpu_usage = 0.010;

View File

@@ -2,7 +2,7 @@ use egui::{
containers::{Frame, Window},
emath, epaint,
epaint::PathStroke,
hex_color, lerp, pos2, remap, vec2, Color32, Context, Pos2, Rect, Ui,
hex_color, lerp, pos2, remap, vec2, Color32, Context, Pos2, Rect, Ui, Vec2,
};
#[derive(Default)]
@@ -43,7 +43,7 @@ impl crate::View for DancingStrings {
let time = ui.input(|i| i.time);
let desired_size = ui.available_width() * vec2(1.0, 0.35);
let (_id, rect) = ui.allocate_space(desired_size);
let (_id, rect) = ui.allocate_space(desired_size, Vec2::ZERO); // TODO
let to_screen =
emath::RectTransform::from_to(Rect::from_x_y_ranges(0.0..=1.0, -1.0..=1.0), rect);

View File

@@ -189,7 +189,8 @@ impl View for MiscDemoWindow {
for i in 0..100 {
let r = i as f32 * 0.5;
let size = Vec2::splat(2.0 * r + 5.0);
let (rect, _response) = ui.allocate_at_least(size, Sense::hover());
let (rect, _response) =
ui.allocate_at_least(size, Sense::hover(), Vec2::ZERO); // TODO
ui.painter()
.circle_filled(rect.center(), r, ui.visuals().text_color());
}
@@ -384,7 +385,7 @@ impl BoxPainting {
ui.horizontal_wrapped(|ui| {
for _ in 0..self.num_boxes {
let (rect, _response) = ui.allocate_at_least(self.size, Sense::hover());
let (rect, _response) = ui.allocate_at_least(self.size, Sense::hover(), Vec2::ZERO); // TODO
ui.painter().rect(
rect,
self.corner_radius,

View File

@@ -225,7 +225,7 @@ fn huge_content_painter(ui: &mut egui::Ui) {
used_rect = used_rect.union(text_rect);
}
ui.allocate_rect(used_rect, Sense::hover()); // make sure it is visible!
ui.allocate_rect(used_rect, Sense::hover(), Vec2::ZERO); // TODO // make sure it is visible!
});
}

View File

@@ -1,3 +1,5 @@
use egui::Vec2;
pub struct WindowResizeTest {
text: String,
}
@@ -91,7 +93,7 @@ impl crate::Demo for WindowResizeTest {
ui.vertical_centered(|ui| {
ui.add(crate::egui_github_link_file!());
});
ui.allocate_space(ui.available_size());
ui.allocate_space(ui.available_size(), Vec2::ZERO); // TODO
});
}
}

View File

@@ -269,7 +269,7 @@ impl ColorTest {
}
fn vertex_gradient(ui: &mut Ui, bg_fill: Color32, gradient: &Gradient) -> Response {
let (rect, response) = ui.allocate_at_least(GRADIENT_SIZE, Sense::hover());
let (rect, response) = ui.allocate_at_least(GRADIENT_SIZE, Sense::hover(), Vec2::ZERO); // TODO
let rect = rect.round_to_pixels(ui.pixels_per_point());
if bg_fill != Default::default() {
let mut mesh = Mesh::default();

View File

@@ -1,4 +1,4 @@
use egui::{emath::GuiRounding, Id, Pos2, Rect, Response, Sense, Ui, UiBuilder};
use egui::{emath::GuiRounding, Id, Pos2, Rect, Response, Sense, Ui, UiBuilder, Vec2};
#[derive(Clone, Copy)]
pub(crate) enum CellSize {
@@ -166,7 +166,8 @@ impl<'l> StripLayout<'l> {
self.set_pos(allocation_rect);
self.ui.advance_cursor_after_rect(allocation_rect);
self.ui
.advance_cursor_after_rect(allocation_rect, Vec2::ZERO); // TODO
let response = child_ui.response();
@@ -192,7 +193,7 @@ impl<'l> StripLayout<'l> {
let before = self.cursor;
self.cursor += delta;
let rect = Rect::from_two_pos(before, self.cursor);
self.ui.allocate_rect(rect, Sense::hover());
self.ui.allocate_rect(rect, Sense::hover(), Vec2::ZERO); // TODO
}
/// Return the Ui to which the contents where added
@@ -243,6 +244,6 @@ impl<'l> StripLayout<'l> {
rect.set_right(self.max.x);
rect.set_bottom(self.max.y);
self.ui.allocate_rect(rect, Sense::hover())
self.ui.allocate_rect(rect, Sense::hover(), Vec2::ZERO) // TODO
}
}

View File

@@ -726,6 +726,31 @@ impl Galley {
pub fn size(&self) -> Vec2 {
self.rect.size()
}
// TODO: Instead return Option<Vec2>?
pub fn desired_size(&self) -> Vec2 {
let mut current_width: f32 = 0.0;
let mut widest_width: f32 = 0.0;
let mut height = self.rows.first().map_or(0.0, |row| row.height());
for row in &self.rows {
if current_width != 0.0 {
let space = row.glyphs.last();
if let Some(space) = space {
if space.chr.is_whitespace() {
// TODO: Needed or not? Doesn't seem like it's needed
// current_width += space.advance_width;
}
}
}
current_width += row.rect.width();
widest_width = widest_width.max(current_width);
if row.ends_with_newline {
height += row.height();
current_width = 0.0;
}
}
vec2(widest_width, height)
}
}
impl AsRef<str> for Galley {

View File

@@ -19,6 +19,7 @@ fn main() -> eframe::Result {
let mut checked = true;
eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
ctx.options_mut(|o| o.max_passes = 1.try_into().unwrap());
egui::CentralPanel::default().show(ctx, |ui| {
// ui.heading("My egui Application");
// ui.horizontal(|ui| {
@@ -32,6 +33,7 @@ fn main() -> eframe::Result {
// }
// ui.label(format!("Hello '{name}', age {age}"));
std::thread::sleep(std::time::Duration::from_millis(100));
let response = ui.button("Hiiii");
let text = if checked {
@@ -46,13 +48,20 @@ fn main() -> eframe::Result {
ui.button("Hiiii");
if Button::new(text)
.wrap_mode(TextWrapMode::Extend)
.ui(ui)
.clicked()
{
checked = !checked;
}
ui.horizontal(|ui| {
ui.vertical(|ui| {
if Button::new(text)
// .wrap_mode(TextWrapMode::Extend)
.ui(ui)
.clicked()
{
checked = !checked;
}
ui.button("Button1");
});
ui.button("Button2")
});
ui.button("Some other button");
});