Skip to content

Commit

Permalink
Add rectangular handle for slider
Browse files Browse the repository at this point in the history
Closes #1974
  • Loading branch information
YgorSouza committed Oct 2, 2023
1 parent 12b6f2c commit 9327c1b
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 12 deletions.
47 changes: 47 additions & 0 deletions crates/egui/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,19 @@ pub struct Selection {
pub stroke: Stroke,
}

/// Shape of the handle for sliders and similar widgets.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum HandleShape {
/// Circular handle
Circle,
/// Rectangular handle
Rect {
/// Aspect ratio of the rectangle. Set to < 1.0 to make it narrower.
aspect_ratio: f32,
},
}

/// The visuals of widgets for different states of interaction.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
Expand Down Expand Up @@ -683,6 +696,9 @@ pub struct WidgetVisuals {

/// Make the frame this much larger.
pub expansion: f32,

/// Shape of the handle for sliders and similar widgets.
pub handle_shape: HandleShape,
}

impl WidgetVisuals {
Expand Down Expand Up @@ -934,6 +950,7 @@ impl Widgets {
fg_stroke: Stroke::new(1.0, Color32::from_gray(140)), // normal text color
rounding: Rounding::same(2.0),
expansion: 0.0,
handle_shape: HandleShape::Circle,
},
inactive: WidgetVisuals {
weak_bg_fill: Color32::from_gray(60), // button background
Expand All @@ -942,6 +959,7 @@ impl Widgets {
fg_stroke: Stroke::new(1.0, Color32::from_gray(180)), // button text
rounding: Rounding::same(2.0),
expansion: 0.0,
handle_shape: HandleShape::Circle,
},
hovered: WidgetVisuals {
weak_bg_fill: Color32::from_gray(70),
Expand All @@ -950,6 +968,7 @@ impl Widgets {
fg_stroke: Stroke::new(1.5, Color32::from_gray(240)),
rounding: Rounding::same(3.0),
expansion: 1.0,
handle_shape: HandleShape::Circle,
},
active: WidgetVisuals {
weak_bg_fill: Color32::from_gray(55),
Expand All @@ -958,6 +977,7 @@ impl Widgets {
fg_stroke: Stroke::new(2.0, Color32::WHITE),
rounding: Rounding::same(2.0),
expansion: 1.0,
handle_shape: HandleShape::Circle,
},
open: WidgetVisuals {
weak_bg_fill: Color32::from_gray(27),
Expand All @@ -966,6 +986,7 @@ impl Widgets {
fg_stroke: Stroke::new(1.0, Color32::from_gray(210)),
rounding: Rounding::same(2.0),
expansion: 0.0,
handle_shape: HandleShape::Circle,
},
}
}
Expand All @@ -979,6 +1000,7 @@ impl Widgets {
fg_stroke: Stroke::new(1.0, Color32::from_gray(80)), // normal text color
rounding: Rounding::same(2.0),
expansion: 0.0,
handle_shape: HandleShape::Circle,
},
inactive: WidgetVisuals {
weak_bg_fill: Color32::from_gray(230), // button background
Expand All @@ -987,6 +1009,7 @@ impl Widgets {
fg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // button text
rounding: Rounding::same(2.0),
expansion: 0.0,
handle_shape: HandleShape::Circle,
},
hovered: WidgetVisuals {
weak_bg_fill: Color32::from_gray(220),
Expand All @@ -995,6 +1018,7 @@ impl Widgets {
fg_stroke: Stroke::new(1.5, Color32::BLACK),
rounding: Rounding::same(3.0),
expansion: 1.0,
handle_shape: HandleShape::Circle,
},
active: WidgetVisuals {
weak_bg_fill: Color32::from_gray(165),
Expand All @@ -1003,6 +1027,7 @@ impl Widgets {
fg_stroke: Stroke::new(2.0, Color32::BLACK),
rounding: Rounding::same(2.0),
expansion: 1.0,
handle_shape: HandleShape::Circle,
},
open: WidgetVisuals {
weak_bg_fill: Color32::from_gray(220),
Expand All @@ -1011,6 +1036,7 @@ impl Widgets {
fg_stroke: Stroke::new(1.0, Color32::BLACK),
rounding: Rounding::same(2.0),
expansion: 0.0,
handle_shape: HandleShape::Circle,
},
}
}
Expand Down Expand Up @@ -1357,6 +1383,7 @@ impl WidgetVisuals {
rounding,
fg_stroke,
expansion,
handle_shape,
} = self;
ui_color(ui, weak_bg_fill, "optional background fill")
.on_hover_text("For buttons, combo-boxes, etc");
Expand All @@ -1369,6 +1396,7 @@ impl WidgetVisuals {
stroke_ui(ui, fg_stroke, "foreground stroke (text)");
ui.add(Slider::new(expansion, -5.0..=5.0).text("expansion"))
.on_hover_text("make shapes this much larger");
handle_shape_ui(ui, handle_shape);
}
}

Expand Down Expand Up @@ -1630,3 +1658,22 @@ fn rounding_ui(ui: &mut Ui, rounding: &mut Rounding) {
}
});
}

fn handle_shape_ui(ui: &mut Ui, handle_shape: &mut HandleShape) {
ui.label("Widget handle shape");
ui.horizontal(|ui| {
ui.radio_value(handle_shape, HandleShape::Circle, "Circle");
if ui
.radio(
matches!(handle_shape, HandleShape::Rect { aspect_ratio: _ }),
"Rectangle",
)
.clicked()
{
*handle_shape = HandleShape::Rect { aspect_ratio: 0.5 };
}
if let HandleShape::Rect { aspect_ratio } = handle_shape {
ui.add(Slider::new(aspect_ratio, 0.1..=3.0).text("Aspect ratio"));
}
});
}
53 changes: 41 additions & 12 deletions crates/egui/src/widgets/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ impl<'a> Slider<'a> {
/// Just the slider, no text
fn slider_ui(&mut self, ui: &mut Ui, response: &Response) {
let rect = &response.rect;
let position_range = self.position_range(rect);
let position_range = self.position_range(rect, &ui.style().interact(response).handle_shape);

if let Some(pointer_position_2d) = response.interact_pointer_pos() {
let position = self.pointer_position(pointer_position_2d);
Expand Down Expand Up @@ -676,12 +676,36 @@ impl<'a> Slider<'a> {
);
}

ui.painter().add(epaint::CircleShape {
center,
radius: self.handle_radius(rect) + visuals.expansion,
fill: visuals.bg_fill,
stroke: visuals.fg_stroke,
});
let radius = self.handle_radius(rect, &visuals.handle_shape);
match visuals.handle_shape {
style::HandleShape::Circle => {
ui.painter().add(epaint::CircleShape {
center,
radius: radius + visuals.expansion,
fill: visuals.bg_fill,
stroke: visuals.fg_stroke,
});
}
style::HandleShape::Rect { aspect_ratio } => {
let v = match self.orientation {
SliderOrientation::Horizontal => Vec2::new(radius, radius / aspect_ratio),
SliderOrientation::Vertical => Vec2::new(radius / aspect_ratio, radius),
};
let v = v + Vec2::splat(visuals.expansion);
let rect = Rect {
min: center - v,
max: center + v,
};
ui.painter().add(epaint::RectShape {
fill: visuals.bg_fill,
stroke: visuals.fg_stroke,
rect,
rounding: visuals.rounding,
fill_texture_id: Default::default(),
uv: Rect::ZERO,
});
}
}
}
}

Expand All @@ -699,8 +723,8 @@ impl<'a> Slider<'a> {
}
}

