diff --git a/egui_demo_lib/src/apps/demo/demo_window.rs b/egui_demo_lib/src/apps/demo/demo_window.rs index 0084231c..0e49b03d 100644 --- a/egui_demo_lib/src/apps/demo/demo_window.rs +++ b/egui_demo_lib/src/apps/demo/demo_window.rs @@ -8,7 +8,6 @@ pub struct DemoWindow { num_columns: usize, widgets: Widgets, - scrolls: Scrolls, colors: ColorWidgets, layout: LayoutDemo, tree: Tree, @@ -20,7 +19,6 @@ impl Default for DemoWindow { DemoWindow { num_columns: 2, - scrolls: Default::default(), widgets: Default::default(), colors: Default::default(), layout: Default::default(), @@ -68,12 +66,6 @@ impl DemoWindow { .default_open(false) .show(ui, |ui| self.box_painting.ui(ui)); - CollapsingHeader::new("Scroll area") - .default_open(false) - .show(ui, |ui| { - self.scrolls.ui(ui); - }); - CollapsingHeader::new("Resize") .default_open(false) .show(ui, |ui| { diff --git a/egui_demo_lib/src/apps/demo/demo_windows.rs b/egui_demo_lib/src/apps/demo/demo_windows.rs index 31483056..04664ab9 100644 --- a/egui_demo_lib/src/apps/demo/demo_windows.rs +++ b/egui_demo_lib/src/apps/demo/demo_windows.rs @@ -13,15 +13,16 @@ struct Demos { impl Default for Demos { fn default() -> Self { let demos: Vec> = vec![ - Box::new(super::WidgetGallery::default()), + Box::new(super::widget_gallery::WidgetGallery::default()), Box::new(super::sliders::Sliders::default()), Box::new(super::input_test::InputTest::default()), - Box::new(super::FontBook::default()), - Box::new(super::Painting::default()), - Box::new(super::DancingStrings::default()), - Box::new(super::DragAndDropDemo::default()), - Box::new(super::Tests::default()), - Box::new(super::WindowOptions::default()), + Box::new(super::font_book::FontBook::default()), + Box::new(super::painting::Painting::default()), + Box::new(super::dancing_strings::DancingStrings::default()), + Box::new(super::drag_and_drop::DragAndDropDemo::default()), + Box::new(super::tests::Tests::default()), + Box::new(super::window_options::WindowOptions::default()), + Box::new(super::scrolling::Scrolling::default()), ]; Self { open: vec![false; demos.len()], diff --git a/egui_demo_lib/src/apps/demo/mod.rs b/egui_demo_lib/src/apps/demo/mod.rs index 7234dc02..a09e17c0 100644 --- a/egui_demo_lib/src/apps/demo/mod.rs +++ b/egui_demo_lib/src/apps/demo/mod.rs @@ -5,28 +5,24 @@ // ---------------------------------------------------------------------------- mod app; -mod dancing_strings; +pub mod dancing_strings; pub mod demo_window; mod demo_windows; -mod drag_and_drop; -mod font_book; +pub mod drag_and_drop; +pub mod font_book; pub mod font_contents_emoji; pub mod font_contents_ubuntu; pub mod input_test; -mod painting; -mod scrolls; +pub mod painting; +pub mod scrolling; pub mod sliders; -mod tests; +pub mod tests; pub mod toggle_switch; -mod widget_gallery; +pub mod widget_gallery; mod widgets; -mod window_options; +pub mod window_options; -pub use { - app::*, dancing_strings::DancingStrings, demo_window::DemoWindow, demo_windows::*, - drag_and_drop::*, font_book::FontBook, painting::Painting, scrolls::Scrolls, sliders::Sliders, - tests::Tests, widget_gallery::*, widgets::Widgets, window_options::WindowOptions, -}; +pub use {app::*, demo_window::DemoWindow, demo_windows::*, widgets::Widgets}; // ---------------------------------------------------------------------------- diff --git a/egui_demo_lib/src/apps/demo/scrolling.rs b/egui_demo_lib/src/apps/demo/scrolling.rs new file mode 100644 index 00000000..51b11e72 --- /dev/null +++ b/egui_demo_lib/src/apps/demo/scrolling.rs @@ -0,0 +1,122 @@ +use egui::{color::*, *}; + +#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "persistence", serde(default))] +pub struct Scrolling { + track_item: usize, + tack_item_align: Align, + offset: f32, +} + +impl Default for Scrolling { + fn default() -> Self { + Self { + track_item: 25, + tack_item_align: Align::Center, + offset: 0.0, + } + } +} + +impl super::Demo for Scrolling { + fn name(&self) -> &str { + "↕ Scrolling" + } + + fn show(&mut self, ctx: &egui::CtxRef, open: &mut bool) { + egui::Window::new(self.name()) + .open(open) + .resizable(false) + .show(ctx, |ui| { + use super::View; + self.ui(ui); + }); + } +} + +impl super::View for Scrolling { + fn ui(&mut self, ui: &mut Ui) { + ScrollArea::from_max_height(200.0) + .id_source("lorem_ipsum_scroll_area") + .show(ui, |ui| { + ui.label(crate::LOREM_IPSUM_LONG); + ui.label(crate::LOREM_IPSUM_LONG); + }); + + ui.separator(); + ui.label("This shows how you can scroll to a specific item or pixel offset"); + + let mut track_item = false; + let mut go_to_scroll_offset = false; + let mut scroll_top = false; + let mut scroll_bottom = false; + + ui.horizontal(|ui| { + ui.label("Scroll to a specific item index:"); + track_item |= ui + .add(Slider::usize(&mut self.track_item, 1..=50).text("Track Item")) + .dragged(); + }); + + ui.horizontal(|ui| { + ui.label("Item align:"); + track_item |= ui + .radio_value(&mut self.tack_item_align, Align::Min, "Top") + .clicked(); + track_item |= ui + .radio_value(&mut self.tack_item_align, Align::Center, "Center") + .clicked(); + track_item |= ui + .radio_value(&mut self.tack_item_align, Align::Max, "Bottom") + .clicked(); + }); + + ui.horizontal(|ui| { + ui.label("Scroll to a specific offset:"); + go_to_scroll_offset |= ui + .add(DragValue::f32(&mut self.offset).speed(1.0).suffix("px")) + .dragged(); + }); + + ui.horizontal(|ui| { + scroll_top |= ui.button("Scroll to top").clicked(); + scroll_bottom |= ui.button("Scroll to bottom").clicked(); + }); + + let mut scroll_area = ScrollArea::from_max_height(200.0); + if go_to_scroll_offset { + scroll_area = scroll_area.scroll_offset(self.offset); + } + + let (current_scroll, max_scroll) = scroll_area.show(ui, |ui| { + if scroll_top { + ui.scroll_to_cursor(Align::top()); + } + ui.vertical(|ui| { + for item in 1..=50 { + if track_item && item == self.track_item { + let response = ui.colored_label(Color32::YELLOW, format!("Item {}", item)); + response.scroll_to_me(self.tack_item_align); + } else { + ui.label(format!("Item {}", item)); + } + } + }); + + if scroll_bottom { + ui.scroll_to_cursor(Align::bottom()); + } + + let margin = ui.style().visuals.clip_rect_margin; + + let current_scroll = ui.clip_rect().top() - ui.min_rect().top() + margin; + let max_scroll = ui.min_rect().height() - ui.clip_rect().height() + 2.0 * margin; + (current_scroll, max_scroll) + }); + + ui.colored_label( + Color32::WHITE, + format!("{:.0}/{:.0} px", current_scroll, max_scroll), + ); + } +} diff --git a/egui_demo_lib/src/apps/demo/scrolls.rs b/egui_demo_lib/src/apps/demo/scrolls.rs deleted file mode 100644 index f99f476d..00000000 --- a/egui_demo_lib/src/apps/demo/scrolls.rs +++ /dev/null @@ -1,91 +0,0 @@ -use egui::{color::*, *}; - -#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "persistence", serde(default))] -pub struct Scrolls { - track_item: usize, - tracking: bool, - offset: f32, -} - -impl Default for Scrolls { - fn default() -> Self { - Self { - track_item: 25, - tracking: true, - offset: 0.0, - } - } -} - -impl Scrolls { - pub fn ui(&mut self, ui: &mut Ui) { - ScrollArea::from_max_height(200.0).show(ui, |ui| { - ui.label(crate::LOREM_IPSUM_LONG); - ui.label(crate::LOREM_IPSUM_LONG); - }); - - ui.separator(); - - ui.horizontal(|ui| { - ui.checkbox(&mut self.tracking, "Track") - .on_hover_text("The scroll position will track the selected item"); - ui.add(Slider::usize(&mut self.track_item, 1..=50).text("Track Item")); - }); - let (scroll_offset, _) = ui.horizontal(|ui| { - let scroll_offset = ui.small_button("Scroll Offset").clicked(); - ui.add(DragValue::f32(&mut self.offset).speed(1.0).suffix("px")); - scroll_offset - }); - - let scroll_top = ui.button("Scroll to top").clicked(); - let scroll_bottom = ui.button("Scroll to bottom").clicked(); - if scroll_bottom || scroll_top { - self.tracking = false; - } - - const TITLES: [&str; 3] = ["Top", "Middle", "Bottom"]; - const ALIGNS: [Align; 3] = [Align::Min, Align::Center, Align::Max]; - ui.columns(3, |cols| { - for (i, col) in cols.iter_mut().enumerate() { - col.colored_label(Color32::WHITE, TITLES[i]); - let mut scroll_area = ScrollArea::from_max_height(200.0).id_source(i); - if scroll_offset { - self.tracking = false; - scroll_area = scroll_area.scroll_offset(self.offset); - } - - let (current_scroll, max_scroll) = scroll_area.show(col, |ui| { - if scroll_top { - ui.scroll_to_cursor(Align::top()); - } - ui.vertical(|ui| { - for item in 1..=50 { - if self.tracking && item == self.track_item { - let response = - ui.colored_label(Color32::YELLOW, format!("Item {}", item)); - response.scroll_to_me(ALIGNS[i]); - } else { - ui.label(format!("Item {}", item)); - } - } - }); - - if scroll_bottom { - ui.scroll_to_cursor(Align::bottom()); - } - - let margin = ui.style().visuals.clip_rect_margin; - ( - ui.clip_rect().top() - ui.min_rect().top() + margin, - ui.min_rect().height() - ui.clip_rect().height() + 2.0 * margin, - ) - }); - col.colored_label( - Color32::WHITE, - format!("{:.0}/{:.0}", current_scroll, max_scroll), - ); - } - }); - } -}