[refactor] introduce NumExt with at_least and at_most

`x.min(maxumim)` can be confusing but `x.at_most(maximum)` is very clear
This commit is contained in:
Emil Ernerfeldt 2020-09-16 21:39:45 +02:00
parent 5856cded95
commit 85a67ab15e
12 changed files with 83 additions and 22 deletions

View file

@ -68,7 +68,7 @@ TODO-list for the Egui project. If you looking for something to do, look here.
* [ ] Thin circles look bad
* [ ] Allow adding multiple tooltips to the same widget, showing them all one after the other.
* Math
* [ ] Change `width.min(max_width)` to `width.at_most(max_width)`
* [x] Change `width.min(max_width)` to `width.at_most(max_width)`
* Id
* struct TempId(u64); struct StateId(u64);
* `TempId` is count-based. Only good for interaction. Can't be used for storing state.

View file

@ -191,7 +191,9 @@ impl CollapsingHeader {
desired_width,
galley.size.y + 2.0 * ui.style().spacing.button_padding.y,
);
desired_size.y = desired_size.y.max(ui.style().spacing.clickable_diameter);
desired_size.y = desired_size
.y
.at_least(ui.style().spacing.clickable_diameter);
let rect = ui.allocate_space(desired_size);
let rect = rect.expand2(ui.style().spacing.button_expand);

View file

@ -140,7 +140,10 @@ impl Resize {
let mut state = ui.memory().resize.get(&id).cloned().unwrap_or_else(|| {
ui.ctx().request_repaint(); // counter frame delay
let default_size = self.default_size.max(self.min_size);
let default_size = self
.default_size
.at_least(self.min_size)
.at_most(self.max_size);
State {
desired_size: default_size,
@ -149,8 +152,10 @@ impl Resize {
}
});
state.desired_size = state.desired_size.max(self.min_size);
state.desired_size = state.desired_size.min(self.max_size);
state.desired_size = state
.desired_size
.at_least(self.min_size)
.at_most(self.max_size);
let position = ui.available().min;
@ -174,8 +179,10 @@ impl Resize {
if let Some(requested_size) = state.requested_size.take() {
state.desired_size = requested_size;
}
state.desired_size = state.desired_size.max(self.min_size);
state.desired_size = state.desired_size.min(self.max_size);
state.desired_size = state
.desired_size
.at_least(self.min_size)
.at_most(self.max_size);
// ------------------------------

View file

@ -94,7 +94,7 @@ impl ScrollArea {
let outer_size = vec2(
ui.available().width(),
ui.available().height().min(max_height),
ui.available().height().at_most(max_height),
);
let inner_size = outer_size - vec2(current_scroll_bar_width, 0.0);

View file

@ -255,7 +255,7 @@ impl<'open> Window<'open> {
&mut collapsing,
collapsible,
);
resize.min_size.x = resize.min_size.x.max(title_bar.rect.width()); // Prevent making window smaller than title bar width
resize.min_size.x = resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width
let content_rect = collapsing
.add_contents(&mut frame.content_ui, collapsing_id, |ui| {

View file

@ -36,8 +36,8 @@ impl Texture {
let v = remap_clamp(pos.y, rect.range_y(), 0.0..=tex_h);
let texel_radius = 32.0;
let u = u.max(texel_radius).min(tex_w - texel_radius);
let v = v.max(texel_radius).min(tex_h - texel_radius);
let u = u.at_least(texel_radius).at_most(tex_w - texel_radius);
let v = v.at_least(texel_radius).at_most(tex_h - texel_radius);
let uv_rect = Rect::from_min_max(
pos2((u - texel_radius) / tex_w, (v - texel_radius) / tex_h),

View file

@ -180,3 +180,49 @@ fn test_remap() {
assert_eq!(remap_clamp(1.0, 1.0..=0.0, 16.0..=0.0), 16.0);
assert_eq!(remap_clamp(0.5, 1.0..=0.0, 16.0..=0.0), 8.0);
}
// ----------------------------------------------------------------------------
pub trait NumExt {
/// More readable version of `self.max(lower_limit)`
fn at_least(self, lower_limit: Self) -> Self;
/// More readable version of `self.min(upper_limit)`
fn at_most(self, upper_limit: Self) -> Self;
}
impl NumExt for f32 {
/// More readable version of `self.max(lower_limit)`
fn at_least(self, lower_limit: Self) -> Self {
self.max(lower_limit)
}
/// More readable version of `self.min(upper_limit)`
fn at_most(self, upper_limit: Self) -> Self {
self.min(upper_limit)
}
}
impl NumExt for Vec2 {
/// More readable version of `self.max(lower_limit)`
fn at_least(self, lower_limit: Self) -> Self {
self.max(lower_limit)
}
/// More readable version of `self.min(upper_limit)`
fn at_most(self, upper_limit: Self) -> Self {
self.min(upper_limit)
}
}
impl NumExt for Pos2 {
/// More readable version of `self.max(lower_limit)`
fn at_least(self, lower_limit: Self) -> Self {
self.max(lower_limit)
}
/// More readable version of `self.min(upper_limit)`
fn at_most(self, upper_limit: Self) -> Self {
self.min(upper_limit)
}
}

View file

@ -710,8 +710,8 @@ fn tessellate_paint_command(
if !rect.is_empty() {
// It is common to (sometimes accidentally) create an infinitely sized rectangle.
// Make sure we can handle that:
rect.min = rect.min.max(pos2(-1e7, -1e7));
rect.max = rect.max.min(pos2(1e7, 1e7));
rect.min = rect.min.at_least(pos2(-1e7, -1e7));
rect.max = rect.max.at_most(pos2(1e7, 1e7));
path::rounded_rectangle(scratchpad_points, rect, corner_radius);
path.add_line_loop(scratchpad_points);

View file

@ -197,7 +197,7 @@ impl Ui {
/// You won't be able to shrink it beyond its current child bounds.
pub fn set_desired_width(&mut self, width: f32) {
let min_width = self.child_bounds.max.x - self.top_left().x;
let width = width.max(min_width);
let width = width.at_least(min_width);
self.desired_rect.max.x = self.top_left().x + width;
}
@ -205,7 +205,7 @@ impl Ui {
/// You won't be able to shrink it beyond its current child bounds.
pub fn set_desired_height(&mut self, height: f32) {
let min_height = self.child_bounds.max.y - self.top_left().y;
let height = height.max(min_height);
let height = height.at_least(min_height);
self.desired_rect.max.y = self.top_left().y + height;
}
@ -584,7 +584,7 @@ impl Ui {
/// After `add_contents` is called the contents of `bounding_size`
/// will decide how much space will be used in the parent ui.
pub fn add_custom_contents(&mut self, size: Vec2, add_contents: impl FnOnce(&mut Ui)) -> Rect {
let size = size.min(self.available().size());
let size = size.at_most(self.available().size());
let child_rect = Rect::from_min_size(self.cursor, size);
let mut child_ui = self.child_ui(child_rect);
add_contents(&mut child_ui);

View file

@ -64,7 +64,7 @@ fn color_button(ui: &mut Ui, color: Srgba) -> Response {
background_checkers(ui.painter(), rect);
ui.painter().add(PaintCmd::Rect {
rect,
corner_radius: visuals.corner_radius.min(2.0),
corner_radius: visuals.corner_radius.at_most(2.0),
fill: color,
stroke: visuals.fg_stroke,
});

View file

@ -292,7 +292,9 @@ impl Widget for Button {
let font = &ui.fonts()[text_style];
let galley = font.layout_multiline(text, ui.available().width());
let mut desired_size = galley.size + 2.0 * ui.style().spacing.button_padding;
desired_size.y = desired_size.y.max(ui.style().spacing.clickable_diameter);
desired_size.y = desired_size
.y
.at_least(ui.style().spacing.clickable_diameter);
let rect = ui.allocate_space(desired_size);
let rect = rect.expand2(ui.style().spacing.button_expand);
@ -355,7 +357,9 @@ impl<'a> Widget for Checkbox<'a> {
let button_padding = ui.style().spacing.button_padding;
let mut desired_size =
button_padding + vec2(icon_width, 0.0) + galley.size + button_padding;
desired_size.y = desired_size.y.max(ui.style().spacing.clickable_diameter);
desired_size.y = desired_size
.y
.at_least(ui.style().spacing.clickable_diameter);
let rect = ui.allocate_space(desired_size);
let response = ui.interact(rect, id, Sense::click());
@ -437,7 +441,9 @@ impl Widget for RadioButton {
let button_padding = ui.style().spacing.button_padding;
let mut desired_size =
button_padding + vec2(icon_width, 0.0) + galley.size + button_padding;
desired_size.y = desired_size.y.max(ui.style().spacing.clickable_diameter);
desired_size.y = desired_size
.y
.at_least(ui.style().spacing.clickable_diameter);
let rect = ui.allocate_space(desired_size);
let response = ui.interact(rect, id, Sense::click());
@ -633,7 +639,7 @@ impl<'a> Widget for DragValue<'a> {
} = self;
let value = get(&mut value_function);
let aim_rad = ui.input().physical_pixel_size(); // ui.input().aim_radius(); // TODO
let precision = (aim_rad / speed.abs()).log10().ceil().max(0.0) as usize;
let precision = (aim_rad / speed.abs()).log10().ceil().at_least(0.0) as usize;
let value_text = format_with_minimum_precision(value as f32, precision); // TODO: full precision
let kb_edit_id = ui.make_position_id().with("edit");

View file

@ -272,7 +272,7 @@ impl<'a> Widget for Slider<'a> {
let font = &ui.fonts()[text_style];
let height = font
.line_spacing()
.max(ui.style().spacing.clickable_diameter);
.at_least(ui.style().spacing.clickable_diameter);
if let Some(text) = &self.text {
self.id = self.id.or_else(|| Some(ui.make_unique_child_id(text)));