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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
// ------------------------------
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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(®ion);
|
||||
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(®ion, child_size)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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!
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user