From fb4c6cc619dada3e490dcb8b598c2d31b159a418 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 23 Jun 2024 10:53:04 +0200 Subject: [PATCH] Put all `egui_demo_lib` tests into their own files in their own folder (#4691) --- crates/egui_demo_lib/src/demo/about.rs | 6 +- crates/egui_demo_lib/src/demo/code_editor.rs | 6 +- crates/egui_demo_lib/src/demo/code_example.rs | 6 +- crates/egui_demo_lib/src/demo/context_menu.rs | 6 +- .../egui_demo_lib/src/demo/dancing_strings.rs | 6 +- .../src/demo/demo_app_windows.rs | 10 +- .../egui_demo_lib/src/demo/drag_and_drop.rs | 6 +- .../egui_demo_lib/src/demo/extra_viewport.rs | 2 +- crates/egui_demo_lib/src/demo/font_book.rs | 6 +- crates/egui_demo_lib/src/demo/frame_demo.rs | 6 +- crates/egui_demo_lib/src/demo/highlighting.rs | 8 +- crates/egui_demo_lib/src/demo/mod.rs | 1 - crates/egui_demo_lib/src/demo/multi_touch.rs | 6 +- crates/egui_demo_lib/src/demo/paint_bezier.rs | 6 +- crates/egui_demo_lib/src/demo/painting.rs | 6 +- crates/egui_demo_lib/src/demo/pan_zoom.rs | 6 +- crates/egui_demo_lib/src/demo/panels.rs | 6 +- crates/egui_demo_lib/src/demo/plot_demo.rs | 6 +- crates/egui_demo_lib/src/demo/scrolling.rs | 10 +- crates/egui_demo_lib/src/demo/sliders.rs | 6 +- crates/egui_demo_lib/src/demo/strip_demo.rs | 6 +- crates/egui_demo_lib/src/demo/table_demo.rs | 6 +- crates/egui_demo_lib/src/demo/tests.rs | 603 ------------------ .../src/demo/tests/cursor_test.rs | 29 + .../egui_demo_lib/src/demo/tests/id_test.rs | 54 ++ .../src/demo/tests/input_test.rs | 186 ++++++ .../src/demo/{ => tests}/layout_test.rs | 6 +- .../src/demo/tests/manual_layout_test.rs | 89 +++ crates/egui_demo_lib/src/demo/tests/mod.rs | 15 + .../src/demo/tests/table_test.rs | 124 ++++ .../src/demo/tests/window_resize_test.rs | 106 +++ crates/egui_demo_lib/src/demo/text_edit.rs | 6 +- crates/egui_demo_lib/src/demo/text_layout.rs | 6 +- crates/egui_demo_lib/src/demo/tooltips.rs | 8 +- .../egui_demo_lib/src/demo/widget_gallery.rs | 6 +- .../egui_demo_lib/src/demo/window_options.rs | 6 +- crates/egui_demo_lib/src/lib.rs | 2 +- 37 files changed, 689 insertions(+), 690 deletions(-) delete mode 100644 crates/egui_demo_lib/src/demo/tests.rs create mode 100644 crates/egui_demo_lib/src/demo/tests/cursor_test.rs create mode 100644 crates/egui_demo_lib/src/demo/tests/id_test.rs create mode 100644 crates/egui_demo_lib/src/demo/tests/input_test.rs rename crates/egui_demo_lib/src/demo/{ => tests}/layout_test.rs (98%) create mode 100644 crates/egui_demo_lib/src/demo/tests/manual_layout_test.rs create mode 100644 crates/egui_demo_lib/src/demo/tests/mod.rs create mode 100644 crates/egui_demo_lib/src/demo/tests/table_test.rs create mode 100644 crates/egui_demo_lib/src/demo/tests/window_resize_test.rs diff --git a/crates/egui_demo_lib/src/demo/about.rs b/crates/egui_demo_lib/src/demo/about.rs index f3143e3c7..4a3bfd456 100644 --- a/crates/egui_demo_lib/src/demo/about.rs +++ b/crates/egui_demo_lib/src/demo/about.rs @@ -3,7 +3,7 @@ #[cfg_attr(feature = "serde", serde(default))] pub struct About {} -impl super::Demo for About { +impl crate::Demo for About { fn name(&self) -> &'static str { "About egui" } @@ -15,13 +15,13 @@ impl super::Demo for About { .open(open) .resizable([true, false]) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for About { +impl crate::View for About { fn ui(&mut self, ui: &mut egui::Ui) { use egui::special_emojis::{OS_APPLE, OS_LINUX, OS_WINDOWS}; diff --git a/crates/egui_demo_lib/src/demo/code_editor.rs b/crates/egui_demo_lib/src/demo/code_editor.rs index 2a8f6a6c9..4dad60d3c 100644 --- a/crates/egui_demo_lib/src/demo/code_editor.rs +++ b/crates/egui_demo_lib/src/demo/code_editor.rs @@ -21,13 +21,13 @@ fn main() {\n\ } } -impl super::Demo for CodeEditor { +impl crate::Demo for CodeEditor { fn name(&self) -> &'static str { "๐Ÿ–ฎ Code Editor" } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - use super::View as _; + use crate::View as _; egui::Window::new(self.name()) .open(open) .default_height(500.0) @@ -35,7 +35,7 @@ impl super::Demo for CodeEditor { } } -impl super::View for CodeEditor { +impl crate::View for CodeEditor { fn ui(&mut self, ui: &mut egui::Ui) { let Self { language, code } = self; diff --git a/crates/egui_demo_lib/src/demo/code_example.rs b/crates/egui_demo_lib/src/demo/code_example.rs index 2b09b557b..2859b3ea7 100644 --- a/crates/egui_demo_lib/src/demo/code_example.rs +++ b/crates/egui_demo_lib/src/demo/code_example.rs @@ -104,13 +104,13 @@ impl CodeExample { } } -impl super::Demo for CodeExample { +impl crate::Demo for CodeExample { fn name(&self) -> &'static str { "๐Ÿ–ฎ Code Example" } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - use super::View; + use crate::View; egui::Window::new(self.name()) .open(open) .min_width(375.0) @@ -121,7 +121,7 @@ impl super::Demo for CodeExample { } } -impl super::View for CodeExample { +impl crate::View for CodeExample { fn ui(&mut self, ui: &mut egui::Ui) { ui.scope(|ui| { ui.spacing_mut().item_spacing = egui::vec2(8.0, 8.0); diff --git a/crates/egui_demo_lib/src/demo/context_menu.rs b/crates/egui_demo_lib/src/demo/context_menu.rs index 86bd2f9d1..3bba79bb8 100644 --- a/crates/egui_demo_lib/src/demo/context_menu.rs +++ b/crates/egui_demo_lib/src/demo/context_menu.rs @@ -47,13 +47,13 @@ impl Default for ContextMenus { } } -impl super::Demo for ContextMenus { +impl crate::Demo for ContextMenus { fn name(&self) -> &'static str { "โ˜ฐ Context Menus" } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - use super::View; + use crate::View; egui::Window::new(self.name()) .vscroll(false) .resizable(false) @@ -62,7 +62,7 @@ impl super::Demo for ContextMenus { } } -impl super::View for ContextMenus { +impl crate::View for ContextMenus { fn ui(&mut self, ui: &mut egui::Ui) { ui.horizontal(|ui| { ui.menu_button("Click for menu", Self::nested_menus); diff --git a/crates/egui_demo_lib/src/demo/dancing_strings.rs b/crates/egui_demo_lib/src/demo/dancing_strings.rs index a2b560ee7..2ba542121 100644 --- a/crates/egui_demo_lib/src/demo/dancing_strings.rs +++ b/crates/egui_demo_lib/src/demo/dancing_strings.rs @@ -7,13 +7,13 @@ pub struct DancingStrings { colors: bool, } -impl super::Demo for DancingStrings { +impl crate::Demo for DancingStrings { fn name(&self) -> &'static str { "โ™ซ Dancing Strings" } fn show(&mut self, ctx: &Context, open: &mut bool) { - use super::View as _; + use crate::View as _; Window::new(self.name()) .open(open) .default_size(vec2(512.0, 256.0)) @@ -22,7 +22,7 @@ impl super::Demo for DancingStrings { } } -impl super::View for DancingStrings { +impl crate::View for DancingStrings { fn ui(&mut self, ui: &mut Ui) { let color = if ui.visuals().dark_mode { Color32::from_additive_luminance(196) diff --git a/crates/egui_demo_lib/src/demo/demo_app_windows.rs b/crates/egui_demo_lib/src/demo/demo_app_windows.rs index 74c5edefb..5e344c2ee 100644 --- a/crates/egui_demo_lib/src/demo/demo_app_windows.rs +++ b/crates/egui_demo_lib/src/demo/demo_app_windows.rs @@ -3,9 +3,9 @@ use std::collections::BTreeSet; use egui::{Context, Modifiers, NumExt as _, ScrollArea, Ui}; use super::About; -use super::Demo; -use super::View; use crate::is_mobile; +use crate::Demo; +use crate::View; // ---------------------------------------------------------------------------- @@ -30,6 +30,7 @@ impl Default for Demos { Box::::default(), Box::::default(), Box::::default(), + Box::::default(), Box::::default(), Box::::default(), Box::::default(), @@ -45,7 +46,6 @@ impl Default for Demos { Box::::default(), Box::::default(), Box::::default(), - Box::::default(), ]) } } @@ -107,12 +107,12 @@ impl Default for Tests { fn default() -> Self { Self::from_demos(vec![ Box::::default(), - Box::::default(), Box::::default(), Box::::default(), - Box::::default(), + Box::::default(), Box::::default(), Box::::default(), + Box::::default(), ]) } } diff --git a/crates/egui_demo_lib/src/demo/drag_and_drop.rs b/crates/egui_demo_lib/src/demo/drag_and_drop.rs index 883095953..10fd9c859 100644 --- a/crates/egui_demo_lib/src/demo/drag_and_drop.rs +++ b/crates/egui_demo_lib/src/demo/drag_and_drop.rs @@ -22,13 +22,13 @@ impl Default for DragAndDropDemo { } } -impl super::Demo for DragAndDropDemo { +impl crate::Demo for DragAndDropDemo { fn name(&self) -> &'static str { "โœ‹ Drag and Drop" } fn show(&mut self, ctx: &Context, open: &mut bool) { - use super::View as _; + use crate::View as _; Window::new(self.name()) .open(open) .default_size(vec2(256.0, 256.0)) @@ -45,7 +45,7 @@ struct Location { row: usize, } -impl super::View for DragAndDropDemo { +impl crate::View for DragAndDropDemo { fn ui(&mut self, ui: &mut Ui) { ui.label("This is a simple example of drag-and-drop in egui."); ui.label("Drag items between columns."); diff --git a/crates/egui_demo_lib/src/demo/extra_viewport.rs b/crates/egui_demo_lib/src/demo/extra_viewport.rs index 5e1855ca5..1ab7787f9 100644 --- a/crates/egui_demo_lib/src/demo/extra_viewport.rs +++ b/crates/egui_demo_lib/src/demo/extra_viewport.rs @@ -1,7 +1,7 @@ #[derive(Default)] pub struct ExtraViewport {} -impl super::Demo for ExtraViewport { +impl crate::Demo for ExtraViewport { fn is_enabled(&self, ctx: &egui::Context) -> bool { !ctx.embed_viewports() } diff --git a/crates/egui_demo_lib/src/demo/font_book.rs b/crates/egui_demo_lib/src/demo/font_book.rs index 4dda2d87b..a5e8eb138 100644 --- a/crates/egui_demo_lib/src/demo/font_book.rs +++ b/crates/egui_demo_lib/src/demo/font_book.rs @@ -16,20 +16,20 @@ impl Default for FontBook { } } -impl super::Demo for FontBook { +impl crate::Demo for FontBook { fn name(&self) -> &'static str { "๐Ÿ”ค Font Book" } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { egui::Window::new(self.name()).open(open).show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for FontBook { +impl crate::View for FontBook { fn ui(&mut self, ui: &mut egui::Ui) { ui.vertical_centered(|ui| { ui.add(crate::egui_github_link_file!()); diff --git a/crates/egui_demo_lib/src/demo/frame_demo.rs b/crates/egui_demo_lib/src/demo/frame_demo.rs index bd1661827..e982d9799 100644 --- a/crates/egui_demo_lib/src/demo/frame_demo.rs +++ b/crates/egui_demo_lib/src/demo/frame_demo.rs @@ -24,7 +24,7 @@ impl Default for FrameDemo { } } -impl super::Demo for FrameDemo { +impl crate::Demo for FrameDemo { fn name(&self) -> &'static str { "โ–ฃ Frame" } @@ -34,13 +34,13 @@ impl super::Demo for FrameDemo { .open(open) .resizable(false) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for FrameDemo { +impl crate::View for FrameDemo { fn ui(&mut self, ui: &mut egui::Ui) { ui.horizontal(|ui| { ui.vertical(|ui| { diff --git a/crates/egui_demo_lib/src/demo/highlighting.rs b/crates/egui_demo_lib/src/demo/highlighting.rs index e163974e4..287111d2f 100644 --- a/crates/egui_demo_lib/src/demo/highlighting.rs +++ b/crates/egui_demo_lib/src/demo/highlighting.rs @@ -3,9 +3,9 @@ #[cfg_attr(feature = "serde", serde(default))] pub struct Highlighting {} -impl super::Demo for Highlighting { +impl crate::Demo for Highlighting { fn name(&self) -> &'static str { - "Highlighting" + "โœจ Highlighting" } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { @@ -13,13 +13,13 @@ impl super::Demo for Highlighting { .default_width(320.0) .open(open) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for Highlighting { +impl crate::View for Highlighting { fn ui(&mut self, ui: &mut egui::Ui) { ui.vertical_centered(|ui| { ui.add(crate::egui_github_link_file!()); diff --git a/crates/egui_demo_lib/src/demo/mod.rs b/crates/egui_demo_lib/src/demo/mod.rs index 724134f86..921a145f5 100644 --- a/crates/egui_demo_lib/src/demo/mod.rs +++ b/crates/egui_demo_lib/src/demo/mod.rs @@ -15,7 +15,6 @@ pub mod extra_viewport; pub mod font_book; pub mod frame_demo; pub mod highlighting; -pub mod layout_test; pub mod misc_demo_window; pub mod multi_touch; pub mod paint_bezier; diff --git a/crates/egui_demo_lib/src/demo/multi_touch.rs b/crates/egui_demo_lib/src/demo/multi_touch.rs index 1a3b29e8e..b6580c5f8 100644 --- a/crates/egui_demo_lib/src/demo/multi_touch.rs +++ b/crates/egui_demo_lib/src/demo/multi_touch.rs @@ -21,7 +21,7 @@ impl Default for MultiTouch { } } -impl super::Demo for MultiTouch { +impl crate::Demo for MultiTouch { fn name(&self) -> &'static str { "๐Ÿ‘Œ Multi Touch" } @@ -32,13 +32,13 @@ impl super::Demo for MultiTouch { .default_size(vec2(512.0, 512.0)) .resizable(true) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for MultiTouch { +impl crate::View for MultiTouch { fn ui(&mut self, ui: &mut egui::Ui) { ui.vertical_centered(|ui| { ui.add(crate::egui_github_link_file!()); diff --git a/crates/egui_demo_lib/src/demo/paint_bezier.rs b/crates/egui_demo_lib/src/demo/paint_bezier.rs index 99d477b44..7fce1356a 100644 --- a/crates/egui_demo_lib/src/demo/paint_bezier.rs +++ b/crates/egui_demo_lib/src/demo/paint_bezier.rs @@ -155,13 +155,13 @@ impl PaintBezier { } } -impl super::Demo for PaintBezier { +impl crate::Demo for PaintBezier { fn name(&self) -> &'static str { "๏ผ‰ Bรฉzier Curve" } fn show(&mut self, ctx: &Context, open: &mut bool) { - use super::View as _; + use crate::View as _; Window::new(self.name()) .open(open) .vscroll(false) @@ -171,7 +171,7 @@ impl super::Demo for PaintBezier { } } -impl super::View for PaintBezier { +impl crate::View for PaintBezier { fn ui(&mut self, ui: &mut Ui) { ui.vertical_centered(|ui| { ui.add(crate::egui_github_link_file!()); diff --git a/crates/egui_demo_lib/src/demo/painting.rs b/crates/egui_demo_lib/src/demo/painting.rs index d95e85346..85650f0ed 100644 --- a/crates/egui_demo_lib/src/demo/painting.rs +++ b/crates/egui_demo_lib/src/demo/painting.rs @@ -72,13 +72,13 @@ impl Painting { } } -impl super::Demo for Painting { +impl crate::Demo for Painting { fn name(&self) -> &'static str { "๐Ÿ–Š Painting" } fn show(&mut self, ctx: &Context, open: &mut bool) { - use super::View as _; + use crate::View as _; Window::new(self.name()) .open(open) .default_size(vec2(512.0, 512.0)) @@ -87,7 +87,7 @@ impl super::Demo for Painting { } } -impl super::View for Painting { +impl crate::View for Painting { fn ui(&mut self, ui: &mut Ui) { ui.vertical_centered(|ui| { ui.add(crate::egui_github_link_file!()); diff --git a/crates/egui_demo_lib/src/demo/pan_zoom.rs b/crates/egui_demo_lib/src/demo/pan_zoom.rs index 6ee75e303..b6e8096b0 100644 --- a/crates/egui_demo_lib/src/demo/pan_zoom.rs +++ b/crates/egui_demo_lib/src/demo/pan_zoom.rs @@ -10,13 +10,13 @@ pub struct PanZoom { impl Eq for PanZoom {} -impl super::Demo for PanZoom { +impl crate::Demo for PanZoom { fn name(&self) -> &'static str { "๐Ÿ” Pan Zoom" } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - use super::View as _; + use crate::View as _; let window = egui::Window::new("Pan Zoom") .default_width(300.0) .default_height(300.0) @@ -26,7 +26,7 @@ impl super::Demo for PanZoom { } } -impl super::View for PanZoom { +impl crate::View for PanZoom { fn ui(&mut self, ui: &mut egui::Ui) { ui.label( "Pan, zoom in, and zoom out with scrolling (see the plot demo for more instructions). \ diff --git a/crates/egui_demo_lib/src/demo/panels.rs b/crates/egui_demo_lib/src/demo/panels.rs index 6c86f9820..f94513866 100644 --- a/crates/egui_demo_lib/src/demo/panels.rs +++ b/crates/egui_demo_lib/src/demo/panels.rs @@ -2,13 +2,13 @@ #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Panels {} -impl super::Demo for Panels { +impl crate::Demo for Panels { fn name(&self) -> &'static str { "๐Ÿ—– Panels" } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - use super::View as _; + use crate::View as _; let window = egui::Window::new("Panels") .default_width(600.0) .default_height(400.0) @@ -18,7 +18,7 @@ impl super::Demo for Panels { } } -impl super::View for Panels { +impl crate::View for Panels { fn ui(&mut self, ui: &mut egui::Ui) { // Note that the order we add the panels is very important! diff --git a/crates/egui_demo_lib/src/demo/plot_demo.rs b/crates/egui_demo_lib/src/demo/plot_demo.rs index 17eceba18..0b6ff45ba 100644 --- a/crates/egui_demo_lib/src/demo/plot_demo.rs +++ b/crates/egui_demo_lib/src/demo/plot_demo.rs @@ -44,13 +44,13 @@ pub struct PlotDemo { open_panel: Panel, } -impl super::Demo for PlotDemo { +impl crate::Demo for PlotDemo { fn name(&self) -> &'static str { "๐Ÿ—  Plot" } fn show(&mut self, ctx: &Context, open: &mut bool) { - use super::View as _; + use crate::View as _; Window::new(self.name()) .open(open) .default_size(vec2(400.0, 400.0)) @@ -59,7 +59,7 @@ impl super::Demo for PlotDemo { } } -impl super::View for PlotDemo { +impl crate::View for PlotDemo { fn ui(&mut self, ui: &mut Ui) { ui.horizontal(|ui| { egui::reset_button(ui, self, "Reset"); diff --git a/crates/egui_demo_lib/src/demo/scrolling.rs b/crates/egui_demo_lib/src/demo/scrolling.rs index ec6ca5e1a..7989ca853 100644 --- a/crates/egui_demo_lib/src/demo/scrolling.rs +++ b/crates/egui_demo_lib/src/demo/scrolling.rs @@ -27,7 +27,7 @@ pub struct Scrolling { scroll_stick_to: ScrollStickTo, } -impl super::Demo for Scrolling { +impl crate::Demo for Scrolling { fn name(&self) -> &'static str { "โ†• Scrolling" } @@ -39,13 +39,13 @@ impl super::Demo for Scrolling { .hscroll(false) .vscroll(false) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for Scrolling { +impl crate::View for Scrolling { fn ui(&mut self, ui: &mut Ui) { ui.horizontal(|ui| { ui.selectable_value(&mut self.demo, ScrollDemo::ScrollAppearance, "Appearance"); @@ -250,7 +250,7 @@ impl Default for ScrollTo { } } -impl super::View for ScrollTo { +impl crate::View for ScrollTo { fn ui(&mut self, ui: &mut Ui) { ui.label("This shows how you can scroll to a specific item or pixel offset"); @@ -370,7 +370,7 @@ struct ScrollStickTo { n_items: usize, } -impl super::View for ScrollStickTo { +impl crate::View for ScrollStickTo { fn ui(&mut self, ui: &mut Ui) { ui.label("Rows enter from the bottom, we want the scroll handle to start and stay at bottom unless moved"); diff --git a/crates/egui_demo_lib/src/demo/sliders.rs b/crates/egui_demo_lib/src/demo/sliders.rs index 4142c7af0..2f3cf7fae 100644 --- a/crates/egui_demo_lib/src/demo/sliders.rs +++ b/crates/egui_demo_lib/src/demo/sliders.rs @@ -39,7 +39,7 @@ impl Default for Sliders { } } -impl super::Demo for Sliders { +impl crate::Demo for Sliders { fn name(&self) -> &'static str { "โฌŒ Sliders" } @@ -49,13 +49,13 @@ impl super::Demo for Sliders { .open(open) .resizable(false) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for Sliders { +impl crate::View for Sliders { fn ui(&mut self, ui: &mut Ui) { let Self { min, diff --git a/crates/egui_demo_lib/src/demo/strip_demo.rs b/crates/egui_demo_lib/src/demo/strip_demo.rs index 091d4f01d..c9231f1bc 100644 --- a/crates/egui_demo_lib/src/demo/strip_demo.rs +++ b/crates/egui_demo_lib/src/demo/strip_demo.rs @@ -6,7 +6,7 @@ use egui_extras::{Size, StripBuilder}; #[derive(Default)] pub struct StripDemo {} -impl super::Demo for StripDemo { +impl crate::Demo for StripDemo { fn name(&self) -> &'static str { "โ–ฃ Strip" } @@ -17,13 +17,13 @@ impl super::Demo for StripDemo { .resizable(true) .default_width(400.0) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for StripDemo { +impl crate::View for StripDemo { fn ui(&mut self, ui: &mut egui::Ui) { let dark_mode = ui.visuals().dark_mode; let faded_color = ui.visuals().window_fill(); diff --git a/crates/egui_demo_lib/src/demo/table_demo.rs b/crates/egui_demo_lib/src/demo/table_demo.rs index ec6fa58c3..f059803ed 100644 --- a/crates/egui_demo_lib/src/demo/table_demo.rs +++ b/crates/egui_demo_lib/src/demo/table_demo.rs @@ -38,7 +38,7 @@ impl Default for TableDemo { } } -impl super::Demo for TableDemo { +impl crate::Demo for TableDemo { fn name(&self) -> &'static str { "โ˜ฐ Table" } @@ -48,7 +48,7 @@ impl super::Demo for TableDemo { .open(open) .default_width(400.0) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } @@ -56,7 +56,7 @@ impl super::Demo for TableDemo { const NUM_MANUAL_ROWS: usize = 20; -impl super::View for TableDemo { +impl crate::View for TableDemo { fn ui(&mut self, ui: &mut egui::Ui) { ui.vertical(|ui| { ui.horizontal(|ui| { diff --git a/crates/egui_demo_lib/src/demo/tests.rs b/crates/egui_demo_lib/src/demo/tests.rs deleted file mode 100644 index 44e355d0e..000000000 --- a/crates/egui_demo_lib/src/demo/tests.rs +++ /dev/null @@ -1,603 +0,0 @@ -#[derive(Default)] -pub struct CursorTest {} - -impl super::Demo for CursorTest { - fn name(&self) -> &'static str { - "Cursor Test" - } - - fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - egui::Window::new(self.name()).open(open).show(ctx, |ui| { - use super::View as _; - self.ui(ui); - }); - } -} - -impl super::View for CursorTest { - fn ui(&mut self, ui: &mut egui::Ui) { - ui.vertical_centered_justified(|ui| { - ui.heading("Hover to switch cursor icon:"); - for &cursor_icon in &egui::CursorIcon::ALL { - let _ = ui - .button(format!("{cursor_icon:?}")) - .on_hover_cursor(cursor_icon); - } - ui.add(crate::egui_github_link_file!()); - }); - } -} - -// ---------------------------------------------------------------------------- - -#[derive(Default)] -pub struct IdTest {} - -impl super::Demo for IdTest { - fn name(&self) -> &'static str { - "ID Test" - } - - fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - egui::Window::new(self.name()).open(open).show(ctx, |ui| { - use super::View as _; - self.ui(ui); - }); - } -} - -impl super::View for IdTest { - fn ui(&mut self, ui: &mut egui::Ui) { - // Make sure the warnings are on (by default they are only on in debug builds). - ui.ctx().options_mut(|opt| opt.warn_on_id_clash = true); - - ui.heading("Name collision example"); - - ui.label("\ - Widgets that store state require unique and persisting identifiers so we can track their state between frames.\n\ - For instance, collapsible headers needs to store whether or not they are open. \ - Their Id:s are derived from their names. \ - If you fail to give them unique names then clicking one will open both. \ - To help you debug this, an error message is printed on screen:"); - - ui.collapsing("Collapsing header", |ui| { - ui.label("Contents of first foldable ui"); - }); - ui.collapsing("Collapsing header", |ui| { - ui.label("Contents of second foldable ui"); - }); - - ui.label("\ - Any widget that can be interacted with also need a unique Id. \ - For most widgets the Id is generated by a running counter. \ - As long as elements are not added or removed, the Id stays the same. \ - This is fine, because during interaction (i.e. while dragging a slider), \ - the number of widgets previously in the same window is most likely not changing \ - (and if it is, the window will have a new layout, and the slider will end up somewhere else, and so aborting the interaction probably makes sense)."); - - ui.label("So these buttons have automatic Id:s, and therefore there is no name clash:"); - let _ = ui.button("Button"); - let _ = ui.button("Button"); - - ui.vertical_centered(|ui| { - ui.add(crate::egui_github_link_file!()); - }); - } -} - -// ---------------------------------------------------------------------------- - -#[derive(Clone, Copy, Debug, PartialEq)] -enum WidgetType { - Label, - Button, - TextEdit, -} - -#[derive(Clone, Debug, PartialEq)] -pub struct ManualLayoutTest { - widget_offset: egui::Vec2, - widget_size: egui::Vec2, - widget_type: WidgetType, - text_edit_contents: String, -} - -impl Default for ManualLayoutTest { - fn default() -> Self { - Self { - widget_offset: egui::Vec2::splat(150.0), - widget_size: egui::vec2(200.0, 100.0), - widget_type: WidgetType::Button, - text_edit_contents: crate::LOREM_IPSUM.to_owned(), - } - } -} - -impl super::Demo for ManualLayoutTest { - fn name(&self) -> &'static str { - "Manual Layout Test" - } - - fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - egui::Window::new(self.name()) - .resizable(false) - .open(open) - .show(ctx, |ui| { - use super::View as _; - self.ui(ui); - }); - } -} - -impl super::View for ManualLayoutTest { - fn ui(&mut self, ui: &mut egui::Ui) { - egui::reset_button(ui, self, "Reset"); - - let Self { - widget_offset, - widget_size, - widget_type, - text_edit_contents, - } = self; - ui.horizontal(|ui| { - ui.label("Test widget:"); - ui.radio_value(widget_type, WidgetType::Button, "Button"); - ui.radio_value(widget_type, WidgetType::Label, "Label"); - ui.radio_value(widget_type, WidgetType::TextEdit, "TextEdit"); - }); - egui::Grid::new("pos_size").show(ui, |ui| { - ui.label("Widget position:"); - ui.add(egui::Slider::new(&mut widget_offset.x, 0.0..=400.0)); - ui.add(egui::Slider::new(&mut widget_offset.y, 0.0..=400.0)); - ui.end_row(); - - ui.label("Widget size:"); - ui.add(egui::Slider::new(&mut widget_size.x, 0.0..=400.0)); - ui.add(egui::Slider::new(&mut widget_size.y, 0.0..=400.0)); - ui.end_row(); - }); - - let widget_rect = - egui::Rect::from_min_size(ui.min_rect().min + *widget_offset, *widget_size); - - ui.add(crate::egui_github_link_file!()); - - // Showing how to place a widget anywhere in the [`Ui`]: - match *widget_type { - WidgetType::Button => { - ui.put(widget_rect, egui::Button::new("Example button")); - } - WidgetType::Label => { - ui.put(widget_rect, egui::Label::new("Example label")); - } - WidgetType::TextEdit => { - ui.put(widget_rect, egui::TextEdit::multiline(text_edit_contents)); - } - } - } -} - -// ---------------------------------------------------------------------------- - -#[derive(PartialEq)] -pub struct TableTest { - num_cols: usize, - num_rows: usize, - min_col_width: f32, - max_col_width: f32, - text_length: usize, -} - -impl Default for TableTest { - fn default() -> Self { - Self { - num_cols: 4, - num_rows: 4, - min_col_width: 10.0, - max_col_width: 200.0, - text_length: 10, - } - } -} - -impl super::Demo for TableTest { - fn name(&self) -> &'static str { - "Table Test" - } - - fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - egui::Window::new(self.name()).open(open).show(ctx, |ui| { - use super::View as _; - self.ui(ui); - }); - } -} - -impl super::View for TableTest { - fn ui(&mut self, ui: &mut egui::Ui) { - ui.add( - egui::Slider::new(&mut self.min_col_width, 0.0..=400.0).text("Minimum column width"), - ); - ui.add( - egui::Slider::new(&mut self.max_col_width, 0.0..=400.0).text("Maximum column width"), - ); - ui.add(egui::Slider::new(&mut self.num_cols, 0..=5).text("Columns")); - ui.add(egui::Slider::new(&mut self.num_rows, 0..=20).text("Rows")); - - ui.separator(); - - let words = [ - "random", "words", "in", "a", "random", "order", "that", "just", "keeps", "going", - "with", "some", "more", - ]; - - egui::Grid::new("my_grid") - .striped(true) - .min_col_width(self.min_col_width) - .max_col_width(self.max_col_width) - .show(ui, |ui| { - for row in 0..self.num_rows { - for col in 0..self.num_cols { - if col == 0 { - ui.label(format!("row {row}")); - } else { - let word_idx = row * 3 + col * 5; - let word_count = (row * 5 + col * 75) % 13; - let mut string = String::new(); - for word in words.iter().cycle().skip(word_idx).take(word_count) { - string += word; - string += " "; - } - ui.label(string); - } - } - ui.end_row(); - } - }); - - ui.separator(); - ui.add(egui::Slider::new(&mut self.text_length, 1..=40).text("Text length")); - egui::Grid::new("parent grid").striped(true).show(ui, |ui| { - ui.vertical(|ui| { - ui.label("Vertical nest1"); - ui.label("Vertical nest2"); - }); - ui.label("First row, second column"); - ui.end_row(); - - ui.horizontal(|ui| { - ui.label("Horizontal nest1"); - ui.label("Horizontal nest2"); - }); - ui.label("Second row, second column"); - ui.end_row(); - - ui.scope(|ui| { - ui.label("Scope nest 1"); - ui.label("Scope nest 2"); - }); - ui.label("Third row, second column"); - ui.end_row(); - - egui::Grid::new("nested grid").show(ui, |ui| { - ui.label("Grid nest11"); - ui.label("Grid nest12"); - ui.end_row(); - ui.label("Grid nest21"); - ui.label("Grid nest22"); - ui.end_row(); - }); - ui.label("Fourth row, second column"); - ui.end_row(); - - let mut dyn_text = String::from("O"); - dyn_text.extend(std::iter::repeat('h').take(self.text_length)); - ui.label(dyn_text); - ui.label("Fifth row, second column"); - ui.end_row(); - }); - - ui.vertical_centered(|ui| { - egui::reset_button(ui, self, "Reset"); - ui.add(crate::egui_github_link_file!()); - }); - } -} - -// ---------------------------------------------------------------------------- - -struct HistoryEntry { - text: String, - repeated: usize, -} - -#[derive(Default)] -struct DeduplicatedHistory { - history: std::collections::VecDeque, -} - -impl DeduplicatedHistory { - fn add(&mut self, text: String) { - if let Some(entry) = self.history.back_mut() { - if entry.text == text { - entry.repeated += 1; - return; - } - } - self.history.push_back(HistoryEntry { text, repeated: 1 }); - if self.history.len() > 100 { - self.history.pop_front(); - } - } - - fn ui(&self, ui: &mut egui::Ui) { - egui::ScrollArea::vertical() - .auto_shrink(false) - .show(ui, |ui| { - ui.spacing_mut().item_spacing.y = 4.0; - for HistoryEntry { text, repeated } in self.history.iter().rev() { - ui.horizontal(|ui| { - if text.is_empty() { - ui.weak("(empty)"); - } else { - ui.label(text); - } - if 1 < *repeated { - ui.weak(format!(" x{repeated}")); - } - }); - } - }); - } -} - -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[derive(Default)] -pub struct InputTest { - #[cfg_attr(feature = "serde", serde(skip))] - history: [DeduplicatedHistory; 4], - - late_interaction: bool, - - show_hovers: bool, -} - -impl super::Demo for InputTest { - fn name(&self) -> &'static str { - "Input Test" - } - - fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - egui::Window::new(self.name()) - .default_width(800.0) - .open(open) - .resizable(true) - .scroll(false) - .show(ctx, |ui| { - use super::View as _; - self.ui(ui); - }); - } -} - -impl super::View for InputTest { - fn ui(&mut self, ui: &mut egui::Ui) { - ui.spacing_mut().item_spacing.y = 8.0; - - ui.vertical_centered(|ui| { - ui.add(crate::egui_github_link_file!()); - }); - - ui.horizontal(|ui| { - if ui.button("Clear").clicked() { - *self = Default::default(); - } - - ui.checkbox(&mut self.show_hovers, "Show hover state"); - }); - - ui.checkbox(&mut self.late_interaction, "Use Response::interact"); - - ui.label("This tests how egui::Response reports events.\n\ - The different buttons are sensitive to different things.\n\ - Try interacting with them with any mouse button by clicking, double-clicking, triple-clicking, or dragging them."); - - ui.columns(4, |columns| { - for (i, (sense_name, sense)) in [ - ("Sense::hover", egui::Sense::hover()), - ("Sense::click", egui::Sense::click()), - ("Sense::drag", egui::Sense::drag()), - ("Sense::click_and_drag", egui::Sense::click_and_drag()), - ] - .into_iter() - .enumerate() - { - columns[i].push_id(i, |ui| { - let response = if self.late_interaction { - let first_response = - ui.add(egui::Button::new(sense_name).sense(egui::Sense::hover())); - first_response.interact(sense) - } else { - ui.add(egui::Button::new(sense_name).sense(sense)) - }; - let info = response_summary(&response, self.show_hovers); - self.history[i].add(info.trim().to_owned()); - self.history[i].ui(ui); - }); - } - }); - } -} - -fn response_summary(response: &egui::Response, show_hovers: bool) -> String { - use std::fmt::Write as _; - - let mut new_info = String::new(); - - if show_hovers { - if response.hovered() { - writeln!(new_info, "hovered").ok(); - } - if response.contains_pointer() { - writeln!(new_info, "contains_pointer").ok(); - } - if response.is_pointer_button_down_on() { - writeln!(new_info, "pointer_down_on").ok(); - } - if let Some(pos) = response.interact_pointer_pos() { - writeln!(new_info, "response.interact_pointer_pos: {pos:?}").ok(); - } - } - - for &button in &[ - egui::PointerButton::Primary, - egui::PointerButton::Secondary, - egui::PointerButton::Middle, - egui::PointerButton::Extra1, - egui::PointerButton::Extra2, - ] { - let button_suffix = if button == egui::PointerButton::Primary { - // Reduce visual clutter in common case: - String::default() - } else { - format!(" by {button:?} button") - }; - - // These are in inverse logical/chonological order, because we show them in the ui that way: - - if response.triple_clicked_by(button) { - writeln!(new_info, "Triple-clicked{button_suffix}").ok(); - } - if response.double_clicked_by(button) { - writeln!(new_info, "Double-clicked{button_suffix}").ok(); - } - if response.clicked_by(button) { - writeln!(new_info, "Clicked{button_suffix}").ok(); - } - - if response.drag_stopped_by(button) { - writeln!(new_info, "Drag stopped{button_suffix}").ok(); - } - if response.dragged_by(button) { - writeln!(new_info, "Dragged{button_suffix}").ok(); - } - if response.drag_started_by(button) { - writeln!(new_info, "Drag started{button_suffix}").ok(); - } - } - - if response.long_touched() { - writeln!(new_info, "Clicked with long-press").ok(); - } - - new_info -} - -// ---------------------------------------------------------------------------- - -pub struct WindowResizeTest { - text: String, -} - -impl Default for WindowResizeTest { - fn default() -> Self { - Self { - text: crate::LOREM_IPSUM_LONG.to_owned(), - } - } -} - -impl super::Demo for WindowResizeTest { - fn name(&self) -> &'static str { - "โ†” Window Resize" - } - - fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - use egui::*; - - Window::new("โ†” auto-sized") - .open(open) - .auto_sized() - .show(ctx, |ui| { - ui.label("This window will auto-size based on its contents."); - ui.heading("Resize this area:"); - Resize::default().show(ui, |ui| { - lorem_ipsum(ui, crate::LOREM_IPSUM); - }); - ui.heading("Resize the above area!"); - }); - - Window::new("โ†” resizable + scroll") - .open(open) - .vscroll(true) - .resizable(true) - .default_height(300.0) - .show(ctx, |ui| { - ui.label( - "This window is resizable and has a scroll area. You can shrink it to any size.", - ); - ui.separator(); - lorem_ipsum(ui, crate::LOREM_IPSUM_LONG); - }); - - Window::new("โ†” resizable + embedded scroll") - .open(open) - .vscroll(false) - .resizable(true) - .default_height(300.0) - .show(ctx, |ui| { - ui.label("This window is resizable but has no built-in scroll area."); - ui.label("However, we have a sub-region with a scroll bar:"); - ui.separator(); - ScrollArea::vertical().show(ui, |ui| { - let lorem_ipsum_extra_long = - format!("{}\n\n{}", crate::LOREM_IPSUM_LONG, crate::LOREM_IPSUM_LONG); - lorem_ipsum(ui, &lorem_ipsum_extra_long); - }); - // ui.heading("Some additional text here, that should also be visible"); // this works, but messes with the resizing a bit - }); - - Window::new("โ†” resizable without scroll") - .open(open) - .vscroll(false) - .resizable(true) - .show(ctx, |ui| { - ui.label("This window is resizable but has no scroll area. This means it can only be resized to a size where all the contents is visible."); - ui.label("egui will not clip the contents of a window, nor add whitespace to it."); - ui.separator(); - lorem_ipsum(ui, crate::LOREM_IPSUM); - }); - - Window::new("โ†” resizable with TextEdit") - .open(open) - .vscroll(false) - .resizable(true) - .default_height(300.0) - .show(ctx, |ui| { - ui.label("Shows how you can fill an area with a widget."); - ui.add_sized(ui.available_size(), TextEdit::multiline(&mut self.text)); - }); - - Window::new("โ†” freely resized") - .open(open) - .vscroll(false) - .resizable(true) - .default_size([250.0, 150.0]) - .show(ctx, |ui| { - ui.label("This window has empty space that fills up the available space, preventing auto-shrink."); - ui.vertical_centered(|ui| { - ui.add(crate::egui_github_link_file!()); - }); - ui.allocate_space(ui.available_size()); - }); - } -} - -fn lorem_ipsum(ui: &mut egui::Ui, text: &str) { - ui.with_layout( - egui::Layout::top_down(egui::Align::LEFT).with_cross_justify(true), - |ui| { - ui.label(egui::RichText::new(text).weak()); - }, - ); -} diff --git a/crates/egui_demo_lib/src/demo/tests/cursor_test.rs b/crates/egui_demo_lib/src/demo/tests/cursor_test.rs new file mode 100644 index 000000000..78214d5eb --- /dev/null +++ b/crates/egui_demo_lib/src/demo/tests/cursor_test.rs @@ -0,0 +1,29 @@ +#[derive(Default)] +pub struct CursorTest {} + +impl crate::Demo for CursorTest { + fn name(&self) -> &'static str { + "Cursor Test" + } + + fn show(&mut self, ctx: &egui::Context, open: &mut bool) { + egui::Window::new(self.name()).open(open).show(ctx, |ui| { + use crate::View as _; + self.ui(ui); + }); + } +} + +impl crate::View for CursorTest { + fn ui(&mut self, ui: &mut egui::Ui) { + ui.vertical_centered_justified(|ui| { + ui.heading("Hover to switch cursor icon:"); + for &cursor_icon in &egui::CursorIcon::ALL { + let _ = ui + .button(format!("{cursor_icon:?}")) + .on_hover_cursor(cursor_icon); + } + ui.add(crate::egui_github_link_file!()); + }); + } +} diff --git a/crates/egui_demo_lib/src/demo/tests/id_test.rs b/crates/egui_demo_lib/src/demo/tests/id_test.rs new file mode 100644 index 000000000..6fd0e067a --- /dev/null +++ b/crates/egui_demo_lib/src/demo/tests/id_test.rs @@ -0,0 +1,54 @@ +#[derive(Default)] +pub struct IdTest {} + +impl crate::Demo for IdTest { + fn name(&self) -> &'static str { + "ID Test" + } + + fn show(&mut self, ctx: &egui::Context, open: &mut bool) { + egui::Window::new(self.name()).open(open).show(ctx, |ui| { + use crate::View as _; + self.ui(ui); + }); + } +} + +impl crate::View for IdTest { + fn ui(&mut self, ui: &mut egui::Ui) { + // Make sure the warnings are on (by default they are only on in debug builds). + ui.ctx().options_mut(|opt| opt.warn_on_id_clash = true); + + ui.heading("Name collision example"); + + ui.label("\ + Widgets that store state require unique and persisting identifiers so we can track their state between frames.\n\ + For instance, collapsible headers needs to store whether or not they are open. \ + Their Id:s are derived from their names. \ + If you fail to give them unique names then clicking one will open both. \ + To help you debug this, an error message is printed on screen:"); + + ui.collapsing("Collapsing header", |ui| { + ui.label("Contents of first foldable ui"); + }); + ui.collapsing("Collapsing header", |ui| { + ui.label("Contents of second foldable ui"); + }); + + ui.label("\ + Any widget that can be interacted with also need a unique Id. \ + For most widgets the Id is generated by a running counter. \ + As long as elements are not added or removed, the Id stays the same. \ + This is fine, because during interaction (i.e. while dragging a slider), \ + the number of widgets previously in the same window is most likely not changing \ + (and if it is, the window will have a new layout, and the slider will end up somewhere else, and so aborting the interaction probably makes sense)."); + + ui.label("So these buttons have automatic Id:s, and therefore there is no name clash:"); + let _ = ui.button("Button"); + let _ = ui.button("Button"); + + ui.vertical_centered(|ui| { + ui.add(crate::egui_github_link_file!()); + }); + } +} diff --git a/crates/egui_demo_lib/src/demo/tests/input_test.rs b/crates/egui_demo_lib/src/demo/tests/input_test.rs new file mode 100644 index 000000000..4b10bdf4d --- /dev/null +++ b/crates/egui_demo_lib/src/demo/tests/input_test.rs @@ -0,0 +1,186 @@ +struct HistoryEntry { + text: String, + repeated: usize, +} + +#[derive(Default)] +struct DeduplicatedHistory { + history: std::collections::VecDeque, +} + +impl DeduplicatedHistory { + fn add(&mut self, text: String) { + if let Some(entry) = self.history.back_mut() { + if entry.text == text { + entry.repeated += 1; + return; + } + } + self.history.push_back(HistoryEntry { text, repeated: 1 }); + if self.history.len() > 100 { + self.history.pop_front(); + } + } + + fn ui(&self, ui: &mut egui::Ui) { + egui::ScrollArea::vertical() + .auto_shrink(false) + .show(ui, |ui| { + ui.spacing_mut().item_spacing.y = 4.0; + for HistoryEntry { text, repeated } in self.history.iter().rev() { + ui.horizontal(|ui| { + if text.is_empty() { + ui.weak("(empty)"); + } else { + ui.label(text); + } + if 1 < *repeated { + ui.weak(format!(" x{repeated}")); + } + }); + } + }); + } +} + +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[derive(Default)] +pub struct InputTest { + #[cfg_attr(feature = "serde", serde(skip))] + history: [DeduplicatedHistory; 4], + + late_interaction: bool, + + show_hovers: bool, +} + +impl crate::Demo for InputTest { + fn name(&self) -> &'static str { + "Input Test" + } + + fn show(&mut self, ctx: &egui::Context, open: &mut bool) { + egui::Window::new(self.name()) + .default_width(800.0) + .open(open) + .resizable(true) + .scroll(false) + .show(ctx, |ui| { + use crate::View as _; + self.ui(ui); + }); + } +} + +impl crate::View for InputTest { + fn ui(&mut self, ui: &mut egui::Ui) { + ui.spacing_mut().item_spacing.y = 8.0; + + ui.vertical_centered(|ui| { + ui.add(crate::egui_github_link_file!()); + }); + + ui.horizontal(|ui| { + if ui.button("Clear").clicked() { + *self = Default::default(); + } + + ui.checkbox(&mut self.show_hovers, "Show hover state"); + }); + + ui.checkbox(&mut self.late_interaction, "Use Response::interact"); + + ui.label("This tests how egui::Response reports events.\n\ + The different buttons are sensitive to different things.\n\ + Try interacting with them with any mouse button by clicking, double-clicking, triple-clicking, or dragging them."); + + ui.columns(4, |columns| { + for (i, (sense_name, sense)) in [ + ("Sense::hover", egui::Sense::hover()), + ("Sense::click", egui::Sense::click()), + ("Sense::drag", egui::Sense::drag()), + ("Sense::click_and_drag", egui::Sense::click_and_drag()), + ] + .into_iter() + .enumerate() + { + columns[i].push_id(i, |ui| { + let response = if self.late_interaction { + let first_response = + ui.add(egui::Button::new(sense_name).sense(egui::Sense::hover())); + first_response.interact(sense) + } else { + ui.add(egui::Button::new(sense_name).sense(sense)) + }; + let info = response_summary(&response, self.show_hovers); + self.history[i].add(info.trim().to_owned()); + self.history[i].ui(ui); + }); + } + }); + } +} + +fn response_summary(response: &egui::Response, show_hovers: bool) -> String { + use std::fmt::Write as _; + + let mut new_info = String::new(); + + if show_hovers { + if response.hovered() { + writeln!(new_info, "hovered").ok(); + } + if response.contains_pointer() { + writeln!(new_info, "contains_pointer").ok(); + } + if response.is_pointer_button_down_on() { + writeln!(new_info, "pointer_down_on").ok(); + } + if let Some(pos) = response.interact_pointer_pos() { + writeln!(new_info, "response.interact_pointer_pos: {pos:?}").ok(); + } + } + + for &button in &[ + egui::PointerButton::Primary, + egui::PointerButton::Secondary, + egui::PointerButton::Middle, + egui::PointerButton::Extra1, + egui::PointerButton::Extra2, + ] { + let button_suffix = if button == egui::PointerButton::Primary { + // Reduce visual clutter in common case: + String::default() + } else { + format!(" by {button:?} button") + }; + + // These are in inverse logical/chonological order, because we show them in the ui that way: + + if response.triple_clicked_by(button) { + writeln!(new_info, "Triple-clicked{button_suffix}").ok(); + } + if response.double_clicked_by(button) { + writeln!(new_info, "Double-clicked{button_suffix}").ok(); + } + if response.clicked_by(button) { + writeln!(new_info, "Clicked{button_suffix}").ok(); + } + + if response.drag_stopped_by(button) { + writeln!(new_info, "Drag stopped{button_suffix}").ok(); + } + if response.dragged_by(button) { + writeln!(new_info, "Dragged{button_suffix}").ok(); + } + if response.drag_started_by(button) { + writeln!(new_info, "Drag started{button_suffix}").ok(); + } + } + + if response.long_touched() { + writeln!(new_info, "Clicked with long-press").ok(); + } + + new_info +} diff --git a/crates/egui_demo_lib/src/demo/layout_test.rs b/crates/egui_demo_lib/src/demo/tests/layout_test.rs similarity index 98% rename from crates/egui_demo_lib/src/demo/layout_test.rs rename to crates/egui_demo_lib/src/demo/tests/layout_test.rs index 2bc1fd0d4..bc5e40e56 100644 --- a/crates/egui_demo_lib/src/demo/layout_test.rs +++ b/crates/egui_demo_lib/src/demo/tests/layout_test.rs @@ -73,7 +73,7 @@ impl LayoutSettings { } } -impl super::Demo for LayoutTest { +impl crate::Demo for LayoutTest { fn name(&self) -> &'static str { "Layout Test" } @@ -83,13 +83,13 @@ impl super::Demo for LayoutTest { .open(open) .resizable(false) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for LayoutTest { +impl crate::View for LayoutTest { fn ui(&mut self, ui: &mut Ui) { ui.label("Tests and demonstrates the limits of the egui layouts"); self.content_ui(ui); diff --git a/crates/egui_demo_lib/src/demo/tests/manual_layout_test.rs b/crates/egui_demo_lib/src/demo/tests/manual_layout_test.rs new file mode 100644 index 000000000..5d3da2262 --- /dev/null +++ b/crates/egui_demo_lib/src/demo/tests/manual_layout_test.rs @@ -0,0 +1,89 @@ +#[derive(Clone, Copy, Debug, PartialEq)] +enum WidgetType { + Label, + Button, + TextEdit, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ManualLayoutTest { + widget_offset: egui::Vec2, + widget_size: egui::Vec2, + widget_type: WidgetType, + text_edit_contents: String, +} + +impl Default for ManualLayoutTest { + fn default() -> Self { + Self { + widget_offset: egui::Vec2::splat(150.0), + widget_size: egui::vec2(200.0, 100.0), + widget_type: WidgetType::Button, + text_edit_contents: crate::LOREM_IPSUM.to_owned(), + } + } +} + +impl crate::Demo for ManualLayoutTest { + fn name(&self) -> &'static str { + "Manual Layout Test" + } + + fn show(&mut self, ctx: &egui::Context, open: &mut bool) { + egui::Window::new(self.name()) + .resizable(false) + .open(open) + .show(ctx, |ui| { + use crate::View as _; + self.ui(ui); + }); + } +} + +impl crate::View for ManualLayoutTest { + fn ui(&mut self, ui: &mut egui::Ui) { + egui::reset_button(ui, self, "Reset"); + + let Self { + widget_offset, + widget_size, + widget_type, + text_edit_contents, + } = self; + ui.horizontal(|ui| { + ui.label("Test widget:"); + ui.radio_value(widget_type, WidgetType::Button, "Button"); + ui.radio_value(widget_type, WidgetType::Label, "Label"); + ui.radio_value(widget_type, WidgetType::TextEdit, "TextEdit"); + }); + egui::Grid::new("pos_size").show(ui, |ui| { + ui.label("Widget position:"); + ui.add(egui::Slider::new(&mut widget_offset.x, 0.0..=400.0)); + ui.add(egui::Slider::new(&mut widget_offset.y, 0.0..=400.0)); + ui.end_row(); + + ui.label("Widget size:"); + ui.add(egui::Slider::new(&mut widget_size.x, 0.0..=400.0)); + ui.add(egui::Slider::new(&mut widget_size.y, 0.0..=400.0)); + ui.end_row(); + }); + + let widget_rect = + egui::Rect::from_min_size(ui.min_rect().min + *widget_offset, *widget_size); + + ui.add(crate::egui_github_link_file!()); + + // Showing how to place a widget anywhere in the [`Ui`]: + match *widget_type { + WidgetType::Button => { + ui.put(widget_rect, egui::Button::new("Example button")); + } + WidgetType::Label => { + ui.put(widget_rect, egui::Label::new("Example label")); + } + WidgetType::TextEdit => { + ui.put(widget_rect, egui::TextEdit::multiline(text_edit_contents)); + } + } + } +} diff --git a/crates/egui_demo_lib/src/demo/tests/mod.rs b/crates/egui_demo_lib/src/demo/tests/mod.rs new file mode 100644 index 000000000..8daf61fce --- /dev/null +++ b/crates/egui_demo_lib/src/demo/tests/mod.rs @@ -0,0 +1,15 @@ +mod cursor_test; +mod id_test; +mod input_test; +mod layout_test; +mod manual_layout_test; +mod table_test; +mod window_resize_test; + +pub use cursor_test::CursorTest; +pub use id_test::IdTest; +pub use input_test::InputTest; +pub use layout_test::LayoutTest; +pub use manual_layout_test::ManualLayoutTest; +pub use table_test::TableTest; +pub use window_resize_test::WindowResizeTest; diff --git a/crates/egui_demo_lib/src/demo/tests/table_test.rs b/crates/egui_demo_lib/src/demo/tests/table_test.rs new file mode 100644 index 000000000..72e39ff00 --- /dev/null +++ b/crates/egui_demo_lib/src/demo/tests/table_test.rs @@ -0,0 +1,124 @@ +#[derive(PartialEq)] +pub struct TableTest { + num_cols: usize, + num_rows: usize, + min_col_width: f32, + max_col_width: f32, + text_length: usize, +} + +impl Default for TableTest { + fn default() -> Self { + Self { + num_cols: 4, + num_rows: 4, + min_col_width: 10.0, + max_col_width: 200.0, + text_length: 10, + } + } +} + +impl crate::Demo for TableTest { + fn name(&self) -> &'static str { + "Table Test" + } + + fn show(&mut self, ctx: &egui::Context, open: &mut bool) { + egui::Window::new(self.name()).open(open).show(ctx, |ui| { + use crate::View as _; + self.ui(ui); + }); + } +} + +impl crate::View for TableTest { + fn ui(&mut self, ui: &mut egui::Ui) { + ui.add( + egui::Slider::new(&mut self.min_col_width, 0.0..=400.0).text("Minimum column width"), + ); + ui.add( + egui::Slider::new(&mut self.max_col_width, 0.0..=400.0).text("Maximum column width"), + ); + ui.add(egui::Slider::new(&mut self.num_cols, 0..=5).text("Columns")); + ui.add(egui::Slider::new(&mut self.num_rows, 0..=20).text("Rows")); + + ui.separator(); + + let words = [ + "random", "words", "in", "a", "random", "order", "that", "just", "keeps", "going", + "with", "some", "more", + ]; + + egui::Grid::new("my_grid") + .striped(true) + .min_col_width(self.min_col_width) + .max_col_width(self.max_col_width) + .show(ui, |ui| { + for row in 0..self.num_rows { + for col in 0..self.num_cols { + if col == 0 { + ui.label(format!("row {row}")); + } else { + let word_idx = row * 3 + col * 5; + let word_count = (row * 5 + col * 75) % 13; + let mut string = String::new(); + for word in words.iter().cycle().skip(word_idx).take(word_count) { + string += word; + string += " "; + } + ui.label(string); + } + } + ui.end_row(); + } + }); + + ui.separator(); + ui.add(egui::Slider::new(&mut self.text_length, 1..=40).text("Text length")); + egui::Grid::new("parent grid").striped(true).show(ui, |ui| { + ui.vertical(|ui| { + ui.label("Vertical nest1"); + ui.label("Vertical nest2"); + }); + ui.label("First row, second column"); + ui.end_row(); + + ui.horizontal(|ui| { + ui.label("Horizontal nest1"); + ui.label("Horizontal nest2"); + }); + ui.label("Second row, second column"); + ui.end_row(); + + ui.scope(|ui| { + ui.label("Scope nest 1"); + ui.label("Scope nest 2"); + }); + ui.label("Third row, second column"); + ui.end_row(); + + egui::Grid::new("nested grid").show(ui, |ui| { + ui.label("Grid nest11"); + ui.label("Grid nest12"); + ui.end_row(); + ui.label("Grid nest21"); + ui.label("Grid nest22"); + ui.end_row(); + }); + ui.label("Fourth row, second column"); + ui.end_row(); + + let mut dyn_text = String::from("O"); + dyn_text.extend(std::iter::repeat('h').take(self.text_length)); + ui.label(dyn_text); + ui.label("Fifth row, second column"); + ui.end_row(); + }); + + ui.vertical_centered(|ui| { + egui::reset_button(ui, self, "Reset"); + ui.add(crate::egui_github_link_file!()); + }); + } +} diff --git a/crates/egui_demo_lib/src/demo/tests/window_resize_test.rs b/crates/egui_demo_lib/src/demo/tests/window_resize_test.rs new file mode 100644 index 000000000..a61540df3 --- /dev/null +++ b/crates/egui_demo_lib/src/demo/tests/window_resize_test.rs @@ -0,0 +1,106 @@ +pub struct WindowResizeTest { + text: String, +} + +impl Default for WindowResizeTest { + fn default() -> Self { + Self { + text: crate::LOREM_IPSUM_LONG.to_owned(), + } + } +} + +impl crate::Demo for WindowResizeTest { + fn name(&self) -> &'static str { + "Window Resize Test" + } + + fn show(&mut self, ctx: &egui::Context, open: &mut bool) { + use egui::*; + + Window::new("โ†” auto-sized") + .open(open) + .auto_sized() + .show(ctx, |ui| { + ui.label("This window will auto-size based on its contents."); + ui.heading("Resize this area:"); + Resize::default().show(ui, |ui| { + lorem_ipsum(ui, crate::LOREM_IPSUM); + }); + ui.heading("Resize the above area!"); + }); + + Window::new("โ†” resizable + scroll") + .open(open) + .vscroll(true) + .resizable(true) + .default_height(300.0) + .show(ctx, |ui| { + ui.label( + "This window is resizable and has a scroll area. You can shrink it to any size.", + ); + ui.separator(); + lorem_ipsum(ui, crate::LOREM_IPSUM_LONG); + }); + + Window::new("โ†” resizable + embedded scroll") + .open(open) + .vscroll(false) + .resizable(true) + .default_height(300.0) + .show(ctx, |ui| { + ui.label("This window is resizable but has no built-in scroll area."); + ui.label("However, we have a sub-region with a scroll bar:"); + ui.separator(); + ScrollArea::vertical().show(ui, |ui| { + let lorem_ipsum_extra_long = + format!("{}\n\n{}", crate::LOREM_IPSUM_LONG, crate::LOREM_IPSUM_LONG); + lorem_ipsum(ui, &lorem_ipsum_extra_long); + }); + // ui.heading("Some additional text here, that should also be visible"); // this works, but messes with the resizing a bit + }); + + Window::new("โ†” resizable without scroll") + .open(open) + .vscroll(false) + .resizable(true) + .show(ctx, |ui| { + ui.label("This window is resizable but has no scroll area. This means it can only be resized to a size where all the contents is visible."); + ui.label("egui will not clip the contents of a window, nor add whitespace to it."); + ui.separator(); + lorem_ipsum(ui, crate::LOREM_IPSUM); + }); + + Window::new("โ†” resizable with TextEdit") + .open(open) + .vscroll(false) + .resizable(true) + .default_height(300.0) + .show(ctx, |ui| { + ui.label("Shows how you can fill an area with a widget."); + ui.add_sized(ui.available_size(), TextEdit::multiline(&mut self.text)); + }); + + Window::new("โ†” freely resized") + .open(open) + .vscroll(false) + .resizable(true) + .default_size([250.0, 150.0]) + .show(ctx, |ui| { + ui.label("This window has empty space that fills up the available space, preventing auto-shrink."); + ui.vertical_centered(|ui| { + ui.add(crate::egui_github_link_file!()); + }); + ui.allocate_space(ui.available_size()); + }); + } +} + +fn lorem_ipsum(ui: &mut egui::Ui, text: &str) { + ui.with_layout( + egui::Layout::top_down(egui::Align::LEFT).with_cross_justify(true), + |ui| { + ui.label(egui::RichText::new(text).weak()); + }, + ); +} diff --git a/crates/egui_demo_lib/src/demo/text_edit.rs b/crates/egui_demo_lib/src/demo/text_edit.rs index 520416cc5..9743306c7 100644 --- a/crates/egui_demo_lib/src/demo/text_edit.rs +++ b/crates/egui_demo_lib/src/demo/text_edit.rs @@ -14,7 +14,7 @@ impl Default for TextEditDemo { } } -impl super::Demo for TextEditDemo { +impl crate::Demo for TextEditDemo { fn name(&self) -> &'static str { "๐Ÿ–น TextEdit" } @@ -24,13 +24,13 @@ impl super::Demo for TextEditDemo { .open(open) .resizable(false) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for TextEditDemo { +impl crate::View for TextEditDemo { fn ui(&mut self, ui: &mut egui::Ui) { ui.vertical_centered(|ui| { ui.add(crate::egui_github_link_file!()); diff --git a/crates/egui_demo_lib/src/demo/text_layout.rs b/crates/egui_demo_lib/src/demo/text_layout.rs index fa02a7175..e4e7ddcc3 100644 --- a/crates/egui_demo_lib/src/demo/text_layout.rs +++ b/crates/egui_demo_lib/src/demo/text_layout.rs @@ -23,7 +23,7 @@ impl Default for TextLayoutDemo { } } -impl super::Demo for TextLayoutDemo { +impl crate::Demo for TextLayoutDemo { fn name(&self) -> &'static str { "๐Ÿ–น Text Layout" } @@ -33,13 +33,13 @@ impl super::Demo for TextLayoutDemo { .open(open) .resizable(true) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for TextLayoutDemo { +impl crate::View for TextLayoutDemo { fn ui(&mut self, ui: &mut egui::Ui) { let Self { break_anywhere, diff --git a/crates/egui_demo_lib/src/demo/tooltips.rs b/crates/egui_demo_lib/src/demo/tooltips.rs index 7daf14e8d..c0960a70e 100644 --- a/crates/egui_demo_lib/src/demo/tooltips.rs +++ b/crates/egui_demo_lib/src/demo/tooltips.rs @@ -10,13 +10,13 @@ impl Default for Tooltips { } } -impl super::Demo for Tooltips { +impl crate::Demo for Tooltips { fn name(&self) -> &'static str { "๐Ÿ—– Tooltips" } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - use super::View as _; + use crate::View as _; let window = egui::Window::new("Tooltips") .constrain(false) // So we can test how tooltips behave close to the screen edge .resizable(false) @@ -26,7 +26,7 @@ impl super::Demo for Tooltips { } } -impl super::View for Tooltips { +impl crate::View for Tooltips { fn ui(&mut self, ui: &mut egui::Ui) { ui.spacing_mut().item_spacing.y = 8.0; @@ -75,7 +75,7 @@ impl super::View for Tooltips { ui.horizontal(|ui| { ui.checkbox(&mut self.enabled, "Enabled") - .on_hover_text("Controls whether or not the button below is enabled."); + .on_hover_text("Controls whether or not the following button is enabled."); ui.add_enabled(self.enabled, egui::Button::new("Sometimes clickable")) .on_hover_ui(tooltip_ui) diff --git a/crates/egui_demo_lib/src/demo/widget_gallery.rs b/crates/egui_demo_lib/src/demo/widget_gallery.rs index bacb25792..063ff305e 100644 --- a/crates/egui_demo_lib/src/demo/widget_gallery.rs +++ b/crates/egui_demo_lib/src/demo/widget_gallery.rs @@ -42,7 +42,7 @@ impl Default for WidgetGallery { } } -impl super::Demo for WidgetGallery { +impl crate::Demo for WidgetGallery { fn name(&self) -> &'static str { "๐Ÿ—„ Widget Gallery" } @@ -53,13 +53,13 @@ impl super::Demo for WidgetGallery { .resizable([true, false]) .default_width(280.0) .show(ctx, |ui| { - use super::View as _; + use crate::View as _; self.ui(ui); }); } } -impl super::View for WidgetGallery { +impl crate::View for WidgetGallery { fn ui(&mut self, ui: &mut egui::Ui) { ui.add_enabled_ui(self.enabled, |ui| { if !self.visible { diff --git a/crates/egui_demo_lib/src/demo/window_options.rs b/crates/egui_demo_lib/src/demo/window_options.rs index 8a95a16f1..f0d24b460 100644 --- a/crates/egui_demo_lib/src/demo/window_options.rs +++ b/crates/egui_demo_lib/src/demo/window_options.rs @@ -35,7 +35,7 @@ impl Default for WindowOptions { } } -impl super::Demo for WindowOptions { +impl crate::Demo for WindowOptions { fn name(&self) -> &'static str { "๐Ÿ—– Window Options" } @@ -60,7 +60,7 @@ impl super::Demo for WindowOptions { ctx.request_repaint(); } - use super::View as _; + use crate::View as _; let mut window = egui::Window::new(title) .id(egui::Id::new("demo_window_options")) // required since we change the title .resizable(resizable) @@ -79,7 +79,7 @@ impl super::Demo for WindowOptions { } } -impl super::View for WindowOptions { +impl crate::View for WindowOptions { fn ui(&mut self, ui: &mut egui::Ui) { let Self { title, diff --git a/crates/egui_demo_lib/src/lib.rs b/crates/egui_demo_lib/src/lib.rs index 68bdc8eed..ce18e0910 100644 --- a/crates/egui_demo_lib/src/lib.rs +++ b/crates/egui_demo_lib/src/lib.rs @@ -15,7 +15,7 @@ mod demo; pub mod easy_mark; mod rendering_test; -pub use demo::{DemoWindows, WidgetGallery}; +pub use demo::{Demo, DemoWindows, View, WidgetGallery}; pub use rendering_test::ColorTest; /// View some Rust code with syntax highlighting and selection.