fn position_range(&self, rect: &Rect) -> Rangef {
let handle_radius = self.handle_radius(rect);
fn position_range(&self, rect: &Rect, handle_shape: &style::HandleShape) -> Rangef {
let handle_radius = self.handle_radius(rect, handle_shape);
match self.orientation {
SliderOrientation::Horizontal => rect.x_range().shrink(handle_radius),
SliderOrientation::Vertical => rect.y_range().shrink(handle_radius),
Expand All @@ -720,12 +744,16 @@ impl<'a> Slider<'a> {
}
}

fn handle_radius(&self, rect: &Rect) -> f32 {
fn handle_radius(&self, rect: &Rect, handle_shape: &style::HandleShape) -> f32 {
let limit = match self.orientation {
SliderOrientation::Horizontal => rect.height(),
SliderOrientation::Vertical => rect.width(),
};
limit / 2.5
let aspect_ratio = match handle_shape {
style::HandleShape::Circle => 1.0,
style::HandleShape::Rect { aspect_ratio } => *aspect_ratio,
};
limit / (2.5 / aspect_ratio)
}

fn rail_radius_limit(&self, rect: &Rect) -> f32 {
Expand Down Expand Up @@ -820,7 +848,8 @@ impl<'a> Slider<'a> {
let slider_response = response.clone();

let value_response = if self.show_value {
let position_range = self.position_range(&response.rect);
let position_range =
self.position_range(&response.rect, &ui.style().interact(&response).handle_shape);
let value_response = self.value_ui(ui, position_range);
if value_response.gained_focus()
|| value_response.has_focus()
Expand Down

0 comments on commit 9327c1b

Please sign in to comment.