Rebrand to Galaxy, major improvements to Bedrock support, still needs some TLC though
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::borrow::Cow;
|
||||
pub mod root_view;
|
||||
|
||||
extern crate galaxyui;
|
||||
use rust_embed::RustEmbed;
|
||||
use galaxyui::{platform, AssetProvider};
|
||||
|
||||
#[derive(Clone, Copy, RustEmbed)]
|
||||
#[folder = "examples/assets"]
|
||||
pub struct Assets;
|
||||
|
||||
// The static assets we need to load in app.
|
||||
pub static ASSETS: Assets = Assets;
|
||||
|
||||
// Implement the AssetProvider trait here (required by App::new).
|
||||
impl AssetProvider for Assets {
|
||||
fn get(&self, path: &str) -> Result<Cow<'_, [u8]>> {
|
||||
<Assets as RustEmbed>::get(path)
|
||||
.map(|f| f.data)
|
||||
.ok_or_else(|| anyhow!("no asset exists at path {}", path))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let app_builder =
|
||||
platform::AppBuilder::new(platform::AppCallbacks::default(), Box::new(ASSETS), None);
|
||||
let _ = app_builder.run(move |ctx| {
|
||||
ctx.add_window(
|
||||
galaxyui::AddWindowOptions::default(),
|
||||
root_view::RootView::new,
|
||||
);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
use galaxyui::fonts::FamilyId;
|
||||
use galaxyui::SingletonEntity as _;
|
||||
use galaxyui::{
|
||||
elements::{
|
||||
Border, ConstrainedBox, Container, Fill, Flex, List, ListState, MainAxisSize,
|
||||
ParentElement, Rect, ScrollStateHandle, Scrollable, ScrollableElement, ScrollbarWidth,
|
||||
Stack, Text,
|
||||
},
|
||||
AppContext, Element, Entity, TypedActionView, View, ViewContext,
|
||||
};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use galaxyui::color::ColorU;
|
||||
|
||||
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 = ();
|
||||
}
|
||||
Reference in New Issue
Block a user