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

Replace uses of RangeInclusive<f32> with emath::Rangef (#3221)

* Replace uses of `RangeInclusive<f32>` with `emath::Rangef`

* Fix doc-test
This commit is contained in:
Emil Ernerfeldt
2023-08-10 13:07:00 +02:00
committed by GitHub
parent 4c3b380889
commit 8cdffc4e2d
14 changed files with 213 additions and 161 deletions

View File

@@ -15,8 +15,6 @@
//!
//! Add your [`Window`]:s after any top-level panels.
use std::ops::RangeInclusive;
use crate::*;
/// State regarding panels.
@@ -99,7 +97,7 @@ pub struct SidePanel {
resizable: bool,
show_separator_line: bool,
default_width: f32,
width_range: RangeInclusive<f32>,
width_range: Rangef,
}
impl SidePanel {
@@ -122,7 +120,7 @@ impl SidePanel {
resizable: true,
show_separator_line: true,
default_width: 200.0,
width_range: 96.0..=f32::INFINITY,
width_range: Rangef::new(96.0, f32::INFINITY),
}
}
@@ -153,26 +151,29 @@ impl SidePanel {
/// The initial wrapping width of the [`SidePanel`].
pub fn default_width(mut self, default_width: f32) -> Self {
self.default_width = default_width;
self.width_range = self.width_range.start().at_most(default_width)
..=self.width_range.end().at_least(default_width);
self.width_range = Rangef::new(
self.width_range.min.at_most(default_width),
self.width_range.max.at_least(default_width),
);
self
}
/// Minimum width of the panel.
pub fn min_width(mut self, min_width: f32) -> Self {
self.width_range = min_width..=self.width_range.end().at_least(min_width);
self.width_range = Rangef::new(min_width, self.width_range.max.at_least(min_width));
self
}
/// Maximum width of the panel.
pub fn max_width(mut self, max_width: f32) -> Self {
self.width_range = self.width_range.start().at_most(max_width)..=max_width;
self.width_range = Rangef::new(self.width_range.min.at_most(max_width), max_width);
self
}
/// The allowable width range for the panel.
pub fn width_range(mut self, width_range: RangeInclusive<f32>) -> Self {
self.default_width = clamp_to_range(self.default_width, width_range.clone());
pub fn width_range(mut self, width_range: impl Into<Rangef>) -> Self {
let width_range = width_range.into();
self.default_width = clamp_to_range(self.default_width, width_range);
self.width_range = width_range;
self
}
@@ -180,7 +181,7 @@ impl SidePanel {
/// Enforce this exact width.
pub fn exact_width(mut self, width: f32) -> Self {
self.default_width = width;
self.width_range = width..=width;
self.width_range = Rangef::point(width);
self
}
@@ -224,7 +225,7 @@ impl SidePanel {
if let Some(state) = PanelState::load(ui.ctx(), id) {
width = state.rect.width();
}
width = clamp_to_range(width, width_range.clone()).at_most(available_rect.width());
width = clamp_to_range(width, width_range).at_most(available_rect.width());
side.set_rect_width(&mut panel_rect, width);
ui.ctx().check_for_id_clash(id, panel_rect, "SidePanel");
}
@@ -241,7 +242,7 @@ impl SidePanel {
let resize_x = side.opposite().side_x(panel_rect);
let mouse_over_resize_line = we_are_on_top
&& panel_rect.y_range().contains(&pointer.y)
&& panel_rect.y_range().contains(pointer.y)
&& (resize_x - pointer.x).abs()
<= ui.style().interaction.resize_grab_radius_side;
@@ -253,8 +254,7 @@ impl SidePanel {
is_resizing = ui.memory(|mem| mem.is_being_dragged(resize_id));
if is_resizing {
let width = (pointer.x - side.side_x(panel_rect)).abs();
let width =
clamp_to_range(width, width_range.clone()).at_most(available_rect.width());
let width = clamp_to_range(width, width_range).at_most(available_rect.width());
side.set_rect_width(&mut panel_rect, width);
}
@@ -273,7 +273,7 @@ impl SidePanel {
let frame = frame.unwrap_or_else(|| Frame::side_top_panel(ui.style()));
let inner_response = frame.show(&mut panel_ui, |ui| {
ui.set_min_height(ui.max_rect().height()); // Make sure the frame fills the full height
ui.set_min_width(*width_range.start());
ui.set_min_width(width_range.min);
add_contents(ui)
});
@@ -544,7 +544,7 @@ pub struct TopBottomPanel {
resizable: bool,
show_separator_line: bool,
default_height: Option<f32>,
height_range: RangeInclusive<f32>,
height_range: Rangef,
}
impl TopBottomPanel {
@@ -567,7 +567,7 @@ impl TopBottomPanel {
resizable: false,
show_separator_line: true,
default_height: None,
height_range: 20.0..=f32::INFINITY,
height_range: Rangef::new(20.0, f32::INFINITY),
}
}
@@ -599,28 +599,31 @@ impl TopBottomPanel {
/// Defaults to [`style::Spacing::interact_size`].y.
pub fn default_height(mut self, default_height: f32) -> Self {
self.default_height = Some(default_height);
self.height_range = self.height_range.start().at_most(default_height)
..=self.height_range.end().at_least(default_height);
self.height_range = Rangef::new(
self.height_range.min.at_most(default_height),
self.height_range.max.at_least(default_height),
);
self
}
/// Minimum height of the panel.
pub fn min_height(mut self, min_height: f32) -> Self {
self.height_range = min_height..=self.height_range.end().at_least(min_height);
self.height_range = Rangef::new(min_height, self.height_range.max.at_least(min_height));
self
}
/// Maximum height of the panel.
pub fn max_height(mut self, max_height: f32) -> Self {
self.height_range = self.height_range.start().at_most(max_height)..=max_height;
self.height_range = Rangef::new(self.height_range.min.at_most(max_height), max_height);
self
}
/// The allowable height range for the panel.
pub fn height_range(mut self, height_range: RangeInclusive<f32>) -> Self {
pub fn height_range(mut self, height_range: impl Into<Rangef>) -> Self {
let height_range = height_range.into();
self.default_height = self
.default_height
.map(|default_height| clamp_to_range(default_height, height_range.clone()));
.map(|default_height| clamp_to_range(default_height, height_range));
self.height_range = height_range;
self
}
@@ -628,7 +631,7 @@ impl TopBottomPanel {
/// Enforce this exact height.
pub fn exact_height(mut self, height: f32) -> Self {
self.default_height = Some(height);
self.height_range = height..=height;
self.height_range = Rangef::point(height);
self
}
@@ -673,7 +676,7 @@ impl TopBottomPanel {
} else {
default_height.unwrap_or_else(|| ui.style().spacing.interact_size.y)
};
height = clamp_to_range(height, height_range.clone()).at_most(available_rect.height());
height = clamp_to_range(height, height_range).at_most(available_rect.height());
side.set_rect_height(&mut panel_rect, height);
ui.ctx()
.check_for_id_clash(id, panel_rect, "TopBottomPanel");
@@ -692,7 +695,7 @@ impl TopBottomPanel {
let resize_y = side.opposite().side_y(panel_rect);
let mouse_over_resize_line = we_are_on_top
&& panel_rect.x_range().contains(&pointer.x)
&& panel_rect.x_range().contains(pointer.x)
&& (resize_y - pointer.y).abs()
<= ui.style().interaction.resize_grab_radius_side;
@@ -704,8 +707,8 @@ impl TopBottomPanel {
is_resizing = ui.memory(|mem| mem.interaction.drag_id == Some(resize_id));
if is_resizing {
let height = (pointer.y - side.side_y(panel_rect)).abs();
let height = clamp_to_range(height, height_range.clone())
.at_most(available_rect.height());
let height =
clamp_to_range(height, height_range).at_most(available_rect.height());
side.set_rect_height(&mut panel_rect, height);
}
@@ -724,7 +727,7 @@ impl TopBottomPanel {
let frame = frame.unwrap_or_else(|| Frame::side_top_panel(ui.style()));
let inner_response = frame.show(&mut panel_ui, |ui| {
ui.set_min_width(ui.max_rect().width()); // Make the frame fill full width
ui.set_min_height(*height_range.start());
ui.set_min_height(height_range.min);
add_contents(ui)
});
@@ -1056,9 +1059,7 @@ impl CentralPanel {
}
}
fn clamp_to_range(x: f32, range: RangeInclusive<f32>) -> f32 {
x.clamp(
range.start().min(*range.end()),
range.start().max(*range.end()),
)
fn clamp_to_range(x: f32, range: Rangef) -> f32 {
let range = range.as_positive();
x.clamp(range.min, range.max)
}

View File

@@ -640,8 +640,7 @@ impl Prepared {
let min = content_ui.min_rect().min[d];
let clip_rect = content_ui.clip_rect();
let visible_range = min..=min + clip_rect.size()[d];
let start = *scroll.start();
let end = *scroll.end();
let (start, end) = (scroll.min, scroll.max);
let clip_start = clip_rect.min[d];
let clip_end = clip_rect.max[d];
let mut spacing = ui.spacing().item_spacing[d];

View File

@@ -1,5 +1,3 @@
use std::ops::RangeInclusive;
use crate::{id::IdSet, *};
#[derive(Clone, Copy, Debug)]
@@ -46,7 +44,7 @@ pub(crate) struct FrameState {
pub(crate) scroll_delta: Vec2, // TODO(emilk): move to `InputState` ?
/// horizontal, vertical
pub(crate) scroll_target: [Option<(RangeInclusive<f32>, Option<Align>)>; 2],
pub(crate) scroll_target: [Option<(Rangef, Option<Align>)>; 2],
#[cfg(feature = "accesskit")]
pub(crate) accesskit_state: Option<AccessKitFrameState>,

View File

@@ -335,7 +335,9 @@ pub use epaint::emath;
#[cfg(feature = "color-hex")]
pub use ecolor::hex_color;
pub use ecolor::{Color32, Rgba};
pub use emath::{lerp, pos2, remap, remap_clamp, vec2, Align, Align2, NumExt, Pos2, Rect, Vec2};
pub use emath::{
lerp, pos2, remap, remap_clamp, vec2, Align, Align2, NumExt, Pos2, Rangef, Rect, Vec2,
};
pub use epaint::{
mutex,
text::{FontData, FontDefinitions, FontFamily, FontId, FontTweak},

View File

@@ -1,8 +1,7 @@
use std::ops::RangeInclusive;
use std::sync::Arc;
use crate::{
emath::{Align2, Pos2, Rect, Vec2},
emath::{Align2, Pos2, Rangef, Rect, Vec2},
layers::{LayerId, PaintList, ShapeIdx},
Color32, Context, FontId,
};
@@ -263,12 +262,12 @@ impl Painter {
}
/// Paints a horizontal line.
pub fn hline(&self, x: RangeInclusive<f32>, y: f32, stroke: impl Into<Stroke>) {
pub fn hline(&self, x: impl Into<Rangef>, y: f32, stroke: impl Into<Stroke>) {
self.add(Shape::hline(x, y, stroke));
}
/// Paints a vertical line.
pub fn vline(&self, x: f32, y: RangeInclusive<f32>, stroke: impl Into<Stroke>) {
pub fn vline(&self, x: f32, y: impl Into<Rangef>, stroke: impl Into<Stroke>) {
self.add(Shape::vline(x, y, stroke));
}

View File

@@ -517,15 +517,17 @@ impl Ui {
}
/// `ui.set_width_range(min..=max);` is equivalent to `ui.set_min_width(min); ui.set_max_width(max);`.
pub fn set_width_range(&mut self, width: std::ops::RangeInclusive<f32>) {
self.set_min_width(*width.start());
self.set_max_width(*width.end());
pub fn set_width_range(&mut self, width: impl Into<Rangef>) {
let width = width.into();
self.set_min_width(width.min);
self.set_max_width(width.max);
}
/// `ui.set_height_range(min..=max);` is equivalent to `ui.set_min_height(min); ui.set_max_height(max);`.
pub fn set_height_range(&mut self, height: std::ops::RangeInclusive<f32>) {
self.set_min_height(*height.start());
self.set_max_height(*height.end());
pub fn set_height_range(&mut self, height: impl Into<Rangef>) {
let height = height.into();
self.set_min_height(height.min);
self.set_max_height(height.max);
}
/// Set both the minimum and maximum width.
@@ -978,7 +980,7 @@ impl Ui {
/// ```
pub fn scroll_to_rect(&self, rect: Rect, align: Option<Align>) {
for d in 0..2 {
let range = rect.min[d]..=rect.max[d];
let range = Rangef::new(rect.min[d], rect.max[d]);
self.ctx()
.frame_state_mut(|state| state.scroll_target[d] = Some((range, align)));
}
@@ -1008,9 +1010,9 @@ impl Ui {
pub fn scroll_to_cursor(&self, align: Option<Align>) {
let target = self.next_widget_position();
for d in 0..2 {
let target = target[d];
let target = Rangef::point(target[d]);
self.ctx()
.frame_state_mut(|state| state.scroll_target[d] = Some((target..=target, align)));
.frame_state_mut(|state| state.scroll_target[d] = Some((target, align)));
}
}

View File

@@ -524,12 +524,12 @@ impl<'a> Slider<'a> {
}
/// For instance, `position` is the mouse position and `position_range` is the physical location of the slider on the screen.
fn value_from_position(&self, position: f32, position_range: RangeInclusive<f32>) -> f64 {
fn value_from_position(&self, position: f32, position_range: Rangef) -> f64 {
let normalized = remap_clamp(position, position_range, 0.0..=1.0) as f64;
value_from_normalized(normalized, self.range(), &self.spec)
}
fn position_from_value(&self, value: f64, position_range: RangeInclusive<f32>) -> f32 {
fn position_from_value(&self, value: f64, position_range: Rangef) -> f32 {
let normalized = normalized_from_value(value, self.range(), &self.spec);
lerp(position_range, normalized as f32)
}
@@ -555,11 +555,11 @@ impl<'a> Slider<'a> {
let new_value = if self.smart_aim {
let aim_radius = ui.input(|i| i.aim_radius());
emath::smart_aim::best_in_range_f64(
self.value_from_position(position - aim_radius, position_range.clone()),
self.value_from_position(position + aim_radius, position_range.clone()),
self.value_from_position(position - aim_radius, position_range),
self.value_from_position(position + aim_radius, position_range),
)
} else {
self.value_from_position(position, position_range.clone())
self.value_from_position(position, position_range)
};
self.set_value(new_value);
}
@@ -594,18 +594,18 @@ impl<'a> Slider<'a> {
if kb_step != 0.0 {
let prev_value = self.get_value();
let prev_position = self.position_from_value(prev_value, position_range.clone());
let prev_position = self.position_from_value(prev_value, position_range);
let new_position = prev_position + kb_step;
let new_value = match self.step {
Some(step) => prev_value + (kb_step as f64 * step),
None if self.smart_aim => {
let aim_radius = ui.input(|i| i.aim_radius());
emath::smart_aim::best_in_range_f64(
self.value_from_position(new_position - aim_radius, position_range.clone()),
self.value_from_position(new_position + aim_radius, position_range.clone()),
self.value_from_position(new_position - aim_radius, position_range),
self.value_from_position(new_position + aim_radius, position_range),
)
}
_ => self.value_from_position(new_position, position_range.clone()),
_ => self.value_from_position(new_position, position_range),
};
self.set_value(new_value);
}
@@ -686,15 +686,11 @@ impl<'a> Slider<'a> {
}
}
fn position_range(&self, rect: &Rect) -> RangeInclusive<f32> {
fn position_range(&self, rect: &Rect) -> Rangef {
let handle_radius = self.handle_radius(rect);
match self.orientation {
SliderOrientation::Horizontal => {
(rect.left() + handle_radius)..=(rect.right() - handle_radius)
}
SliderOrientation::Vertical => {
(rect.bottom() - handle_radius)..=(rect.top() + handle_radius)
}
SliderOrientation::Horizontal => rect.x_range().shrink(handle_radius),
SliderOrientation::Vertical => rect.y_range().shrink(handle_radius),
}
}
@@ -726,7 +722,7 @@ impl<'a> Slider<'a> {
}
}
fn value_ui(&mut self, ui: &mut Ui, position_range: RangeInclusive<f32>) -> Response {
fn value_ui(&mut self, ui: &mut Ui, position_range: Rangef) -> Response {
// If [`DragValue`] is controlled from the keyboard and `step` is defined, set speed to `step`
let change = ui.input(|input| {
input.num_presses(Key::ArrowUp) as i32 + input.num_presses(Key::ArrowRight) as i32
@@ -740,7 +736,7 @@ impl<'a> Slider<'a> {
step
} else {
self.drag_value_speed
.unwrap_or_else(|| self.current_gradient(&position_range))
.unwrap_or_else(|| self.current_gradient(position_range))
};
let mut value = self.get_value();
@@ -767,12 +763,11 @@ impl<'a> Slider<'a> {
}
/// delta(value) / delta(points)
fn current_gradient(&mut self, position_range: &RangeInclusive<f32>) -> f64 {
fn current_gradient(&mut self, position_range: Rangef) -> f64 {
// TODO(emilk): handle clamping
let value = self.get_value();
let value_from_pos =
|position: f32| self.value_from_position(position, position_range.clone());
let pos_from_value = |value: f64| self.position_from_value(value, position_range.clone());
let value_from_pos = |position: f32| self.value_from_position(position, position_range);
let pos_from_value = |value: f64| self.position_from_value(value, position_range);
let left_value = value_from_pos(pos_from_value(value) - 0.5);
let right_value = value_from_pos(pos_from_value(value) + 0.5);
right_value - left_value