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:
parent
4c3b380889
commit
8cdffc4e2d
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
use egui::Rangef;
|
||||
|
||||
/// Size hint for table column/strip cell.
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
pub enum Size {
|
||||
/// Absolute size in points, with a given range of allowed sizes to resize within.
|
||||
Absolute { initial: f32, range: (f32, f32) },
|
||||
Absolute { initial: f32, range: Rangef },
|
||||
|
||||
/// Relative size relative to all available space.
|
||||
Relative { fraction: f32, range: (f32, f32) },
|
||||
Relative { fraction: f32, range: Rangef },
|
||||
|
||||
/// Multiple remainders each get the same space.
|
||||
Remainder { range: (f32, f32) },
|
||||
Remainder { range: Rangef },
|
||||
}
|
||||
|
||||
impl Size {
|
||||
|
|
@ -16,7 +18,7 @@ impl Size {
|
|||
pub fn exact(points: f32) -> Self {
|
||||
Self::Absolute {
|
||||
initial: points,
|
||||
range: (points, points),
|
||||
range: Rangef::new(points, points),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +26,7 @@ impl Size {
|
|||
pub fn initial(points: f32) -> Self {
|
||||
Self::Absolute {
|
||||
initial: points,
|
||||
range: (0.0, f32::INFINITY),
|
||||
range: Rangef::new(0.0, f32::INFINITY),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,14 +35,14 @@ impl Size {
|
|||
egui::egui_assert!(0.0 <= fraction && fraction <= 1.0);
|
||||
Self::Relative {
|
||||
fraction,
|
||||
range: (0.0, f32::INFINITY),
|
||||
range: Rangef::new(0.0, f32::INFINITY),
|
||||
}
|
||||
}
|
||||
|
||||
/// Multiple remainders each get the same space.
|
||||
pub fn remainder() -> Self {
|
||||
Self::Remainder {
|
||||
range: (0.0, f32::INFINITY),
|
||||
range: Rangef::new(0.0, f32::INFINITY),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +52,7 @@ impl Size {
|
|||
Self::Absolute { range, .. }
|
||||
| Self::Relative { range, .. }
|
||||
| Self::Remainder { range, .. } => {
|
||||
range.0 = minimum;
|
||||
range.min = minimum;
|
||||
}
|
||||
}
|
||||
self
|
||||
|
|
@ -62,14 +64,14 @@ impl Size {
|
|||
Self::Absolute { range, .. }
|
||||
| Self::Relative { range, .. }
|
||||
| Self::Remainder { range, .. } => {
|
||||
range.1 = maximum;
|
||||
range.max = maximum;
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Allowed range of movement (in points), if in a resizable [`Table`](crate::table::Table).
|
||||
pub fn range(self) -> (f32, f32) {
|
||||
pub fn range(self) -> Rangef {
|
||||
match self {
|
||||
Self::Absolute { range, .. }
|
||||
| Self::Relative { range, .. }
|
||||
|
|
@ -99,12 +101,9 @@ impl Sizing {
|
|||
.iter()
|
||||
.map(|&size| match size {
|
||||
Size::Absolute { initial, .. } => initial,
|
||||
Size::Relative {
|
||||
fraction,
|
||||
range: (min, max),
|
||||
} => {
|
||||
Size::Relative { fraction, range } => {
|
||||
assert!(0.0 <= fraction && fraction <= 1.0);
|
||||
(length * fraction).clamp(min, max)
|
||||
range.clamp(length * fraction)
|
||||
}
|
||||
Size::Remainder { .. } => {
|
||||
remainders += 1;
|
||||
|
|
@ -120,9 +119,9 @@ impl Sizing {
|
|||
let mut remainder_length = length - sum_non_remainder;
|
||||
let avg_remainder_length = 0.0f32.max(remainder_length / remainders as f32).floor();
|
||||
self.sizes.iter().for_each(|&size| {
|
||||
if let Size::Remainder { range: (min, _max) } = size {
|
||||
if avg_remainder_length < min {
|
||||
remainder_length -= min;
|
||||
if let Size::Remainder { range } = size {
|
||||
if avg_remainder_length < range.min {
|
||||
remainder_length -= range.min;
|
||||
remainders -= 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -138,11 +137,8 @@ impl Sizing {
|
|||
.iter()
|
||||
.map(|&size| match size {
|
||||
Size::Absolute { initial, .. } => initial,
|
||||
Size::Relative {
|
||||
fraction,
|
||||
range: (min, max),
|
||||
} => (length * fraction).clamp(min, max),
|
||||
Size::Remainder { range: (min, max) } => avg_remainder_length.clamp(min, max),
|
||||
Size::Relative { fraction, range } => range.clamp(length * fraction),
|
||||
Size::Remainder { range } => range.clamp(avg_remainder_length),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
//! | fixed size | all available space/minimum | 30% of available width | fixed size |
|
||||
//! Takes all available height, so if you want something below the table, put it in a strip.
|
||||
|
||||
use egui::{Align, NumExt as _, Rect, Response, ScrollArea, Ui, Vec2};
|
||||
use egui::{Align, NumExt as _, Rangef, Rect, Response, ScrollArea, Ui, Vec2};
|
||||
|
||||
use crate::{
|
||||
layout::{CellDirection, CellSize},
|
||||
|
|
@ -28,7 +28,7 @@ enum InitialColumnSize {
|
|||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Column {
|
||||
initial_width: InitialColumnSize,
|
||||
width_range: (f32, f32),
|
||||
width_range: Rangef,
|
||||
/// Clip contents if too narrow?
|
||||
clip: bool,
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ impl Column {
|
|||
fn new(initial_width: InitialColumnSize) -> Self {
|
||||
Self {
|
||||
initial_width,
|
||||
width_range: (0.0, f32::INFINITY),
|
||||
width_range: Rangef::new(0.0, f32::INFINITY),
|
||||
resizable: None,
|
||||
clip: false,
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ impl Column {
|
|||
///
|
||||
/// Default: 0.0
|
||||
pub fn at_least(mut self, minimum: f32) -> Self {
|
||||
self.width_range.0 = minimum;
|
||||
self.width_range.min = minimum;
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -118,13 +118,13 @@ impl Column {
|
|||
///
|
||||
/// Default: [`f32::INFINITY`]
|
||||
pub fn at_most(mut self, maximum: f32) -> Self {
|
||||
self.width_range.1 = maximum;
|
||||
self.width_range.max = maximum;
|
||||
self
|
||||
}
|
||||
|
||||
/// Allowed range of movement (in points), if in a resizable [`Table`](crate::table::Table).
|
||||
pub fn range(mut self, range: std::ops::RangeInclusive<f32>) -> Self {
|
||||
self.width_range = (*range.start(), *range.end());
|
||||
pub fn range(mut self, range: impl Into<Rangef>) -> Self {
|
||||
self.width_range = range.into();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -146,8 +146,8 @@ fn to_sizing(columns: &[Column]) -> crate::sizing::Sizing {
|
|||
InitialColumnSize::Automatic(suggested_width) => Size::initial(suggested_width),
|
||||
InitialColumnSize::Remainder => Size::remainder(),
|
||||
}
|
||||
.at_least(column.width_range.0)
|
||||
.at_most(column.width_range.1);
|
||||
.at_least(column.width_range.min)
|
||||
.at_most(column.width_range.max);
|
||||
sizing.add(size);
|
||||
}
|
||||
sizing
|
||||
|
|
@ -598,13 +598,13 @@ impl<'a> Table<'a> {
|
|||
|
||||
if scroll_to_row.is_some() && scroll_to_y_range.is_none() {
|
||||
// TableBody::row didn't find the right row, so scroll to the bottom:
|
||||
scroll_to_y_range = Some((f32::INFINITY, f32::INFINITY));
|
||||
scroll_to_y_range = Some(Rangef::new(f32::INFINITY, f32::INFINITY));
|
||||
}
|
||||
});
|
||||
|
||||
if let Some((min_y, max_y)) = scroll_to_y_range {
|
||||
if let Some(y_range) = scroll_to_y_range {
|
||||
let x = 0.0; // ignored, we only have vertical scrolling
|
||||
let rect = egui::Rect::from_min_max(egui::pos2(x, min_y), egui::pos2(x, max_y));
|
||||
let rect = egui::Rect::from_x_y_ranges(x..=x, y_range);
|
||||
let align = scroll_to_row.and_then(|(_, a)| a);
|
||||
ui.scroll_to_rect(rect, align);
|
||||
}
|
||||
|
|
@ -617,14 +617,14 @@ impl<'a> Table<'a> {
|
|||
for (i, column_width) in state.column_widths.iter_mut().enumerate() {
|
||||
let column = &columns[i];
|
||||
let column_is_resizable = column.resizable.unwrap_or(resizable);
|
||||
let (min_width, max_width) = column.width_range;
|
||||
let width_range = column.width_range;
|
||||
|
||||
if !column.clip {
|
||||
// Unless we clip we don't want to shrink below the
|
||||
// size that was actually used:
|
||||
*column_width = column_width.at_least(max_used_widths[i]);
|
||||
}
|
||||
*column_width = column_width.clamp(min_width, max_width);
|
||||
*column_width = width_range.clamp(*column_width);
|
||||
|
||||
let is_last_column = i + 1 == columns.len();
|
||||
|
||||
|
|
@ -633,7 +633,7 @@ impl<'a> Table<'a> {
|
|||
let eps = 0.1; // just to avoid some rounding errors.
|
||||
*column_width = available_width - eps;
|
||||
*column_width = column_width.at_least(max_used_widths[i]);
|
||||
*column_width = column_width.clamp(min_width, max_width);
|
||||
*column_width = width_range.clamp(*column_width);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -641,7 +641,7 @@ impl<'a> Table<'a> {
|
|||
|
||||
if column.is_auto() && (first_frame_auto_size_columns || !column_is_resizable) {
|
||||
*column_width = max_used_widths[i];
|
||||
*column_width = column_width.clamp(min_width, max_width);
|
||||
*column_width = width_range.clamp(*column_width);
|
||||
} else if column_is_resizable {
|
||||
let column_resize_id = ui.id().with("resize_column").with(i);
|
||||
|
||||
|
|
@ -656,7 +656,7 @@ impl<'a> Table<'a> {
|
|||
if resize_response.double_clicked() {
|
||||
// Resize to the minimum of what is needed.
|
||||
|
||||
*column_width = max_used_widths[i].clamp(min_width, max_width);
|
||||
*column_width = width_range.clamp(max_used_widths[i]);
|
||||
} else if resize_response.dragged() {
|
||||
if let Some(pointer) = ui.ctx().pointer_latest_pos() {
|
||||
let mut new_width = *column_width + pointer.x - x;
|
||||
|
|
@ -671,7 +671,7 @@ impl<'a> Table<'a> {
|
|||
new_width =
|
||||
new_width.at_least(max_used_widths[i] - max_shrinkage_per_frame);
|
||||
}
|
||||
new_width = new_width.clamp(min_width, max_width);
|
||||
new_width = width_range.clamp(new_width);
|
||||
|
||||
let x = x - *column_width + new_width;
|
||||
(p0.x, p1.x) = (x, x);
|
||||
|
|
@ -731,7 +731,7 @@ pub struct TableBody<'a> {
|
|||
|
||||
/// If we find the correct row to scroll to,
|
||||
/// this is set to the y-range of the row.
|
||||
scroll_to_y_range: &'a mut Option<(f32, f32)>,
|
||||
scroll_to_y_range: &'a mut Option<Rangef>,
|
||||
}
|
||||
|
||||
impl<'a> TableBody<'a> {
|
||||
|
|
@ -779,7 +779,7 @@ impl<'a> TableBody<'a> {
|
|||
let bottom_y = self.layout.cursor.y;
|
||||
|
||||
if Some(self.row_nr) == self.scroll_to_row {
|
||||
*self.scroll_to_y_range = Some((top_y, bottom_y));
|
||||
*self.scroll_to_y_range = Some(Rangef::new(top_y, bottom_y));
|
||||
}
|
||||
|
||||
self.row_nr += 1;
|
||||
|
|
@ -819,7 +819,7 @@ impl<'a> TableBody<'a> {
|
|||
|
||||
if let Some(scroll_to_row) = self.scroll_to_row {
|
||||
let scroll_to_row = scroll_to_row.at_most(total_rows.saturating_sub(1)) as f32;
|
||||
*self.scroll_to_y_range = Some((
|
||||
*self.scroll_to_y_range = Some(Rangef::new(
|
||||
self.layout.cursor.y + scroll_to_row * row_height_with_spacing,
|
||||
self.layout.cursor.y + (scroll_to_row + 1.0) * row_height_with_spacing,
|
||||
));
|
||||
|
|
@ -909,7 +909,7 @@ impl<'a> TableBody<'a> {
|
|||
cursor_y += (row_height + spacing.y) as f64;
|
||||
|
||||
if Some(row_index) == self.scroll_to_row {
|
||||
*self.scroll_to_y_range = Some((
|
||||
*self.scroll_to_y_range = Some(Rangef::new(
|
||||
(scroll_to_y_range_offset + old_cursor_y) as f32,
|
||||
(scroll_to_y_range_offset + cursor_y) as f32,
|
||||
));
|
||||
|
|
@ -953,7 +953,7 @@ impl<'a> TableBody<'a> {
|
|||
cursor_y += (row_height + spacing.y) as f64;
|
||||
|
||||
if Some(row_index) == self.scroll_to_row {
|
||||
*self.scroll_to_y_range = Some((
|
||||
*self.scroll_to_y_range = Some(Rangef::new(
|
||||
(scroll_to_y_range_offset + top_y) as f32,
|
||||
(scroll_to_y_range_offset + cursor_y) as f32,
|
||||
));
|
||||
|
|
@ -972,7 +972,7 @@ impl<'a> TableBody<'a> {
|
|||
let top_y = cursor_y;
|
||||
cursor_y += (row_height + spacing.y) as f64;
|
||||
if Some(row_index) == self.scroll_to_row {
|
||||
*self.scroll_to_y_range = Some((
|
||||
*self.scroll_to_y_range = Some(Rangef::new(
|
||||
(scroll_to_y_range_offset + top_y) as f32,
|
||||
(scroll_to_y_range_offset + cursor_y) as f32,
|
||||
));
|
||||
|
|
@ -981,10 +981,8 @@ impl<'a> TableBody<'a> {
|
|||
|
||||
if self.scroll_to_row.is_some() && self.scroll_to_y_range.is_none() {
|
||||
// Catch desire to scroll past the end:
|
||||
*self.scroll_to_y_range = Some((
|
||||
(scroll_to_y_range_offset + cursor_y) as f32,
|
||||
(scroll_to_y_range_offset + cursor_y) as f32,
|
||||
));
|
||||
*self.scroll_to_y_range =
|
||||
Some(Rangef::point((scroll_to_y_range_offset + cursor_y) as f32));
|
||||
}
|
||||
|
||||
if height_below_visible > 0.0 {
|
||||
|
|
|
|||
|
|
@ -110,29 +110,25 @@ impl Align {
|
|||
/// assert_eq!(Max .align_size_within_range(INFINITY, NEG_INFINITY..=20.0), NEG_INFINITY..=20.0);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn align_size_within_range(
|
||||
self,
|
||||
size: f32,
|
||||
range: RangeInclusive<f32>,
|
||||
) -> RangeInclusive<f32> {
|
||||
let min = *range.start();
|
||||
let max = *range.end();
|
||||
pub fn align_size_within_range(self, size: f32, range: impl Into<Rangef>) -> Rangef {
|
||||
let range = range.into();
|
||||
let Rangef { min, max } = range;
|
||||
|
||||
if max - min == f32::INFINITY && size == f32::INFINITY {
|
||||
return range;
|
||||
}
|
||||
|
||||
match self {
|
||||
Self::Min => min..=min + size,
|
||||
Self::Min => Rangef::new(min, min + size),
|
||||
Self::Center => {
|
||||
if size == f32::INFINITY {
|
||||
f32::NEG_INFINITY..=f32::INFINITY
|
||||
Rangef::new(f32::NEG_INFINITY, f32::INFINITY)
|
||||
} else {
|
||||
let left = (min + max) / 2.0 - size / 2.0;
|
||||
left..=left + size
|
||||
Rangef::new(left, left + size)
|
||||
}
|
||||
}
|
||||
Self::Max => max - size..=max,
|
||||
Self::Max => Rangef::new(max - size, max),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,11 +99,12 @@ impl Real for f64 {}
|
|||
/// assert_eq!(lerp(1.0..=5.0, 2.0), 9.0);
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn lerp<R, T>(range: RangeInclusive<R>, t: T) -> R
|
||||
pub fn lerp<R, T>(range: impl Into<RangeInclusive<R>>, t: T) -> R
|
||||
where
|
||||
T: Real + Mul<R, Output = R>,
|
||||
R: Copy + Add<R, Output = R>,
|
||||
{
|
||||
let range = range.into();
|
||||
(T::one() - t) * *range.start() + t * *range.end()
|
||||
}
|
||||
|
||||
|
|
@ -138,20 +139,28 @@ where
|
|||
/// Linearly remap a value from one range to another,
|
||||
/// so that when `x == from.start()` returns `to.start()`
|
||||
/// and when `x == from.end()` returns `to.end()`.
|
||||
pub fn remap<T>(x: T, from: RangeInclusive<T>, to: RangeInclusive<T>) -> T
|
||||
pub fn remap<T>(x: T, from: impl Into<RangeInclusive<T>>, to: impl Into<RangeInclusive<T>>) -> T
|
||||
where
|
||||
T: Real,
|
||||
{
|
||||
let from = from.into();
|
||||
let to = to.into();
|
||||
crate::emath_assert!(from.start() != from.end());
|
||||
let t = (x - *from.start()) / (*from.end() - *from.start());
|
||||
lerp(to, t)
|
||||
}
|
||||
|
||||
/// Like [`remap`], but also clamps the value so that the returned value is always in the `to` range.
|
||||
pub fn remap_clamp<T>(x: T, from: RangeInclusive<T>, to: RangeInclusive<T>) -> T
|
||||
pub fn remap_clamp<T>(
|
||||
x: T,
|
||||
from: impl Into<RangeInclusive<T>>,
|
||||
to: impl Into<RangeInclusive<T>>,
|
||||
) -> T
|
||||
where
|
||||
T: Real,
|
||||
{
|
||||
let from = from.into();
|
||||
let to = to.into();
|
||||
if from.end() < from.start() {
|
||||
return remap_clamp(x, *from.end()..=*from.start(), *to.end()..=*to.start());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,14 +36,60 @@ impl Rangef {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn span(&self) -> f32 {
|
||||
pub fn point(min_and_max: f32) -> Self {
|
||||
Self {
|
||||
min: min_and_max,
|
||||
max: min_and_max,
|
||||
}
|
||||
}
|
||||
|
||||
/// The length of the range, i.e. `max - min`.
|
||||
#[inline]
|
||||
pub fn span(self) -> f32 {
|
||||
self.max - self.min
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains(&self, x: f32) -> bool {
|
||||
#[must_use]
|
||||
pub fn contains(self, x: f32) -> bool {
|
||||
self.min <= x && x <= self.max
|
||||
}
|
||||
|
||||
/// Equivalent to `x.clamp(min, max)`
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn clamp(self, x: f32) -> f32 {
|
||||
x.clamp(self.min, self.max)
|
||||
}
|
||||
|
||||
/// Flip `min` and `max` if needed, so that `min <= max` after.
|
||||
#[inline]
|
||||
pub fn as_positive(self) -> Self {
|
||||
Rangef {
|
||||
min: self.min.min(self.max),
|
||||
max: self.min.max(self.max),
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrink by this much on each side, keeping the center
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn shrink(self, amnt: f32) -> Self {
|
||||
Self {
|
||||
min: self.min + amnt,
|
||||
max: self.max - amnt,
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand by this much on each side, keeping the center
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn expand(self, amnt: f32) -> Self {
|
||||
Self {
|
||||
min: self.min - amnt,
|
||||
max: self.max + amnt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rangef> for RangeInclusive<f32> {
|
||||
|
|
@ -108,3 +154,17 @@ impl From<RangeToInclusive<f32>> for Rangef {
|
|||
Self::new(f32::NEG_INFINITY, range.end)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<RangeInclusive<f32>> for Rangef {
|
||||
#[inline]
|
||||
fn eq(&self, other: &RangeInclusive<f32>) -> bool {
|
||||
self.min == *other.start() && self.max == *other.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Rangef> for RangeInclusive<f32> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Rangef) -> bool {
|
||||
*self.start() == other.min && *self.end() == other.max
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use std::f32::INFINITY;
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
|
@ -82,15 +81,12 @@ impl Rect {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_x_y_ranges(
|
||||
x_range: impl Into<RangeInclusive<f32>>,
|
||||
y_range: impl Into<RangeInclusive<f32>>,
|
||||
) -> Self {
|
||||
pub fn from_x_y_ranges(x_range: impl Into<Rangef>, y_range: impl Into<Rangef>) -> Self {
|
||||
let x_range = x_range.into();
|
||||
let y_range = y_range.into();
|
||||
Rect {
|
||||
min: pos2(*x_range.start(), *y_range.start()),
|
||||
max: pos2(*x_range.end(), *y_range.end()),
|
||||
min: pos2(x_range.min, y_range.min),
|
||||
max: pos2(x_range.max, y_range.max),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -390,18 +386,18 @@ impl Rect {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn x_range(&self) -> RangeInclusive<f32> {
|
||||
self.min.x..=self.max.x
|
||||
pub fn x_range(&self) -> Rangef {
|
||||
Rangef::new(self.min.x, self.max.x)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn y_range(&self) -> RangeInclusive<f32> {
|
||||
self.min.y..=self.max.y
|
||||
pub fn y_range(&self) -> Rangef {
|
||||
Rangef::new(self.min.y, self.max.y)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn bottom_up_range(&self) -> RangeInclusive<f32> {
|
||||
self.max.y..=self.min.y
|
||||
pub fn bottom_up_range(&self) -> Rangef {
|
||||
Rangef::new(self.max.y, self.min.y)
|
||||
}
|
||||
|
||||
/// `width < 0 || height < 0`
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
//! The different shapes that can be painted.
|
||||
|
||||
use std::ops::RangeInclusive;
|
||||
use std::{any::Any, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -94,17 +93,19 @@ impl Shape {
|
|||
}
|
||||
|
||||
/// A horizontal line.
|
||||
pub fn hline(x: RangeInclusive<f32>, y: f32, stroke: impl Into<Stroke>) -> Self {
|
||||
pub fn hline(x: impl Into<Rangef>, y: f32, stroke: impl Into<Stroke>) -> Self {
|
||||
let x = x.into();
|
||||
Shape::LineSegment {
|
||||
points: [pos2(*x.start(), y), pos2(*x.end(), y)],
|
||||
points: [pos2(x.min, y), pos2(x.max, y)],
|
||||
stroke: stroke.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// A vertical line.
|
||||
pub fn vline(x: f32, y: RangeInclusive<f32>, stroke: impl Into<Stroke>) -> Self {
|
||||
pub fn vline(x: f32, y: impl Into<Rangef>, stroke: impl Into<Stroke>) -> Self {
|
||||
let y = y.into();
|
||||
Shape::LineSegment {
|
||||
points: [pos2(x, *y.start()), pos2(x, *y.end())],
|
||||
points: [pos2(x, y.min), pos2(x, y.max)],
|
||||
stroke: stroke.into(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue