1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
//! Widgets are pieces of GUI such as [`Label`], [`Button`], [`Slider`] etc.
//!
//! Example widget uses:
//! * `ui.add(Label::new("Text").text_color(color::red));`
//! * `if ui.add(Button::new("Click me")).clicked() { … }`
use crate::{epaint, Response, Ui};
mod button;
mod checkbox;
pub mod color_picker;
pub(crate) mod drag_value;
mod hyperlink;
mod image;
mod image_button;
mod label;
mod progress_bar;
mod radio_button;
mod selected_label;
mod separator;
mod slider;
mod spinner;
pub mod text_edit;
pub use self::{
button::Button,
checkbox::Checkbox,
drag_value::DragValue,
hyperlink::{Hyperlink, Link},
image::{
decode_gif_uri, has_gif_magic_header, paint_texture_at, GifFrameDurations, Image, ImageFit,
ImageOptions, ImageSize, ImageSource,
},
image_button::ImageButton,
label::Label,
progress_bar::ProgressBar,
radio_button::RadioButton,
selected_label::SelectableLabel,
separator::Separator,
slider::{Slider, SliderClamping, SliderOrientation},
spinner::Spinner,
text_edit::{TextBuffer, TextEdit},
};
// ----------------------------------------------------------------------------
/// Anything implementing Widget can be added to a [`Ui`] with [`Ui::add`].
///
/// [`Button`], [`Label`], [`Slider`], etc all implement the [`Widget`] trait.
///
/// You only need to implement `Widget` if you care about being able to do `ui.add(your_widget);`.
///
/// Note that the widgets ([`Button`], [`TextEdit`] etc) are
/// [builders](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html),
/// and not objects that hold state.
///
/// Tip: you can `impl Widget for &mut YourThing { }`.
///
/// `|ui: &mut Ui| -> Response { … }` also implements [`Widget`].
#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
pub trait Widget {
/// Allocate space, interact, paint, and return a [`Response`].
///
/// Note that this consumes `self`.
/// This is because most widgets ([`Button`], [`TextEdit`] etc) are
/// [builders](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html)
///
/// Tip: you can `impl Widget for &mut YourObject { }`.
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::new(&mut value.x, 0.0..=1.0).text("x"));
/// ui.add(egui::Slider::new(&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)
}
}
/// Helper so that you can do e.g. `TextEdit::State::load`.
pub trait WidgetWithState {
type State;
}
// ----------------------------------------------------------------------------
/// Show a button to reset a value to its default.
/// The button is only enabled if the value does not already have its original value.
///
/// The `text` could be something like "Reset foo".
pub fn reset_button<T: Default + PartialEq>(ui: &mut Ui, value: &mut T, text: &str) {
reset_button_with(ui, value, text, T::default());
}
/// Show a button to reset a value to its default.
/// The button is only enabled if the value does not already have its original value.
///
/// The `text` could be something like "Reset foo".
pub fn reset_button_with<T: PartialEq>(ui: &mut Ui, value: &mut T, text: &str, reset_value: T) {
if ui
.add_enabled(*value != reset_value, Button::new(text))
.clicked()
{
*value = reset_value;
}
}
// ----------------------------------------------------------------------------
#[deprecated = "Use `ui.add(&mut stroke)` instead"]
pub fn stroke_ui(ui: &mut crate::Ui, stroke: &mut epaint::Stroke, text: &str) {
ui.horizontal(|ui| {
ui.label(text);
ui.add(stroke);
});
}
/// Show a small button to switch to/from dark/light mode (globally).
pub fn global_theme_preference_switch(ui: &mut Ui) {
if let Some(new_theme) = ui.ctx().theme().small_toggle_button(ui) {
ui.ctx().set_theme(new_theme);
}
}
/// Show larger buttons for switching between light and dark mode (globally).
pub fn global_theme_preference_buttons(ui: &mut Ui) {
let mut theme_preference = ui.ctx().options(|opt| opt.theme_preference);
theme_preference.radio_buttons(ui);
ui.ctx().set_theme(theme_preference);
}
/// Show a small button to switch to/from dark/light mode (globally).
#[deprecated = "Use global_theme_preference_switch instead"]
pub fn global_dark_light_mode_switch(ui: &mut Ui) {
global_theme_preference_switch(ui);
}
/// Show larger buttons for switching between light and dark mode (globally).
#[deprecated = "Use global_theme_preference_buttons instead"]
pub fn global_dark_light_mode_buttons(ui: &mut Ui) {
global_theme_preference_buttons(ui);
}