Skip to content

Commit

Permalink
add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
hacknus committed Oct 30, 2024
1 parent b4eb83f commit 90e52ea
Showing 1 changed file with 41 additions and 17 deletions.
58 changes: 41 additions & 17 deletions crates/egui/src/widgets/double_slider.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::emath;
use crate::emath::{Pos2, Rect, Vec2};
use crate::epaint::{CircleShape, Color32, PathShape, Shape, Stroke};
use crate::{Sense, Ui, Widget};
Expand All @@ -7,6 +6,21 @@ use std::ops::RangeInclusive;
// offset for stroke highlight
const OFFSET: f32 = 2.0;

/// Control two numbers with a double slider.
///
/// The slider range defines the values you get when pulling the slider to the far edges.
///
/// The range can include any numbers, and go from low-to-high or from high-to-low.
///
///
/// ```
/// # egui::__run_test_ui(|ui| {
/// # let mut my_f32: f32 = 0.0;
/// # let mut my_other_f32: f32 = 0.0;
/// ui.add(egui::DoubleSlider::new(&mut my_f32,&mut my_other_f32, 0.0..=100.0));
/// # });
/// ```
///
#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
pub struct DoubleSlider<'a> {
left_slider: &'a mut f32,
Expand Down Expand Up @@ -39,64 +53,64 @@ impl<'a> DoubleSlider<'a> {
}
}

#[allow(dead_code)]
/// Set the primary width for the slider.
#[inline]
pub fn width(mut self, width: f32) -> Self {
self.width = width;
self
}

#[allow(dead_code)]
/// Set the separation distance for the two sliders.
#[inline]
pub fn separation_distance(mut self, separation_distance: f32) -> Self {
self.separation_distance = separation_distance;
self
}

#[allow(dead_code)]
/// Set the primary color for the slider.
#[inline]
pub fn color(mut self, color: Color32) -> Self {
self.color = color;
self
}

#[allow(dead_code)]
/// Set the stroke for the main line.
#[inline]
pub fn stroke(mut self, stroke: Stroke) -> Self {
self.stroke = stroke;
self
}

#[allow(dead_code)]
/// Set the color fill for the slider cursor.
#[inline]
pub fn cursor_fill(mut self, cursor_fill: Color32) -> Self {
self.cursor_fill = cursor_fill;
self
}

#[allow(dead_code)]
/// Set the auxiliary stroke.
#[inline]
pub fn aux_stroke(mut self, aux_stroke: Stroke) -> Self {
self.stroke = aux_stroke;
self
}

#[allow(dead_code)]
/// Set the control point radius
#[inline]
pub fn control_point_radius(mut self, control_point_radius: f32) -> Self {
self.control_point_radius = control_point_radius;
self
}

fn to_coord(&self, num: f32) -> f32 {
fn val_to_x(&self, val: f32) -> f32 {
(self.width - 2.0 * self.control_point_radius - 2.0 * OFFSET)
/ (self.range.end() - self.range.start())
* (num - self.range.start())
* (val - self.range.start())
+ self.control_point_radius
+ OFFSET
}

fn from_coord(&self, x: f32) -> f32 {
fn x_to_val(&self, x: f32) -> f32 {
(self.range.end() - self.range.start())
/ (self.width - 2.0 * self.control_point_radius - 2.0 * OFFSET)
* x
Expand All @@ -105,6 +119,7 @@ impl<'a> DoubleSlider<'a> {

impl<'a> Widget for DoubleSlider<'a> {
fn ui(self, ui: &mut Ui) -> crate::Response {
// calculate height
let height = 2.0 * self.control_point_radius + 2.0 * OFFSET;

let (response, painter) =
Expand All @@ -114,6 +129,7 @@ impl<'a> Widget for DoubleSlider<'a> {
let mut right_edge = response.rect.right_center();
right_edge.x -= self.control_point_radius;

// draw the line
painter.add(PathShape::line(
vec![left_edge, right_edge],
Stroke::new(self.stroke.width, self.color),
Expand All @@ -124,17 +140,20 @@ impl<'a> Widget for DoubleSlider<'a> {
response.rect,
);

// handle lower bound
let lower_bound = {
// get the control point
let size = Vec2::splat(2.0 * self.control_point_radius);
let point_in_screen = to_screen.transform_pos(Pos2 {
x: self.to_coord(*self.left_slider),
x: self.val_to_x(*self.left_slider),
y: self.control_point_radius + OFFSET,
});
let point_rect = Rect::from_center_size(point_in_screen, size);
let point_id = response.id.with(0);
let point_response = ui.interact(point_rect, point_id, Sense::drag());

*self.left_slider += self.from_coord(point_response.drag_delta().x);
// handle logic
*self.left_slider += self.x_to_val(point_response.drag_delta().x);
if *self.right_slider < *self.left_slider + self.separation_distance {
*self.right_slider = *self.left_slider + self.separation_distance;
}
Expand All @@ -155,17 +174,20 @@ impl<'a> Widget for DoubleSlider<'a> {
}
};

// handle upper bound
let upper_bound = {
// get the control point
let size = Vec2::splat(2.0 * self.control_point_radius);
let point_in_screen = to_screen.transform_pos(Pos2 {
x: self.to_coord(*self.right_slider),
x: self.val_to_x(*self.right_slider),
y: self.control_point_radius + OFFSET,
});
let point_rect = Rect::from_center_size(point_in_screen, size);
let point_id = response.id.with(1);
let point_response = ui.interact(point_rect, point_id, Sense::drag());

*self.right_slider += self.from_coord(point_response.drag_delta().x);
// handle logic
*self.right_slider += self.x_to_val(point_response.drag_delta().x);
if *self.left_slider > *self.right_slider - self.separation_distance {
*self.left_slider = *self.right_slider - self.separation_distance;
}
Expand All @@ -187,8 +209,8 @@ impl<'a> Widget for DoubleSlider<'a> {
};

let points_in_screen: Vec<Pos2> = [
self.to_coord(*self.left_slider),
self.to_coord(*self.right_slider),
self.val_to_x(*self.left_slider),
self.val_to_x(*self.right_slider),
]
.iter()
.map(|p| {
Expand All @@ -200,7 +222,9 @@ impl<'a> Widget for DoubleSlider<'a> {
})
.collect();

// draw line between points
painter.add(PathShape::line(points_in_screen, self.stroke));
// draw control points
painter.extend([Shape::Circle(lower_bound), Shape::Circle(upper_bound)]);

response
Expand Down

0 comments on commit 90e52ea

Please sign in to comment.