123 lines
3.8 KiB
Rust
123 lines
3.8 KiB
Rust
![]() |
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),
|
||
|
);
|
||
|
}
|
||
|
}
|