[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 * [ ] Thin circles look bad
* [ ] Allow adding multiple tooltips to the same widget, showing them all one after the other. * [ ] Allow adding multiple tooltips to the same widget, showing them all one after the other.
* Math * 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 * Id
* struct TempId(u64); struct StateId(u64); * struct TempId(u64); struct StateId(u64);
* `TempId` is count-based. Only good for interaction. Can't be used for storing state. * `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, desired_width,
galley.size.y + 2.0 * ui.style().spacing.button_padding.y, 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 = ui.allocate_space(desired_size);
let rect = rect.expand2(ui.style().spacing.button_expand); 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(|| { let mut state = ui.memory().resize.get(&id).cloned().unwrap_or_else(|| {
ui.ctx().request_repaint(); // counter frame delay 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 { State {
desired_size: default_size, desired_size: default_size,
@ -149,8 +152,10 @@ impl Resize {
} }
}); });
state.desired_size = state.desired_size.max(self.min_size); state.desired_size = state
state.desired_size = state.desired_size.min(self.max_size); .desired_size
.at_least(self.min_size)
.at_most(self.max_size);
let position = ui.available().min; let position = ui.available().min;
@ -174,8 +179,10 @@ impl Resize {
if let Some(requested_size) = state.requested_size.take() { if let Some(requested_size) = state.requested_size.take() {
state.desired_size = requested_size; state.desired_size = requested_size;
} }
state.desired_size = state.desired_size.max(self.min_size); state.desired_size = state
state.desired_size = state.desired_size.min(self.max_size); .desired_size
.at_least(self.min_size)
.at_most(self.max_size);
// ------------------------------ // ------------------------------

View file

@ -94,7 +94,7 @@ impl ScrollArea {
let outer_size = vec2( let outer_size = vec2(
ui.available().width(), 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); let inner_size = outer_size - vec2(current_scroll_bar_width, 0.0);

View file

@ -255,7 +255,7 @@ impl<'open> Window<'open> {
&mut collapsing, &mut collapsing,
collapsible, 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 let content_rect = collapsing
.add_contents(&mut frame.content_ui, collapsing_id, |ui| { .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 v = remap_clamp(pos.y, rect.range_y(), 0.0..=tex_h);
let texel_radius = 32.0; let texel_radius = 32.0;
let u = u.max(texel_radius).min(tex_w - texel_radius); let u = u.at_least(texel_radius).at_most(tex_w - texel_radius);
let v = v.max(texel_radius).min(tex_h - texel_radius); let v = v.at_least(texel_radius).at_most(tex_h - texel_radius);
let uv_rect = Rect::from_min_max( let uv_rect = Rect::from_min_max(
pos2((u - texel_radius) / tex_w, (v - texel_radius) / tex_h), 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(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); 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() { if !rect.is_empty() {
// It is common to (sometimes accidentally) create an infinitely sized rectangle. // It is common to (sometimes accidentally) create an infinitely sized rectangle.
// Make sure we can handle that: // Make sure we can handle that:
rect.min = rect.min.max(pos2(-1e7, -1e7)); rect.min = rect.min.at_least(pos2(-1e7, -1e7));
rect.max = rect.max.min(pos2(1e7, 1e7)); rect.max = rect.max.at_most(pos2(1e7, 1e7));
path::rounded_rectangle(scratchpad_points, rect, corner_radius); path::rounded_rectangle(scratchpad_points, rect, corner_radius);
path.add_line_loop(scratchpad_points); 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. /// You won't be able to shrink it beyond its current child bounds.
pub fn set_desired_width(&mut self, width: f32) { pub fn set_desired_width(&mut self, width: f32) {
let min_width = self.child_bounds.max.x - self.top_left().x; 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; 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. /// You won't be able to shrink it beyond its current child bounds.
pub fn set_desired_height(&mut self, height: f32) { pub fn set_desired_height(&mut self, height: f32) {
let min_height = self.child_bounds.max.y - self.top_left().y; 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; 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` /// After `add_contents` is called the contents of `bounding_size`
/// will decide how much space will be used in the parent ui. /// 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 { 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 child_rect = Rect::from_min_size(self.cursor, size);
let mut child_ui = self.child_ui(child_rect); let mut child_ui = self.child_ui(child_rect);
add_contents(&mut child_ui); 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); background_checkers(ui.painter(), rect);
ui.painter().add(PaintCmd::Rect { ui.painter().add(PaintCmd::Rect {
rect, rect,
corner_radius: visuals.corner_radius.min(2.0), corner_radius: visuals.corner_radius.at_most(2.0),
fill: color, fill: color,
stroke: visuals.fg_stroke, stroke: visuals.fg_stroke,
}); });

View file

@ -292,7 +292,9 @@ impl Widget for Button {
let font = &ui.fonts()[text_style]; let font = &ui.fonts()[text_style];
let galley = font.layout_multiline(text, ui.available().width()); let galley = font.layout_multiline(text, ui.available().width());
let mut desired_size = galley.size + 2.0 * ui.style().spacing.button_padding; 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 = ui.allocate_space(desired_size);
let rect = rect.expand2(ui.style().spacing.button_expand); 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 button_padding = ui.style().spacing.button_padding;
let mut desired_size = let mut desired_size =
button_padding + vec2(icon_width, 0.0) + galley.size + button_padding; 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 rect = ui.allocate_space(desired_size);
let response = ui.interact(rect, id, Sense::click()); 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 button_padding = ui.style().spacing.button_padding;
let mut desired_size = let mut desired_size =
button_padding + vec2(icon_width, 0.0) + galley.size + button_padding; 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 rect = ui.allocate_space(desired_size);
let response = ui.interact(rect, id, Sense::click()); let response = ui.interact(rect, id, Sense::click());
@ -633,7 +639,7 @@ impl<'a> Widget for DragValue<'a> {
} = self; } = self;
let value = get(&mut value_function); let value = get(&mut value_function);
let aim_rad = ui.input().physical_pixel_size(); // ui.input().aim_radius(); // TODO 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 value_text = format_with_minimum_precision(value as f32, precision); // TODO: full precision
let kb_edit_id = ui.make_position_id().with("edit"); 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 font = &ui.fonts()[text_style];
let height = font let height = font
.line_spacing() .line_spacing()
.max(ui.style().spacing.clickable_diameter); .at_least(ui.style().spacing.clickable_diameter);
if let Some(text) = &self.text { if let Some(text) = &self.text {
self.id = self.id.or_else(|| Some(ui.make_unique_child_id(text))); self.id = self.id.or_else(|| Some(ui.make_unique_child_id(text)));