Browse Source

Add ui.drag_angle helper

pull/20/head
Emil Ernerfeldt 4 years ago
parent
commit
5df9bfd514
  1. 11
      egui/src/demos/app.rs
  2. 1
      egui/src/paint/font.rs
  3. 16
      egui/src/ui.rs
  4. 37
      egui/src/widgets.rs

11
egui/src/demos/app.rs

@ -416,6 +416,7 @@ struct Widgets {
count: usize,
radio: usize,
slider_value: f32,
angle: f32,
single_line_text_input: String,
multiline_text_input: String,
}
@ -427,6 +428,7 @@ impl Default for Widgets {
radio: 0,
count: 0,
slider_value: 3.4,
angle: TAU / 8.0,
single_line_text_input: "Hello World!".to_owned(),
multiline_text_input: "Text can both be so wide that it needs a line break, but you can also add manual line break by pressing enter, creating new paragraphs.\nThis is the start of the next paragraph.\n\nClick me to edit me!".to_owned(),
}
@ -480,6 +482,15 @@ impl Widgets {
}
}
ui.separator();
{
ui.label("An angle stored as radians, but edited in degrees:");
ui.horizontal_centered(|ui| {
ui.style_mut().item_spacing.x = 0.0;
ui.drag_angle(&mut self.angle);
ui.label(format!(" = {} radians", self.angle));
});
}
ui.separator();
ui.horizontal(|ui| {
ui.add(label!("Single line text input:"));

1
egui/src/paint/font.rs

@ -211,6 +211,7 @@ impl Font {
font.add_char(c);
}
font.add_char(REPLACEMENT_CHAR);
font.add_char('°');
font
}

16
egui/src/ui.rs

@ -506,6 +506,22 @@ impl Ui {
pub fn separator(&mut self) -> GuiResponse {
self.add(Separator::new())
}
/// Modify an angle. The given angle should be in radians, but is shown to the user in degrees.
/// The angle is NOT wrapped, so the user may select, for instance 720° = 2𝞃 = 4π
pub fn drag_angle(&mut self, radians: &mut f32) -> GuiResponse {
#![allow(clippy::float_cmp)]
let mut degrees = radians.to_degrees();
let response = self.add(DragValue::f32(&mut degrees).speed(1.0).suffix("°"));
// only touch `*radians` if we actually changed the degree value
if degrees != radians.to_degrees() {
*radians = degrees.to_radians();
}
response
}
}
/// # Adding Containers / Sub-uis:

37
egui/src/widgets.rs

@ -552,11 +552,18 @@ impl Widget for Separator {
pub struct DragValue<'a> {
value: &'a mut f32,
speed: f32,
prefix: String,
suffix: String,
}
impl<'a> DragValue<'a> {
pub fn f32(value: &'a mut f32) -> Self {
DragValue { value, speed: 1.0 }
DragValue {
value,
speed: 1.0,
prefix: Default::default(),
suffix: Default::default(),
}
}
/// How much the value changes when dragged one point (logical pixel).
@ -564,16 +571,30 @@ impl<'a> DragValue<'a> {
self.speed = speed;
self
}
/// Show a prefix before the number, e.g. "x: "
pub fn prefix(mut self, prefix: impl ToString) -> Self {
self.prefix = prefix.to_string();
self
}
/// Add a suffix to the number, this can be e.g. a unit ("°" or " m")
pub fn suffix(mut self, suffix: impl ToString) -> Self {
self.suffix = suffix.to_string();
self
}
}
impl<'a> Widget for DragValue<'a> {
fn ui(self, ui: &mut Ui) -> InteractInfo {
let Self { value, speed } = self;
let speed_in_physical_pixels = speed / ui.input().pixels_per_point;
let precision = (1.0 / speed_in_physical_pixels.abs())
.log10()
.ceil()
.max(0.0) as usize;
let Self {
value,
speed,
prefix,
suffix,
} = self;
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 value_text = format_with_minimum_precision(*value, precision);
let kb_edit_id = ui.make_position_id().with("edit");
@ -602,7 +623,7 @@ impl<'a> Widget for DragValue<'a> {
}
response.into()
} else {
let button = Button::new(value_text)
let button = Button::new(format!("{}{}{}", prefix, value_text, suffix))
.sense(Sense::click_and_drag())
.text_style(TextStyle::Monospace);
let response = ui.add(button);

Loading…
Cancel
Save