impl<F> Widget for F where F: FnOnce(&mut Ui) -> Response
This enables functions that return `impl Widget`, so that you can create a widget by just returning a lambda from a function. For instance: `ui.add(toggle(bool))` (instead of `toggle(ui, bool)`)
This commit is contained in:
parent
6fe70e685b
commit
040553da78
4 changed files with 62 additions and 48 deletions
|
@ -506,10 +506,10 @@ impl Spacing {
|
||||||
tooltip_width,
|
tooltip_width,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
ui_slider_vec2(ui, item_spacing, 0.0..=10.0, "item_spacing");
|
ui.add(slider_vec2(item_spacing, 0.0..=10.0, "item_spacing"));
|
||||||
ui_slider_vec2(ui, window_padding, 0.0..=10.0, "window_padding");
|
ui.add(slider_vec2(window_padding, 0.0..=10.0, "window_padding"));
|
||||||
ui_slider_vec2(ui, button_padding, 0.0..=10.0, "button_padding");
|
ui.add(slider_vec2(button_padding, 0.0..=10.0, "button_padding"));
|
||||||
ui_slider_vec2(ui, interact_size, 0.0..=60.0, "interact_size")
|
ui.add(slider_vec2(interact_size, 0.0..=60.0, "interact_size"))
|
||||||
.on_hover_text("Minimum size of an interactive widget");
|
.on_hover_text("Minimum size of an interactive widget");
|
||||||
ui.add(Slider::f32(indent, 0.0..=100.0).text("indent"));
|
ui.add(Slider::f32(indent, 0.0..=100.0).text("indent"));
|
||||||
ui.add(Slider::f32(slider_width, 0.0..=1000.0).text("slider_width"));
|
ui.add(Slider::f32(slider_width, 0.0..=1000.0).text("slider_width"));
|
||||||
|
@ -694,38 +694,20 @@ impl Visuals {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: improve and standardize ui_slider_vec2
|
// TODO: improve and standardize `slider_vec2`
|
||||||
fn ui_slider_vec2(
|
fn slider_vec2<'a>(
|
||||||
ui: &mut Ui,
|
value: &'a mut Vec2,
|
||||||
value: &mut Vec2,
|
|
||||||
range: std::ops::RangeInclusive<f32>,
|
range: std::ops::RangeInclusive<f32>,
|
||||||
text: &str,
|
text: &'a str,
|
||||||
) -> Response {
|
) -> impl Widget + 'a {
|
||||||
ui.horizontal(|ui| {
|
move |ui: &mut crate::Ui| {
|
||||||
/*
|
ui.horizontal(|ui| {
|
||||||
let fsw = full slider_width
|
ui.add(Slider::f32(&mut value.x, range.clone()).text("w"));
|
||||||
let ssw = small slider_width
|
ui.add(Slider::f32(&mut value.y, range.clone()).text("h"));
|
||||||
let space = item_spacing.x
|
ui.label(text);
|
||||||
let value = interact_size.x;
|
})
|
||||||
|
.response
|
||||||
fsw + space + value = ssw + space + value + space + ssw + space + value
|
}
|
||||||
fsw + space + value = 2 * ssw + 3 * space + 2 * value
|
|
||||||
fsw + space - value = 2 * ssw + 3 * space
|
|
||||||
fsw - 2 * space - value = 2 * ssw
|
|
||||||
ssw = fsw / 2 - space - value / 2
|
|
||||||
*/
|
|
||||||
// let spacing = &ui.spacing();
|
|
||||||
// let space = spacing.item_spacing.x;
|
|
||||||
// let value_w = spacing.interact_size.x;
|
|
||||||
// let full_slider_width = spacing.slider_width;
|
|
||||||
// let small_slider_width = full_slider_width / 2.0 - space - value_w / 2.0;
|
|
||||||
// ui.spacing_mut().slider_width = small_slider_width;
|
|
||||||
|
|
||||||
ui.add(Slider::f32(&mut value.x, range.clone()).text("w"));
|
|
||||||
ui.add(Slider::f32(&mut value.y, range.clone()).text("h"));
|
|
||||||
ui.label(text);
|
|
||||||
})
|
|
||||||
.response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_color(ui: &mut Ui, srgba: &mut Color32, text: &str) {
|
fn ui_color(ui: &mut Ui, srgba: &mut Color32, text: &str) {
|
||||||
|
|
|
@ -35,6 +35,31 @@ pub trait Widget {
|
||||||
fn ui(self, ui: &mut Ui) -> Response;
|
fn ui(self, ui: &mut Ui) -> Response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This enables functions that return `impl Widget`, so that you can
|
||||||
|
/// create a widget by just returning a lambda from a function.
|
||||||
|
///
|
||||||
|
/// For instance: `ui.add(slider_vec2(&mut vec2));` with:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// pub fn slider_vec2(value: &mut egui::Vec2) -> impl egui::Widget + '_ {
|
||||||
|
/// move |ui: &mut egui::Ui| {
|
||||||
|
/// ui.horizontal(|ui| {
|
||||||
|
/// ui.add(egui::Slider::f32(&mut value.x, 0.0..=1.0).text("x"));
|
||||||
|
/// ui.add(egui::Slider::f32(&mut value.y, 0.0..=1.0).text("y"));
|
||||||
|
/// })
|
||||||
|
/// .response
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
impl<F> Widget for F
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut Ui) -> Response,
|
||||||
|
{
|
||||||
|
fn ui(self, ui: &mut Ui) -> Response {
|
||||||
|
self(ui)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Show a button to reset a value to its default.
|
/// Show a button to reset a value to its default.
|
||||||
|
|
|
@ -9,7 +9,12 @@
|
||||||
/// | |.......|
|
/// | |.......|
|
||||||
/// \_______\_____/
|
/// \_______\_____/
|
||||||
/// ```
|
/// ```
|
||||||
pub fn toggle(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
///
|
||||||
|
/// ## Example:
|
||||||
|
/// ``` ignore
|
||||||
|
/// toggle_ui(ui, &mut my_bool);
|
||||||
|
/// ```
|
||||||
|
pub fn toggle_ui(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
||||||
// Widget code can be broken up in four steps:
|
// Widget code can be broken up in four steps:
|
||||||
// 1. Decide a size for the widget
|
// 1. Decide a size for the widget
|
||||||
// 2. Allocate space for it
|
// 2. Allocate space for it
|
||||||
|
@ -58,7 +63,7 @@ pub fn toggle(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
||||||
|
|
||||||
/// Here is the same code again, but a bit more compact:
|
/// Here is the same code again, but a bit more compact:
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn toggle_compact(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
fn toggle_ui_compact(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
||||||
let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0, 1.0);
|
let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0, 1.0);
|
||||||
let (rect, response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
|
let (rect, response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
|
||||||
*on ^= response.clicked(); // toggle if clicked
|
*on ^= response.clicked(); // toggle if clicked
|
||||||
|
@ -77,14 +82,13 @@ fn toggle_compact(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn demo(ui: &mut egui::Ui, on: &mut bool) {
|
// A wrapper that allows the more idiomatic usage pattern: `ui.add(toggle(&mut my_bool))`
|
||||||
ui.horizontal_wrapped_for_text(egui::TextStyle::Button, |ui| {
|
/// iOS-style toggle switch.
|
||||||
toggle(ui, on).on_hover_text("Click to toggle");
|
///
|
||||||
ui.add(crate::__egui_github_link_file!());
|
/// ## Example:
|
||||||
})
|
/// ``` ignore
|
||||||
.response
|
/// ui.add(toggle(&mut my_bool));
|
||||||
.on_hover_text(
|
/// ```
|
||||||
"It's easy to create your own widgets!\n\
|
pub fn toggle(on: &mut bool) -> impl egui::Widget + '_ {
|
||||||
This toggle switch is just one function and 15 lines of code.",
|
move |ui: &mut egui::Ui| toggle_ui(ui, on)
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,10 @@ impl super::View for WidgetGallery {
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
|
|
||||||
ui.label("Custom widget:");
|
ui.label("Custom widget:");
|
||||||
super::toggle_switch::demo(ui, boolean);
|
ui.add(super::toggle_switch::toggle(boolean)).on_hover_text(
|
||||||
|
"It's easy to create your own widgets!\n\
|
||||||
|
This toggle switch is just 15 lines of code.",
|
||||||
|
);
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
|
|
||||||
ui.label("Plot:");
|
ui.label("Plot:");
|
||||||
|
|
Loading…
Reference in a new issue