Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-ui-renderer/examples/resizable/root_view.rs
1use strato_ui::fonts::FamilyId;
2use strato_ui::SingletonEntity as _;
3use strato_ui::{
4 color::ColorU,
5 elements::{
6 resizable_state_handle, Container, CrossAxisAlignment, DragBarSide, Flex,
7 MainAxisAlignment, MainAxisSize, ParentElement, Rect, Resizable, ResizableStateHandle,
8 Shrinkable, Stack, Text,
9 },
10 AppContext, Element, Entity, TypedActionView, View, ViewContext,
11};
12 
13pub struct RootView {
14 font_family: FamilyId,
15 left_panel_state: ResizableStateHandle,
16 top_panel_state: ResizableStateHandle,
17}
18 
19impl RootView {
20 pub fn new(ctx: &mut ViewContext<Self>) -> Self {
21 let font_family = strato_ui::fonts::Cache::handle(ctx)
22 .update(ctx, |cache, _| cache.load_system_font("Arial").unwrap());
23 
24 // Initialize resizable state handles
25 let left_panel_state = resizable_state_handle(250.0);
26 let top_panel_state = resizable_state_handle(150.0);
27 
28 RootView {
29 font_family,
30 left_panel_state,
31 top_panel_state,
32 }
33 }
34 
35 fn make_panel_content(&self, text: String, color: ColorU) -> Box<dyn Element> {
36 Container::new(
37 Flex::column()
38 .with_main_axis_alignment(MainAxisAlignment::Center)
39 .with_main_axis_size(MainAxisSize::Max)
40 .with_cross_axis_alignment(CrossAxisAlignment::Stretch)
41 .with_child(
42 Text::new_inline(text, self.font_family, 16.)
43 .with_color(ColorU::white())
44 .finish(),
45 )
46 .finish(),
47 )
48 .with_background_color(color)
49 .with_uniform_padding(10.)
50 .finish()
51 }
52 
53 fn make_info_text(&self, text: String) -> Box<dyn Element> {
54 Text::new_inline(text, self.font_family, 14.)
55 .with_color(ColorU::white())
56 .finish()
57 }
58}
59 
60impl Entity for RootView {
61 type Event = ();
62}
63 
64impl View for RootView {
65 fn ui_name() -> &'static str {
66 "RootView"
67 }
68 
69 fn render(&self, _: &AppContext) -> Box<dyn Element> {
70 // Create main column for vertical layout
71 let mut main_column = Flex::column().with_cross_axis_alignment(CrossAxisAlignment::Stretch);
72 
73 // Top panel with bottom-side dragbar for vertical resizing
74 let top_panel = Container::new(
75 Resizable::new(
76 self.top_panel_state.clone(),
77 self.make_panel_content(
78 "Top Panel\n(Drag bottom edge)".to_string(),
79 ColorU::new(200, 100, 200, 255),
80 ),
81 )
82 .with_dragbar_side(DragBarSide::Bottom)
83 .with_dragbar_color(strato_ui::elements::Fill::Solid(ColorU::new(
84 0, 255, 255, 200,
85 )))
86 .on_resize(move |ctx, _| {
87 ctx.notify();
88 })
89 .on_start_resizing(|_, _| {
90 eprintln!("Top panel: Started resizing");
91 })
92 .on_end_resizing(|_, _| {
93 eprintln!("Top panel: Finished resizing");
94 })
95 .with_bounds_callback(Box::new(|window_size| {
96 let min_height = 100.0;
97 let max_height = window_size.y() * 0.5;
98 (min_height, max_height.max(min_height))
99 }))
100 .finish(),
101 )
102 .finish();
103 
104 main_column.add_child(top_panel);
105 
106 // Create the row with CrossAxisAlignment::Stretch
107 let mut main_row = Flex::row().with_cross_axis_alignment(CrossAxisAlignment::Stretch);
108 
109 // Left panel with right-side dragbar - added directly to the row
110 let left_panel = Container::new(
111 Resizable::new(
112 self.left_panel_state.clone(),
113 self.make_panel_content(
114 "Left Panel\n(Drag right edge)".to_string(),
115 ColorU::new(100, 100, 200, 255),
116 ),
117 )
118 .with_dragbar_side(DragBarSide::Right)
119 .with_dragbar_color(strato_ui::elements::Fill::Solid(ColorU::new(
120 255, 255, 0, 200,
121 )))
122 .on_resize(move |ctx, _| {
123 ctx.notify();
124 })
125 .on_start_resizing(|_, _| {
126 eprintln!("Left panel: Started resizing");
127 })
128 .on_end_resizing(|_, _| {
129 eprintln!("Left panel: Finished resizing");
130 })
131 .with_bounds_callback(Box::new(|window_size| {
132 let min_width = 150.0;
133 let max_width = window_size.x() * 0.6;
134 (min_width, max_width.max(min_width))
135 }))
136 .finish(),
137 )
138 .finish();
139 
140 main_row.add_child(left_panel);
141 
142 // Right content area - wrapped in Shrinkable to fill remaining space
143 let right_content = Container::new(
144 Flex::column()
145 .with_main_axis_alignment(MainAxisAlignment::Center)
146 .with_main_axis_size(MainAxisSize::Max)
147 .with_cross_axis_alignment(CrossAxisAlignment::Stretch)
148 .with_spacing(20.)
149 .with_child(
150 Text::new_inline("Resizable Example", self.font_family, 24.)
151 .with_color(ColorU::white())
152 .finish(),
153 )
154 .with_child(self.make_info_text("Yellow bar: Horizontal resize (left)".to_string()))
155 .with_child(self.make_info_text("Cyan bar: Vertical resize (top)".to_string()))
156 .with_child(self.make_info_text("Check terminal for events".to_string()))
157 .finish(),
158 )
159 .with_background_color(ColorU::new(50, 50, 50, 255))
160 .with_uniform_padding(20.)
161 .finish();
162 
163 main_row.add_child(Shrinkable::new(1.0, right_content).finish());
164 
165 main_column.add_child(Shrinkable::new(1.0, main_row.finish()).finish());
166 
167 // Main layout
168 Stack::new()
169 .with_child(
170 Rect::new()
171 .with_background_color(ColorU::new(30, 30, 30, 255))
172 .finish(),
173 )
174 .with_child(Shrinkable::new(1.0, main_column.finish()).finish())
175 .finish()
176 }
177}
178 
179impl TypedActionView for RootView {
180 type Action = ();
181}
182