207 lines
7.6 KiB
Rust
207 lines
7.6 KiB
Rust
use std::sync::{Arc, Mutex};
|
|
|
|
use galaxyui::color::ColorU;
|
|
use galaxyui::elements::{
|
|
Border, ConstrainedBox, Container, Fill, Flex, List, ListState, MainAxisSize, ParentElement,
|
|
Rect, ScrollStateHandle, Scrollable, ScrollableElement, ScrollbarWidth, Stack, Text,
|
|
};
|
|
use galaxyui::fonts::FamilyId;
|
|
use galaxyui::{
|
|
AppContext, Element, Entity, SingletonEntity as _, TypedActionView, View, ViewContext,
|
|
};
|
|
|
|
pub struct RootView {
|
|
font_family: FamilyId,
|
|
list_state: ListState<()>,
|
|
scroll_state: ScrollStateHandle,
|
|
}
|
|
|
|
impl RootView {
|
|
pub fn new(ctx: &mut ViewContext<Self>) -> Self {
|
|
let font_family = galaxyui::fonts::Cache::handle(ctx)
|
|
.update(ctx, |cache, _| cache.load_system_font("Arial").unwrap());
|
|
|
|
let list_state = ListState::new(move |i, _scroll_offset, _app| {
|
|
println!(" 📦 Creating element for item {i}"); // This should only appear for visible items!
|
|
Self::make_list_item(i, font_family).finish()
|
|
});
|
|
let scroll_state = Arc::new(Mutex::new(Default::default()));
|
|
|
|
// Add many items to demonstrate viewporting - only visible ones should be rendered
|
|
println!("Creating List with 1000 items...");
|
|
for _ in 0..=1000 {
|
|
list_state.add_item();
|
|
}
|
|
println!(
|
|
"✅ All 1000 items added to list state. Now only visible ones should be rendered."
|
|
);
|
|
|
|
RootView {
|
|
font_family,
|
|
list_state,
|
|
scroll_state,
|
|
}
|
|
}
|
|
|
|
fn make_list_item(index: usize, font_family: FamilyId) -> Container {
|
|
// Alternate colors to make it easy to see which items are rendered
|
|
let bg_color = if index.is_multiple_of(2) {
|
|
ColorU::new(240, 240, 240, 255) // Light gray
|
|
} else {
|
|
ColorU::new(255, 255, 255, 255) // White
|
|
};
|
|
|
|
let border_color = if index.is_multiple_of(10) {
|
|
ColorU::new(255, 0, 0, 255) // Red border for every 10th item
|
|
} else {
|
|
ColorU::new(200, 200, 200, 255) // Light gray border
|
|
};
|
|
|
|
let height = 50. * (index + 1) as f32;
|
|
|
|
Container::new(
|
|
ConstrainedBox::new(
|
|
Flex::row()
|
|
.with_child(
|
|
Text::new_inline(format!("Item #{index}"), font_family, 16.)
|
|
.with_color(ColorU::black())
|
|
.finish(),
|
|
)
|
|
.with_child(
|
|
Container::new(
|
|
ConstrainedBox::new(
|
|
Text::new_inline(
|
|
if index.is_multiple_of(10) {
|
|
" (MILESTONE)".to_string()
|
|
} else {
|
|
format!(" - Height: {height}px")
|
|
},
|
|
font_family,
|
|
14.,
|
|
)
|
|
.with_color(ColorU::black())
|
|
.finish(),
|
|
)
|
|
.with_width(200.)
|
|
.finish(),
|
|
)
|
|
.finish(),
|
|
)
|
|
.with_main_axis_size(MainAxisSize::Max)
|
|
.finish(),
|
|
)
|
|
.with_width(600.)
|
|
.with_height(height)
|
|
.finish(),
|
|
)
|
|
.with_background_color(bg_color)
|
|
.with_border(Border::all(1.).with_border_color(border_color))
|
|
}
|
|
|
|
fn make_instructions(&self) -> Box<dyn Element> {
|
|
Container::new(
|
|
ConstrainedBox::new(
|
|
Flex::column()
|
|
.with_child(
|
|
Text::new_inline(
|
|
"List Demo - 1000 Items".to_string(),
|
|
self.font_family,
|
|
20.,
|
|
)
|
|
.with_color(ColorU::black())
|
|
.finish(),
|
|
)
|
|
.with_child(
|
|
Text::new_inline(
|
|
"This demonstrates viewporting: only visible items are rendered!"
|
|
.to_string(),
|
|
self.font_family,
|
|
14.,
|
|
)
|
|
.with_color(ColorU::black())
|
|
.finish(),
|
|
)
|
|
.with_child(
|
|
Text::new_inline(
|
|
"🔍 Check the console output to see which items are being rendered."
|
|
.to_string(),
|
|
self.font_family,
|
|
14.,
|
|
)
|
|
.with_color(ColorU::black())
|
|
.finish(),
|
|
)
|
|
.with_child(
|
|
Text::new_inline(
|
|
"🟥 Red borders mark milestone items (every 10th).".to_string(),
|
|
self.font_family,
|
|
14.,
|
|
)
|
|
.with_color(ColorU::black())
|
|
.finish(),
|
|
)
|
|
.with_child(
|
|
Text::new_inline(
|
|
"📏 Viewport height: 400px.".to_string(),
|
|
self.font_family,
|
|
12.,
|
|
)
|
|
.with_color(ColorU::black())
|
|
.finish(),
|
|
)
|
|
.finish(),
|
|
)
|
|
.with_height(140.)
|
|
.finish(),
|
|
)
|
|
.with_background_color(ColorU::new(230, 230, 255, 255))
|
|
.with_border(Border::all(2.).with_border_color(ColorU::new(100, 100, 200, 255)))
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
impl Entity for RootView {
|
|
type Event = ();
|
|
}
|
|
|
|
impl View for RootView {
|
|
fn ui_name() -> &'static str {
|
|
"ListRootView"
|
|
}
|
|
|
|
fn render(&self, _: &AppContext) -> Box<dyn Element> {
|
|
Stack::new()
|
|
.with_child(Rect::new().with_background_color(ColorU::white()).finish())
|
|
.with_child(
|
|
Flex::column()
|
|
.with_child(self.make_instructions())
|
|
.with_child(
|
|
Container::new(
|
|
ConstrainedBox::new(
|
|
Scrollable::vertical(
|
|
self.scroll_state.clone(),
|
|
List::new(self.list_state.clone()).finish_scrollable(),
|
|
ScrollbarWidth::Auto,
|
|
Fill::Solid(ColorU::new(150, 150, 150, 255)), // Non-active thumb
|
|
Fill::Solid(ColorU::new(100, 100, 100, 255)), // Active thumb
|
|
Fill::Solid(ColorU::new(240, 240, 240, 255)), // Track background
|
|
)
|
|
.finish(),
|
|
)
|
|
.with_height(400.) // Constrain the viewport height
|
|
.finish(),
|
|
)
|
|
.with_background_color(ColorU::new(250, 250, 250, 255))
|
|
.with_border(Border::all(2.).with_border_color(ColorU::black()))
|
|
.finish(),
|
|
)
|
|
.finish(),
|
|
)
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
impl TypedActionView for RootView {
|
|
type Action = ();
|
|
}
|