[culling] full widget culling
This commit is contained in:
parent
7abb9a2814
commit
9112834f20
16 changed files with 179 additions and 109 deletions
|
@ -180,6 +180,8 @@ impl CollapsingHeader {
|
|||
|
||||
let id = ui.make_persistent_id(id_source);
|
||||
|
||||
let mut state = State::from_memory_with_default_open(ui.ctx(), id, default_open);
|
||||
|
||||
let available = ui.available_finite();
|
||||
let text_pos = available.min + vec2(ui.style().spacing.indent, 0.0);
|
||||
let galley = label.layout_width(ui, available.right() - text_pos.x);
|
||||
|
@ -192,53 +194,57 @@ impl CollapsingHeader {
|
|||
galley.size.y + 2.0 * ui.style().spacing.button_padding.y,
|
||||
);
|
||||
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
|
||||
let header_response = ui.interact(rect, id, Sense::click());
|
||||
let text_pos = pos2(
|
||||
text_pos.x,
|
||||
header_response.rect.center().y - galley.size.y / 2.0,
|
||||
);
|
||||
let header_response;
|
||||
|
||||
let mut state = State::from_memory_with_default_open(ui.ctx(), id, default_open);
|
||||
if header_response.clicked {
|
||||
state.toggle(ui);
|
||||
if let Some(rect) = ui.request_space(desired_size) {
|
||||
header_response = ui.interact(rect, id, Sense::click());
|
||||
let text_pos = pos2(
|
||||
text_pos.x,
|
||||
header_response.rect.center().y - galley.size.y / 2.0,
|
||||
);
|
||||
|
||||
if header_response.clicked {
|
||||
state.toggle(ui);
|
||||
}
|
||||
|
||||
let bg_index = ui.painter().add(PaintCmd::Noop);
|
||||
|
||||
{
|
||||
let (mut icon_rect, _) = ui.style().spacing.icon_rectangles(header_response.rect);
|
||||
icon_rect.set_center(pos2(
|
||||
header_response.rect.left() + ui.style().spacing.indent / 2.0,
|
||||
header_response.rect.center().y,
|
||||
));
|
||||
let icon_response = Response {
|
||||
rect: icon_rect,
|
||||
..header_response.clone()
|
||||
};
|
||||
let openness = state.openness(ui.ctx(), id);
|
||||
paint_icon(ui, openness, &icon_response);
|
||||
}
|
||||
|
||||
let painter = ui.painter();
|
||||
painter.galley(
|
||||
text_pos,
|
||||
galley,
|
||||
label.text_style_or_default(ui.style()),
|
||||
ui.style().interact(&header_response).text_color(),
|
||||
);
|
||||
|
||||
painter.set(
|
||||
bg_index,
|
||||
PaintCmd::Rect {
|
||||
rect: header_response.rect,
|
||||
corner_radius: ui.style().interact(&header_response).corner_radius,
|
||||
fill: ui.style().interact(&header_response).bg_fill,
|
||||
stroke: Default::default(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
header_response = Default::default();
|
||||
}
|
||||
|
||||
let bg_index = ui.painter().add(PaintCmd::Noop);
|
||||
|
||||
{
|
||||
let (mut icon_rect, _) = ui.style().spacing.icon_rectangles(header_response.rect);
|
||||
icon_rect.set_center(pos2(
|
||||
header_response.rect.left() + ui.style().spacing.indent / 2.0,
|
||||
header_response.rect.center().y,
|
||||
));
|
||||
let icon_response = Response {
|
||||
rect: icon_rect,
|
||||
..header_response.clone()
|
||||
};
|
||||
let openness = state.openness(ui.ctx(), id);
|
||||
paint_icon(ui, openness, &icon_response);
|
||||
}
|
||||
|
||||
let painter = ui.painter();
|
||||
painter.galley(
|
||||
text_pos,
|
||||
galley,
|
||||
label.text_style_or_default(ui.style()),
|
||||
ui.style().interact(&header_response).text_color(),
|
||||
);
|
||||
|
||||
painter.set(
|
||||
bg_index,
|
||||
PaintCmd::Rect {
|
||||
rect: header_response.rect,
|
||||
corner_radius: ui.style().interact(&header_response).corner_radius,
|
||||
fill: ui.style().interact(&header_response).bg_fill,
|
||||
stroke: Default::default(),
|
||||
},
|
||||
);
|
||||
|
||||
Prepared {
|
||||
id,
|
||||
header_response,
|
||||
|
|
|
@ -38,7 +38,7 @@ pub fn combo_box(
|
|||
let advance = full_minimum_width - icon_width - ui.min_rect().width();
|
||||
ui.advance_cursor(advance.at_least(0.0));
|
||||
|
||||
let icon_rect = ui.allocate_space(Vec2::splat(icon_width));
|
||||
let icon_rect = unwrap_or_return_default!(ui.request_space(Vec2::splat(icon_width)));
|
||||
let button_rect = ui.min_rect().expand2(ui.style().spacing.button_padding);
|
||||
let mut response = ui.interact(button_rect, button_id, Sense::click());
|
||||
response.active |= button_active;
|
||||
|
@ -91,6 +91,7 @@ fn button_frame(
|
|||
add_contents(&mut content_ui);
|
||||
|
||||
let outer_rect = Rect::from_min_max(outer_rect_bounds.min, content_ui.min_rect().max + margin);
|
||||
ui.allocate_space(outer_rect.size());
|
||||
|
||||
let mut response = ui.interact(outer_rect, id, sense);
|
||||
response.active |= button_active;
|
||||
|
@ -106,8 +107,6 @@ fn button_frame(
|
|||
},
|
||||
);
|
||||
|
||||
ui.allocate_space(outer_rect.size());
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
|
|
|
@ -436,7 +436,7 @@ impl Context {
|
|||
if id.is_none() || sense == Sense::nothing() || !layer_id.allow_interaction() {
|
||||
// Not interested or allowed input:
|
||||
return Response {
|
||||
ctx: self.clone(),
|
||||
ctx: Some(self.clone()),
|
||||
sense,
|
||||
rect,
|
||||
hovered,
|
||||
|
@ -461,7 +461,7 @@ impl Context {
|
|||
if self.input.mouse.pressed {
|
||||
if hovered {
|
||||
let mut response = Response {
|
||||
ctx: self.clone(),
|
||||
ctx: Some(self.clone()),
|
||||
sense,
|
||||
rect,
|
||||
hovered: true,
|
||||
|
@ -491,7 +491,7 @@ impl Context {
|
|||
} else {
|
||||
// miss
|
||||
Response {
|
||||
ctx: self.clone(),
|
||||
ctx: Some(self.clone()),
|
||||
sense,
|
||||
rect,
|
||||
hovered,
|
||||
|
@ -504,7 +504,7 @@ impl Context {
|
|||
} else if self.input.mouse.released {
|
||||
let clicked = hovered && active && self.input.mouse.could_be_click;
|
||||
Response {
|
||||
ctx: self.clone(),
|
||||
ctx: Some(self.clone()),
|
||||
sense,
|
||||
rect,
|
||||
hovered,
|
||||
|
@ -515,7 +515,7 @@ impl Context {
|
|||
}
|
||||
} else if self.input.mouse.down {
|
||||
Response {
|
||||
ctx: self.clone(),
|
||||
ctx: Some(self.clone()),
|
||||
sense,
|
||||
rect,
|
||||
hovered: hovered && active,
|
||||
|
@ -526,7 +526,7 @@ impl Context {
|
|||
}
|
||||
} else {
|
||||
Response {
|
||||
ctx: self.clone(),
|
||||
ctx: Some(self.clone()),
|
||||
sense,
|
||||
rect,
|
||||
hovered,
|
||||
|
|
|
@ -105,7 +105,9 @@ impl FrameHistory {
|
|||
|
||||
// TODO: we should not use `slider_width` as default graph width.
|
||||
let height = ui.style().spacing.slider_width;
|
||||
let rect = ui.allocate_space(vec2(ui.available_finite().width(), height));
|
||||
let rect = unwrap_or_return_default!(
|
||||
ui.request_space(vec2(ui.available_finite().width(), height))
|
||||
);
|
||||
let style = ui.style().noninteractive();
|
||||
|
||||
let mut cmds = vec![PaintCmd::Rect {
|
||||
|
|
|
@ -267,7 +267,7 @@ impl ColorTest {
|
|||
|
||||
fn vertex_gradient(ui: &mut Ui, bg_fill: Srgba, gradient: &Gradient) -> Response {
|
||||
use crate::paint::*;
|
||||
let rect = ui.allocate_space(GRADIENT_SIZE);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(GRADIENT_SIZE));
|
||||
if bg_fill != Default::default() {
|
||||
let mut triangles = Triangles::default();
|
||||
triangles.add_colored_rect(rect, bg_fill);
|
||||
|
|
|
@ -93,16 +93,17 @@ impl DemoWindow {
|
|||
.show(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("You can pretty easily paint your own small icons:");
|
||||
let rect = ui.allocate_space(Vec2::splat(16.0));
|
||||
let painter = ui.painter();
|
||||
let c = rect.center();
|
||||
let r = rect.width() / 2.0 - 1.0;
|
||||
let color = Srgba::gray(128);
|
||||
let stroke = Stroke::new(1.0, color);
|
||||
painter.circle_stroke(c, r, stroke);
|
||||
painter.line_segment([c - vec2(0.0, r), c + vec2(0.0, r)], stroke);
|
||||
painter.line_segment([c, c + r * Vec2::angled(TAU * 1.0 / 8.0)], stroke);
|
||||
painter.line_segment([c, c + r * Vec2::angled(TAU * 3.0 / 8.0)], stroke);
|
||||
if let Some(rect) = ui.request_space(Vec2::splat(16.0)) {
|
||||
let painter = ui.painter();
|
||||
let c = rect.center();
|
||||
let r = rect.width() / 2.0 - 1.0;
|
||||
let color = Srgba::gray(128);
|
||||
let stroke = Stroke::new(1.0, color);
|
||||
painter.circle_stroke(c, r, stroke);
|
||||
painter.line_segment([c - vec2(0.0, r), c + vec2(0.0, r)], stroke);
|
||||
painter.line_segment([c, c + r * Vec2::angled(TAU * 1.0 / 8.0)], stroke);
|
||||
painter.line_segment([c, c + r * Vec2::angled(TAU * 3.0 / 8.0)], stroke);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -210,9 +211,9 @@ impl BoxPainting {
|
|||
ui.add(Slider::f32(&mut self.stroke_width, 0.0..=10.0).text("stroke_width"));
|
||||
ui.add(Slider::usize(&mut self.num_boxes, 0..=5).text("num_boxes"));
|
||||
|
||||
let pos = ui
|
||||
.allocate_space(vec2(self.size.x * (self.num_boxes as f32), self.size.y))
|
||||
.min;
|
||||
let rect = ui.request_space(vec2(self.size.x * (self.num_boxes as f32), self.size.y));
|
||||
let rect = unwrap_or_return_default!(rect);
|
||||
let pos = rect.min;
|
||||
|
||||
let mut cmds = vec![];
|
||||
for i in 0..self.num_boxes {
|
||||
|
@ -265,7 +266,7 @@ impl Painting {
|
|||
}
|
||||
|
||||
fn content(&mut self, ui: &mut Ui) {
|
||||
let rect = ui.allocate_space(ui.available_finite().size());
|
||||
let rect = unwrap_or_return_default!(ui.request_space(ui.available_finite().size()));
|
||||
let response = ui.interact(rect, ui.id(), Sense::drag());
|
||||
let rect = response.rect;
|
||||
let clip_rect = ui.clip_rect().intersect(rect); // Make sure we don't paint out of bounds
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::*;
|
|||
pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||
// Widget code can be broken up in four steps:
|
||||
// 1. Decide a size for the widget
|
||||
// 2. Allocate space for it
|
||||
// 2. Request space for it
|
||||
// 3. Handle interactions with the widget (if any)
|
||||
// 4. Paint the widget
|
||||
|
||||
|
@ -22,9 +22,14 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
|||
// but in this example we have a fixed size widget of the default size for a button:
|
||||
let desired_size = ui.style().spacing.interact_size;
|
||||
|
||||
// 2. Allocating space:
|
||||
// 2. Requesting space:
|
||||
// This is where we get a region (`Rect`) of the screen assigned.
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = ui.request_space(desired_size);
|
||||
|
||||
// If we get `None` back from `request_space`, it means this widgets isn't visible.
|
||||
// In this case we shouldn't do anything else and just return early.
|
||||
// Egui has a helper macro for this:
|
||||
let rect = unwrap_or_return_default!(rect);
|
||||
|
||||
// 3. Interact: Time to check for clicks!
|
||||
// To do that we need an `Id` for the button.
|
||||
|
|
|
@ -19,7 +19,7 @@ impl Texture {
|
|||
if size.x > ui.available().width() {
|
||||
size *= ui.available().width() / size.x;
|
||||
}
|
||||
let rect = ui.allocate_space(size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(size));
|
||||
let mut triangles = Triangles::default();
|
||||
triangles.add_rect_with_uv(rect, [pos2(0.0, 0.0), pos2(1.0, 1.0)].into(), WHITE);
|
||||
ui.painter().add(PaintCmd::triangles(triangles));
|
||||
|
@ -34,7 +34,7 @@ impl Texture {
|
|||
.mouse
|
||||
.pos
|
||||
.unwrap_or_else(|| ui.min_rect().left_top());
|
||||
let zoom_rect = ui.allocate_space(vec2(128.0, 128.0));
|
||||
let zoom_rect = unwrap_or_return_default!(ui.request_space(vec2(128.0, 128.0)));
|
||||
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);
|
||||
|
||||
|
|
|
@ -120,3 +120,15 @@ pub fn text_egui_e2e() {
|
|||
assert!(!paint_jobs.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! unwrap_or_return_default {
|
||||
($option:expr) => {
|
||||
match $option {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
return Default::default();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
#![allow(clippy::if_same_then_else)]
|
||||
|
||||
use crate::{
|
||||
color::*,
|
||||
math::*,
|
||||
paint::{Stroke, TextStyle},
|
||||
types::*,
|
||||
};
|
||||
use crate::{color::*, *};
|
||||
|
||||
/// Specifies the look and feel of a `Ui`.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -474,7 +469,8 @@ impl Stroke {
|
|||
ui.label(text);
|
||||
|
||||
// stroke preview:
|
||||
let stroke_rect = ui.allocate_space(ui.style().spacing.interact_size);
|
||||
let stroke_rect =
|
||||
unwrap_or_return_default!(ui.request_space(ui.style().spacing.interact_size));
|
||||
let left = stroke_rect.left_center();
|
||||
let right = stroke_rect.right_center();
|
||||
ui.painter().line_segment([left, right], (*width, *color));
|
||||
|
|
|
@ -56,8 +56,10 @@ impl Default for CursorIcon {
|
|||
#[derive(Clone)]
|
||||
pub struct Response {
|
||||
// CONTEXT:
|
||||
/// Used for optionally showing a tooltip
|
||||
pub ctx: Arc<Context>,
|
||||
/// Used for optionally showing a tooltip.
|
||||
/// If `None`, we likely come from a cull widgets and shouldn't show any
|
||||
/// tooltip.
|
||||
pub ctx: Option<Arc<Context>>,
|
||||
|
||||
// IN:
|
||||
/// The area of the screen we are talking about
|
||||
|
@ -83,17 +85,18 @@ pub struct Response {
|
|||
pub has_kb_focus: bool,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Response {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Response")
|
||||
.field("rect", &self.rect)
|
||||
.field("sense", &self.sense)
|
||||
.field("hovered", &self.hovered)
|
||||
.field("clicked", &self.clicked)
|
||||
.field("double_clicked", &self.double_clicked)
|
||||
.field("active", &self.active)
|
||||
.field("has_kb_focus", &self.has_kb_focus)
|
||||
.finish()
|
||||
impl Default for Response {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ctx: None,
|
||||
rect: Rect::nothing(),
|
||||
sense: Sense::nothing(),
|
||||
hovered: false,
|
||||
clicked: false,
|
||||
double_clicked: false,
|
||||
active: false,
|
||||
has_kb_focus: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +104,11 @@ impl Response {
|
|||
/// Show this UI if the item was hovered (i.e. a tooltip)
|
||||
pub fn on_hover_ui(self, add_contents: impl FnOnce(&mut Ui)) -> Self {
|
||||
if self.hovered {
|
||||
crate::containers::show_tooltip(&self.ctx, add_contents);
|
||||
if let Some(ctx) = &self.ctx {
|
||||
crate::containers::show_tooltip(ctx, add_contents);
|
||||
} else {
|
||||
panic!("We shouldn't be able to hover something without a Context");
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -123,9 +130,12 @@ impl Response {
|
|||
/// A logical "or" operation.
|
||||
/// For instance `a.union(b).hovered` means "was either a or b hovered?".
|
||||
pub fn union(&self, other: Self) -> Self {
|
||||
assert!(Arc::ptr_eq(&self.ctx, &other.ctx));
|
||||
if let (Some(lc), Some(rc)) = (&self.ctx, &other.ctx) {
|
||||
debug_assert!(Arc::ptr_eq(lc, rc));
|
||||
}
|
||||
|
||||
Self {
|
||||
ctx: other.ctx,
|
||||
ctx: other.ctx.or_else(|| self.ctx.clone()),
|
||||
rect: self.rect.union(other.rect),
|
||||
sense: self.sense.union(other.sense),
|
||||
hovered: self.hovered || other.hovered,
|
||||
|
@ -137,6 +147,23 @@ impl Response {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Response {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Response")
|
||||
.field("ctx", &self.ctx.is_some())
|
||||
.field("rect", &self.rect)
|
||||
.field("sense", &self.sense)
|
||||
.field("hovered", &self.hovered)
|
||||
.field("clicked", &self.clicked)
|
||||
.field("double_clicked", &self.double_clicked)
|
||||
.field("active", &self.active)
|
||||
.field("has_kb_focus", &self.has_kb_focus)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// To summarize the response from many widgets you can use this pattern:
|
||||
///
|
||||
/// ```
|
||||
|
|
|
@ -462,6 +462,26 @@ impl Ui {
|
|||
rect
|
||||
}
|
||||
|
||||
/// Potential future of `allocate_space`.
|
||||
/// Returns `None` if the allocated rectangle is outside the clip rect and is thus invisible.
|
||||
/// Works well together with the `unwrap_or_return_default!` macro:
|
||||
/// ```
|
||||
/// # use egui::*;
|
||||
/// # let mut ui = Ui::test();
|
||||
/// let desired_size = vec2(100.0, 200.0);
|
||||
/// let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
/// assert_eq!(rect, Rect::from_min_size(pos2(0.0, 0.0), desired_size));
|
||||
/// ```
|
||||
///
|
||||
pub fn request_space(&mut self, desired_size: Vec2) -> Option<Rect> {
|
||||
let rect = self.allocate_space(desired_size);
|
||||
if self.clip_rect().intersects(rect) {
|
||||
Some(rect)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Reserve this much space and move the cursor.
|
||||
/// Returns where to put the widget.
|
||||
fn reserve_space_impl(&mut self, child_size: Vec2) -> Rect {
|
||||
|
|
|
@ -43,7 +43,7 @@ pub fn show_color(ui: &mut Ui, color: impl Into<Srgba>, desired_size: Vec2) -> R
|
|||
}
|
||||
|
||||
fn show_srgba(ui: &mut Ui, srgba: Srgba, desired_size: Vec2) -> Response {
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
background_checkers(ui.painter(), rect);
|
||||
ui.painter().add(PaintCmd::Rect {
|
||||
rect,
|
||||
|
@ -56,7 +56,7 @@ fn show_srgba(ui: &mut Ui, srgba: Srgba, desired_size: Vec2) -> Response {
|
|||
|
||||
fn color_button(ui: &mut Ui, color: Srgba) -> Response {
|
||||
let desired_size = ui.style().spacing.interact_size;
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
let id = ui.make_position_id();
|
||||
let response = ui.interact(rect, id, Sense::click());
|
||||
let visuals = ui.style().interact(&response);
|
||||
|
@ -77,7 +77,7 @@ fn color_slider_1d(ui: &mut Ui, value: &mut f32, color_at: impl Fn(f32) -> Srgba
|
|||
ui.style().spacing.slider_width,
|
||||
ui.style().spacing.interact_size.y * 2.0,
|
||||
);
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
|
||||
let id = ui.make_position_id();
|
||||
let response = ui.interact(rect, id, Sense::click_and_drag());
|
||||
|
@ -136,7 +136,7 @@ fn color_slider_2d(
|
|||
color_at: impl Fn(f32, f32) -> Srgba,
|
||||
) -> Response {
|
||||
let desired_size = Vec2::splat(ui.style().spacing.slider_width);
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
|
||||
let id = ui.make_position_id();
|
||||
let response = ui.interact(rect, id, Sense::click_and_drag());
|
||||
|
|
|
@ -49,7 +49,7 @@ impl Widget for Image {
|
|||
bg_fill,
|
||||
tint,
|
||||
} = self;
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
if bg_fill != Default::default() {
|
||||
let mut triangles = Triangles::default();
|
||||
triangles.add_colored_rect(rect, bg_fill);
|
||||
|
|
|
@ -135,7 +135,7 @@ macro_rules! label {
|
|||
impl Widget for Label {
|
||||
fn ui(self, ui: &mut Ui) -> Response {
|
||||
let galley = self.layout(ui);
|
||||
let rect = ui.allocate_space(galley.size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(galley.size));
|
||||
self.paint_galley(ui, rect.min, galley);
|
||||
ui.interact_hover(rect)
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ impl Widget for Hyperlink {
|
|||
let text_style = text_style.unwrap_or_else(|| ui.style().body_text_style);
|
||||
let font = &ui.fonts()[text_style];
|
||||
let galley = font.layout_multiline(text, ui.available().width());
|
||||
let rect = ui.allocate_space(galley.size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(galley.size));
|
||||
|
||||
let id = ui.make_position_id();
|
||||
let response = ui.interact(rect, id, Sense::click());
|
||||
|
@ -318,7 +318,7 @@ impl Widget for Button {
|
|||
let galley = font.layout_multiline(text, ui.available().width());
|
||||
let mut desired_size = galley.size + 2.0 * button_padding;
|
||||
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
|
||||
let id = ui.make_position_id();
|
||||
let response = ui.interact(rect, id, sense);
|
||||
|
@ -390,7 +390,7 @@ impl<'a> Widget for Checkbox<'a> {
|
|||
button_padding + vec2(icon_width + icon_spacing, 0.0) + galley.size + button_padding;
|
||||
desired_size = desired_size.at_least(spacing.interact_size);
|
||||
desired_size.y = desired_size.y.max(icon_width);
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
|
||||
let id = ui.make_position_id();
|
||||
let response = ui.interact(rect, id, Sense::click());
|
||||
|
@ -475,7 +475,7 @@ impl Widget for RadioButton {
|
|||
button_padding + vec2(icon_width + icon_spacing, 0.0) + galley.size + button_padding;
|
||||
desired_size = desired_size.at_least(ui.style().spacing.interact_size);
|
||||
desired_size.y = desired_size.y.max(icon_width);
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
|
||||
let id = ui.make_position_id();
|
||||
let response = ui.interact(rect, id, Sense::click());
|
||||
|
@ -544,7 +544,8 @@ impl Widget for Separator {
|
|||
|
||||
let (points, rect) = match ui.layout().dir() {
|
||||
Direction::Horizontal => {
|
||||
let rect = ui.allocate_space(vec2(spacing, available_space.y));
|
||||
let rect =
|
||||
unwrap_or_return_default!(ui.request_space(vec2(spacing, available_space.y)));
|
||||
(
|
||||
[
|
||||
pos2(rect.center().x, rect.top()),
|
||||
|
@ -554,7 +555,8 @@ impl Widget for Separator {
|
|||
)
|
||||
}
|
||||
Direction::Vertical => {
|
||||
let rect = ui.allocate_space(vec2(available_space.x, spacing));
|
||||
let rect =
|
||||
unwrap_or_return_default!(ui.request_space(vec2(available_space.x, spacing)));
|
||||
(
|
||||
[
|
||||
pos2(rect.left(), rect.center().y),
|
||||
|
|
|
@ -122,7 +122,7 @@ impl<'t> Widget for TextEdit<'t> {
|
|||
galley.size.x.max(desired_width.min(available_width)),
|
||||
galley.size.y.max(line_spacing),
|
||||
);
|
||||
let rect = ui.allocate_space(desired_size);
|
||||
let rect = unwrap_or_return_default!(ui.request_space(desired_size));
|
||||
let sense = if enabled {
|
||||
Sense::click_and_drag()
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue