1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 21:30:03 -04:00

Merge branch 'master' into axis-labels

This commit is contained in:
Emil Ernerfeldt
2023-08-14 13:23:26 +02:00
156 changed files with 1778 additions and 1026 deletions

View File

@@ -4,7 +4,7 @@ version = "0.22.0"
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
description = "Example library for egui"
edition = "2021"
rust-version = "1.65"
rust-version = "1.67"
homepage = "https://github.com/emilk/egui/tree/master/crates/egui_demo_lib"
license = "MIT OR Apache-2.0"
readme = "README.md"

View File

@@ -83,11 +83,11 @@ fn about_immediate_mode(ui: &mut egui::Ui) {
fn links(ui: &mut egui::Ui) {
use egui::special_emojis::{GITHUB, TWITTER};
ui.hyperlink_to(
format!("{} egui on GitHub", GITHUB),
format!("{GITHUB} egui on GitHub"),
"https://github.com/emilk/egui",
);
ui.hyperlink_to(
format!("{} @ernerfeldt", TWITTER),
format!("{TWITTER} @ernerfeldt"),
"https://twitter.com/ernerfeldt",
);
ui.hyperlink_to("egui documentation", "https://docs.rs/egui/");

View File

@@ -121,7 +121,7 @@ impl CodeExample {
ui.separator();
code_view_ui(ui, &format!("{:#?}", self));
code_view_ui(ui, &format!("{self:#?}"));
ui.separator();

View File

@@ -251,11 +251,11 @@ impl DemoWindows {
use egui::special_emojis::{GITHUB, TWITTER};
ui.hyperlink_to(
format!("{} egui on GitHub", GITHUB),
format!("{GITHUB} egui on GitHub"),
"https://github.com/emilk/egui",
);
ui.hyperlink_to(
format!("{} @ernerfeldt", TWITTER),
format!("{TWITTER} @ernerfeldt"),
"https://twitter.com/ernerfeldt",
);

View File

@@ -140,7 +140,7 @@ impl LayoutTest {
Direction::TopDown,
Direction::BottomUp,
] {
ui.radio_value(&mut self.layout.main_dir, dir, format!("{:?}", dir));
ui.radio_value(&mut self.layout.main_dir, dir, format!("{dir:?}"));
}
});
@@ -162,7 +162,7 @@ impl LayoutTest {
ui.horizontal(|ui| {
ui.label("Cross Align:");
for &align in &[Align::Min, Align::Center, Align::Max] {
ui.radio_value(&mut self.layout.cross_align, align, format!("{:?}", align));
ui.radio_value(&mut self.layout.cross_align, align, format!("{align:?}"));
}
});

View File

@@ -1,5 +1,4 @@
use super::*;
use crate::LOREM_IPSUM;
use egui::{epaint::text::TextWrapping, *};
/// Showcase some ui code
@@ -8,9 +7,7 @@ use egui::{epaint::text::TextWrapping, *};
pub struct MiscDemoWindow {
num_columns: usize,
break_anywhere: bool,
max_rows: usize,
overflow_character: Option<char>,
text_break: TextBreakDemo,
widgets: Widgets,
colors: ColorWidgets,
@@ -27,9 +24,7 @@ impl Default for MiscDemoWindow {
MiscDemoWindow {
num_columns: 2,
max_rows: 2,
break_anywhere: false,
overflow_character: Some('…'),
text_break: Default::default(),
widgets: Default::default(),
colors: Default::default(),
@@ -61,8 +56,14 @@ impl View for MiscDemoWindow {
fn ui(&mut self, ui: &mut Ui) {
ui.set_min_width(250.0);
CollapsingHeader::new("Widgets")
CollapsingHeader::new("Label")
.default_open(true)
.show(ui, |ui| {
label_ui(ui);
});
CollapsingHeader::new("Misc widgets")
.default_open(false)
.show(ui, |ui| {
self.widgets.ui(ui);
});
@@ -70,12 +71,12 @@ impl View for MiscDemoWindow {
CollapsingHeader::new("Text layout")
.default_open(false)
.show(ui, |ui| {
text_layout_ui(
ui,
&mut self.max_rows,
&mut self.break_anywhere,
&mut self.overflow_character,
);
text_layout_demo(ui);
ui.separator();
self.text_break.ui(ui);
ui.vertical_centered(|ui| {
ui.add(crate::egui_github_link_file_line!());
});
});
CollapsingHeader::new("Colors")
@@ -177,6 +178,43 @@ impl View for MiscDemoWindow {
// ----------------------------------------------------------------------------
fn label_ui(ui: &mut egui::Ui) {
ui.vertical_centered(|ui| {
ui.add(crate::egui_github_link_file_line!());
});
ui.horizontal_wrapped(|ui| {
// Trick so we don't have to add spaces in the text below:
let width = ui.fonts(|f|f.glyph_width(&TextStyle::Body.resolve(ui.style()), ' '));
ui.spacing_mut().item_spacing.x = width;
ui.label(RichText::new("Text can have").color(Color32::from_rgb(110, 255, 110)));
ui.colored_label(Color32::from_rgb(128, 140, 255), "color"); // Shortcut version
ui.label("and tooltips.").on_hover_text(
"This is a multiline tooltip that demonstrates that you can easily add tooltips to any element.\nThis is the second line.\nThis is the third.",
);
ui.label("You can mix in other widgets into text, like");
let _ = ui.small_button("this button");
ui.label(".");
ui.label("The default font supports all latin and cyrillic characters (ИÅđ…), common math symbols (∫√∞²⅓…), and many emojis (💓🌟🖩…).")
.on_hover_text("There is currently no support for right-to-left languages.");
ui.label("See the 🔤 Font Book for more!");
ui.monospace("There is also a monospace font.");
});
ui.add(
egui::Label::new(
"Labels containing long text can be set to elide the text that doesn't fit on a single line using `Label::elide`. When hovered, the label will show the full text.",
)
.truncate(true),
);
}
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Widgets {
@@ -200,28 +238,6 @@ impl Widgets {
ui.add(crate::egui_github_link_file_line!());
});
ui.horizontal_wrapped(|ui| {
// Trick so we don't have to add spaces in the text below:
let width = ui.fonts(|f|f.glyph_width(&TextStyle::Body.resolve(ui.style()), ' '));
ui.spacing_mut().item_spacing.x = width;
ui.label(RichText::new("Text can have").color(Color32::from_rgb(110, 255, 110)));
ui.colored_label(Color32::from_rgb(128, 140, 255), "color"); // Shortcut version
ui.label("and tooltips.").on_hover_text(
"This is a multiline tooltip that demonstrates that you can easily add tooltips to any element.\nThis is the second line.\nThis is the third.",
);
ui.label("You can mix in other widgets into text, like");
let _ = ui.small_button("this button");
ui.label(".");
ui.label("The default font supports all latin and cyrillic characters (ИÅđ…), common math symbols (∫√∞²⅓…), and many emojis (💓🌟🖩…).")
.on_hover_text("There is currently no support for right-to-left languages.");
ui.label("See the 🔤 Font Book for more!");
ui.monospace("There is also a monospace font.");
});
let tooltip_ui = |ui: &mut Ui| {
ui.heading("The name of the tooltip");
ui.horizontal(|ui| {
@@ -455,7 +471,7 @@ impl Tree {
.into_iter()
.enumerate()
.filter_map(|(i, mut tree)| {
if tree.ui_impl(ui, depth + 1, &format!("child #{}", i)) == Action::Keep {
if tree.ui_impl(ui, depth + 1, &format!("child #{i}")) == Action::Keep {
Some(tree)
} else {
None
@@ -473,12 +489,7 @@ impl Tree {
// ----------------------------------------------------------------------------
fn text_layout_ui(
ui: &mut egui::Ui,
max_rows: &mut usize,
break_anywhere: &mut bool,
overflow_character: &mut Option<char>,
) {
fn text_layout_demo(ui: &mut Ui) {
use egui::text::LayoutJob;
let mut job = LayoutJob::default();
@@ -632,32 +643,64 @@ fn text_layout_ui(
);
ui.label(job);
ui.separator();
ui.horizontal(|ui| {
ui.add(DragValue::new(max_rows));
ui.label("Max rows");
});
ui.checkbox(break_anywhere, "Break anywhere");
ui.horizontal(|ui| {
ui.selectable_value(overflow_character, None, "None");
ui.selectable_value(overflow_character, Some('…'), "");
ui.selectable_value(overflow_character, Some('—'), "");
ui.selectable_value(overflow_character, Some('-'), " - ");
ui.label("Overflow character");
});
let mut job = LayoutJob::single_section(LOREM_IPSUM.to_owned(), TextFormat::default());
job.wrap = TextWrapping {
max_rows: *max_rows,
break_anywhere: *break_anywhere,
overflow_character: *overflow_character,
..Default::default()
};
ui.label(job);
ui.vertical_centered(|ui| {
ui.add(crate::egui_github_link_file_line!());
});
}
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
struct TextBreakDemo {
break_anywhere: bool,
max_rows: usize,
overflow_character: Option<char>,
}
impl Default for TextBreakDemo {
fn default() -> Self {
Self {
max_rows: 1,
break_anywhere: true,
overflow_character: Some('…'),
}
}
}
impl TextBreakDemo {
pub fn ui(&mut self, ui: &mut Ui) {
let Self {
break_anywhere,
max_rows,
overflow_character,
} = self;
use egui::text::LayoutJob;
ui.horizontal(|ui| {
ui.add(DragValue::new(max_rows));
ui.label("Max rows");
});
ui.horizontal(|ui| {
ui.label("Line-break:");
ui.radio_value(break_anywhere, false, "word boundaries");
ui.radio_value(break_anywhere, true, "anywhere");
});
ui.horizontal(|ui| {
ui.selectable_value(overflow_character, None, "None");
ui.selectable_value(overflow_character, Some('…'), "");
ui.selectable_value(overflow_character, Some('—'), "");
ui.selectable_value(overflow_character, Some('-'), " - ");
ui.label("Overflow character");
});
let mut job =
LayoutJob::single_section(crate::LOREM_IPSUM_LONG.to_owned(), TextFormat::default());
job.wrap = TextWrapping {
max_rows: *max_rows,
break_anywhere: *break_anywhere,
overflow_character: *overflow_character,
..Default::default()
};
ui.label(job); // `Label` overrides some of the wrapping settings, e.g. wrap width
}
}

View File

@@ -50,7 +50,7 @@ impl super::View for MultiTouch {
ui.label("Try touch gestures Pinch/Stretch, Rotation, and Pressure with 2+ fingers.");
let num_touches = ui.input(|i| i.multi_touch().map_or(0, |mt| mt.num_touches));
ui.label(format!("Current touches: {}", num_touches));
ui.label(format!("Current touches: {num_touches}"));
let color = if ui.visuals().dark_mode {
Color32::WHITE

View File

@@ -39,8 +39,8 @@ pub struct PlotDemo {
charts_demo: ChartsDemo,
items_demo: ItemsDemo,
interaction_demo: InteractionDemo,
custom_axes_demo: CustomAxisDemo,
linked_axes_demo: LinkedAxisDemo,
custom_axes_demo: CustomAxesDemo,
linked_axes_demo: LinkedAxesDemo,
open_panel: Panel,
}
@@ -322,7 +322,7 @@ impl MarkerDemo {
[5.0, 0.0 + y_offset],
[6.0, 0.5 + y_offset],
])
.name(format!("{:?}", marker))
.name(format!("{marker:?}"))
.filled(self.fill_markers)
.radius(self.marker_radius)
.shape(marker);
@@ -412,7 +412,7 @@ impl LegendDemo {
ui.label("Position:");
ui.horizontal(|ui| {
Corner::all().for_each(|position| {
ui.selectable_value(&mut config.position, position, format!("{:?}", position));
ui.selectable_value(&mut config.position, position, format!("{position:?}"));
});
});
ui.end_row();
@@ -446,19 +446,19 @@ impl LegendDemo {
// ----------------------------------------------------------------------------
#[derive(PartialEq, Default)]
struct CustomAxisDemo {}
struct CustomAxesDemo {}
impl CustomAxisDemo {
impl CustomAxesDemo {
const MINS_PER_DAY: f64 = 24.0 * 60.0;
const MINS_PER_H: f64 = 60.0;
fn logistic_fn() -> Line {
fn days(min: f64) -> f64 {
CustomAxisDemo::MINS_PER_DAY * min
CustomAxesDemo::MINS_PER_DAY * min
}
let values = PlotPoints::from_explicit_callback(
move |x| 1.0 / (1.0 + (-2.5 * (x / CustomAxisDemo::MINS_PER_DAY - 2.0)).exp()),
move |x| 1.0 / (1.0 + (-2.5 * (x / CustomAxesDemo::MINS_PER_DAY - 2.0)).exp()),
days(0.0)..days(5.0),
100,
);
@@ -502,8 +502,8 @@ impl CustomAxisDemo {
#[allow(clippy::unused_self)]
fn ui(&mut self, ui: &mut Ui) -> Response {
const MINS_PER_DAY: f64 = CustomAxisDemo::MINS_PER_DAY;
const MINS_PER_H: f64 = CustomAxisDemo::MINS_PER_H;
const MINS_PER_DAY: f64 = CustomAxesDemo::MINS_PER_DAY;
const MINS_PER_H: f64 = CustomAxesDemo::MINS_PER_H;
fn day(x: f64) -> f64 {
(x / MINS_PER_DAY).floor()
@@ -572,10 +572,10 @@ impl CustomAxisDemo {
.data_aspect(2.0 * MINS_PER_DAY as f32)
.custom_x_axes(x_axes)
.custom_y_axes(y_axes)
.x_grid_spacer(CustomAxisDemo::x_grid)
.x_grid_spacer(CustomAxesDemo::x_grid)
.label_formatter(label_fmt)
.show(ui, |plot_ui| {
plot_ui.line(CustomAxisDemo::logistic_fn());
plot_ui.line(CustomAxesDemo::logistic_fn());
})
.response
}
@@ -584,14 +584,14 @@ impl CustomAxisDemo {
// ----------------------------------------------------------------------------
#[derive(PartialEq)]
struct LinkedAxisDemo {
struct LinkedAxesDemo {
link_x: bool,
link_y: bool,
link_cursor_x: bool,
link_cursor_y: bool,
}
impl Default for LinkedAxisDemo {
impl Default for LinkedAxesDemo {
fn default() -> Self {
let link_x = true;
let link_y = false;
@@ -606,7 +606,7 @@ impl Default for LinkedAxisDemo {
}
}
impl LinkedAxisDemo {
impl LinkedAxesDemo {
fn line_with_slope(slope: f64) -> Line {
Line::new(PlotPoints::from_explicit_callback(
move |x| slope * x,
@@ -632,11 +632,11 @@ impl LinkedAxisDemo {
}
fn configure_plot(plot_ui: &mut plot::PlotUi) {
plot_ui.line(LinkedAxisDemo::line_with_slope(0.5));
plot_ui.line(LinkedAxisDemo::line_with_slope(1.0));
plot_ui.line(LinkedAxisDemo::line_with_slope(2.0));
plot_ui.line(LinkedAxisDemo::sin());
plot_ui.line(LinkedAxisDemo::cos());
plot_ui.line(LinkedAxesDemo::line_with_slope(0.5));
plot_ui.line(LinkedAxesDemo::line_with_slope(1.0));
plot_ui.line(LinkedAxesDemo::line_with_slope(2.0));
plot_ui.line(LinkedAxesDemo::sin());
plot_ui.line(LinkedAxesDemo::cos());
}
fn ui(&mut self, ui: &mut Ui) -> Response {
@@ -659,7 +659,7 @@ impl LinkedAxisDemo {
.height(250.0)
.link_axis(link_group_id, self.link_x, self.link_y)
.link_cursor(link_group_id, self.link_cursor_x, self.link_cursor_y)
.show(ui, LinkedAxisDemo::configure_plot);
.show(ui, LinkedAxesDemo::configure_plot);
Plot::new("linked_axis_2")
.data_aspect(2.0)
.width(150.0)
@@ -669,7 +669,7 @@ impl LinkedAxisDemo {
.y_axis_width(3)
.link_axis(link_group_id, self.link_x, self.link_y)
.link_cursor(link_group_id, self.link_cursor_x, self.link_cursor_y)
.show(ui, LinkedAxisDemo::configure_plot);
.show(ui, LinkedAxesDemo::configure_plot);
});
Plot::new("linked_axis_3")
.data_aspect(0.5)
@@ -678,7 +678,7 @@ impl LinkedAxisDemo {
.x_axis_label("x")
.link_axis(link_group_id, self.link_x, self.link_y)
.link_cursor(link_group_id, self.link_cursor_x, self.link_cursor_y)
.show(ui, LinkedAxisDemo::configure_plot)
.show(ui, LinkedAxesDemo::configure_plot)
.response
}
}
@@ -776,7 +776,7 @@ impl InteractionDemo {
plot_ui.pointer_coordinate(),
plot_ui.pointer_coordinate_drag_delta(),
plot_ui.plot_bounds(),
plot_ui.plot_hovered(),
plot_ui.response().hovered(),
)
});
@@ -789,21 +789,18 @@ impl InteractionDemo {
"origin in screen coordinates: x: {:.02}, y: {:.02}",
screen_pos.x, screen_pos.y
));
ui.label(format!("plot hovered: {}", hovered));
ui.label(format!("plot hovered: {hovered}"));
let coordinate_text = if let Some(coordinate) = pointer_coordinate {
format!("x: {:.02}, y: {:.02}", coordinate.x, coordinate.y)
} else {
"None".to_owned()
};
ui.label(format!("pointer coordinate: {}", coordinate_text));
ui.label(format!("pointer coordinate: {coordinate_text}"));
let coordinate_text = format!(
"x: {:.02}, y: {:.02}",
pointer_coordinate_drag_delta.x, pointer_coordinate_drag_delta.y
);
ui.label(format!(
"pointer coordinate drag delta: {}",
coordinate_text
));
ui.label(format!("pointer coordinate drag delta: {coordinate_text}"));
response
}

View File

@@ -232,10 +232,10 @@ impl super::View for ScrollTo {
for item in 1..=50 {
if track_item && item == self.track_item {
let response =
ui.colored_label(Color32::YELLOW, format!("This is item {}", item));
ui.colored_label(Color32::YELLOW, format!("This is item {item}"));
response.scroll_to_me(self.tack_item_align);
} else {
ui.label(format!("This is item {}", item));
ui.label(format!("This is item {item}"));
}
}
});
@@ -254,8 +254,7 @@ impl super::View for ScrollTo {
ui.separator();
ui.label(format!(
"Scroll offset: {:.0}/{:.0} px",
current_scroll, max_scroll
"Scroll offset: {current_scroll:.0}/{max_scroll:.0} px"
));
ui.separator();

View File

@@ -37,7 +37,7 @@ impl super::View for StripDemo {
.size(Size::exact(50.0))
.size(Size::remainder())
.size(Size::relative(0.5).at_least(60.0))
.size(Size::exact(10.0))
.size(Size::exact(10.5))
.vertical(|mut strip| {
strip.cell(|ui| {
ui.painter().rect_filled(

View File

@@ -38,7 +38,6 @@ impl super::Demo for TableDemo {
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
egui::Window::new(self.name())
.open(open)
.resizable(true)
.default_width(400.0)
.show(ctx, |ui| {
use super::View as _;
@@ -102,7 +101,7 @@ impl super::View for TableDemo {
use egui_extras::{Size, StripBuilder};
StripBuilder::new(ui)
.size(Size::remainder().at_least(100.0)) // for the table
.size(Size::exact(10.0)) // for the source code link
.size(Size::exact(10.5)) // for the source code link
.vertical(|mut strip| {
strip.cell(|ui| {
egui::ScrollArea::horizontal().show(ui, |ui| {

View File

@@ -20,7 +20,7 @@ impl super::View for CursorTest {
ui.heading("Hover to switch cursor icon:");
for &cursor_icon in &egui::CursorIcon::ALL {
let _ = ui
.button(format!("{:?}", cursor_icon))
.button(format!("{cursor_icon:?}"))
.on_hover_cursor(cursor_icon);
}
ui.add(crate::egui_github_link_file!());
@@ -239,7 +239,7 @@ impl super::View for TableTest {
for row in 0..self.num_rows {
for col in 0..self.num_cols {
if col == 0 {
ui.label(format!("row {}", row));
ui.label(format!("row {row}"));
} else {
let word_idx = row * 3 + col * 5;
let word_count = (row * 5 + col * 75) % 13;
@@ -350,13 +350,13 @@ impl super::View for InputTest {
use std::fmt::Write as _;
if response.clicked_by(button) {
writeln!(new_info, "Clicked by {:?} button", button).ok();
writeln!(new_info, "Clicked by {button:?} button").ok();
}
if response.double_clicked_by(button) {
writeln!(new_info, "Double-clicked by {:?} button", button).ok();
writeln!(new_info, "Double-clicked by {button:?} button").ok();
}
if response.triple_clicked_by(button) {
writeln!(new_info, "Triple-clicked by {:?} button", button).ok();
writeln!(new_info, "Triple-clicked by {button:?} button").ok();
}
if response.dragged_by(button) {
writeln!(

View File

@@ -126,7 +126,7 @@ impl WidgetGallery {
ui.add(doc_link_label("Hyperlink", "Hyperlink"));
use egui::special_emojis::GITHUB;
ui.hyperlink_to(
format!("{} egui on GitHub", GITHUB),
format!("{GITHUB} egui on GitHub"),
"https://github.com/emilk/egui",
);
ui.end_row();
@@ -173,7 +173,7 @@ impl WidgetGallery {
ui.add(doc_link_label("ComboBox", "ComboBox"));
egui::ComboBox::from_label("Take your pick")
.selected_text(format!("{:?}", radio))
.selected_text(format!("{radio:?}"))
.show_ui(ui, |ui| {
ui.style_mut().wrap = Some(false);
ui.set_min_width(60.0);
@@ -278,8 +278,8 @@ fn example_plot(ui: &mut egui::Ui) -> egui::Response {
}
fn doc_link_label<'a>(title: &'a str, search_term: &'a str) -> impl egui::Widget + 'a {
let label = format!("{}:", title);
let url = format!("https://docs.rs/egui?search={}", search_term);
let label = format!("{title}:");
let url = format!("https://docs.rs/egui?search={search_term}");
move |ui: &mut egui::Ui| {
ui.hyperlink_to(label, url).on_hover_ui(|ui| {
ui.horizontal_wrapped(|ui| {

View File

@@ -161,7 +161,7 @@ fn numbered_point(ui: &mut Ui, width: f32, number: &str) -> Response {
let font_id = TextStyle::Body.resolve(ui.style());
let row_height = ui.fonts(|f| f.row_height(&font_id));
let (rect, response) = ui.allocate_exact_size(vec2(width, row_height), Sense::hover());
let text = format!("{}.", number);
let text = format!("{number}.");
let text_color = ui.visuals().strong_text_color();
ui.painter().text(
rect.right_center(),