StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.
| 1 | use strato_ui::elements::{Expanded, Shrinkable}; |
| 2 | use strato_ui::fonts::FamilyId; |
| 3 | use strato_ui::SingletonEntity as _; |
| 4 | use strato_ui::{ |
| 5 | elements::{ |
| 6 | Border, ConstrainedBox, Container, Flex, MainAxisAlignment, MainAxisSize, ParentElement, |
| 7 | Rect, Stack, Text, |
| 8 | }, |
| 9 | AppContext, Element, Entity, TypedActionView, View, ViewContext, |
| 10 | }; |
| 11 | |
| 12 | use strato_ui::color::ColorU; |
| 13 | |
| 14 | pub struct RootView { |
| 15 | font_family: FamilyId, |
| 16 | } |
| 17 | |
| 18 | impl RootView { |
| 19 | pub fn new(ctx: &mut ViewContext<Self>) -> Self { |
| 20 | let font_family = strato_ui::fonts::Cache::handle(ctx) |
| 21 | .update(ctx, |cache, _| cache.load_system_font("Arial").unwrap()); |
| 22 | RootView { font_family } |
| 23 | } |
| 24 | |
| 25 | fn make_label(&self, label: String) -> Box<dyn Element> { |
| 26 | Flex::row() |
| 27 | .with_child(Text::new_inline(label, self.font_family, 16.).finish()) |
| 28 | .finish() |
| 29 | } |
| 30 | |
| 31 | fn make_expanded_row(&self) -> Flex { |
| 32 | Flex::row() |
| 33 | .with_child( |
| 34 | Container::new( |
| 35 | ConstrainedBox::new( |
| 36 | Text::new_inline("Fixed 100", self.font_family, 16.).finish(), |
| 37 | ) |
| 38 | .with_width(100.) |
| 39 | .with_height(50.) |
| 40 | .finish(), |
| 41 | ) |
| 42 | .with_background_color(ColorU::new(255, 0, 0, 255)) |
| 43 | .finish(), |
| 44 | ) |
| 45 | .with_child( |
| 46 | Expanded::new( |
| 47 | 1.0, |
| 48 | Container::new( |
| 49 | ConstrainedBox::new( |
| 50 | Text::new_inline("Max Width 500, Min 200", self.font_family, 16.) |
| 51 | .finish(), |
| 52 | ) |
| 53 | .with_max_width(500.) |
| 54 | .with_min_width(200.) |
| 55 | .with_height(50.) |
| 56 | .finish(), |
| 57 | ) |
| 58 | .with_background_color(ColorU::new(0, 150, 0, 255)) |
| 59 | .finish(), |
| 60 | ) |
| 61 | .finish(), |
| 62 | ) |
| 63 | .with_child( |
| 64 | Container::new( |
| 65 | ConstrainedBox::new( |
| 66 | Text::new_inline("Fixed 100", self.font_family, 16.).finish(), |
| 67 | ) |
| 68 | .with_width(100.) |
| 69 | .with_height(50.) |
| 70 | .finish(), |
| 71 | ) |
| 72 | .with_background_color(ColorU::new(0, 0, 255, 255)) |
| 73 | .finish(), |
| 74 | ) |
| 75 | .with_main_axis_size(MainAxisSize::Max) |
| 76 | } |
| 77 | |
| 78 | fn make_shrinkable_row(&self) -> Flex { |
| 79 | Flex::row() |
| 80 | .with_child( |
| 81 | Container::new( |
| 82 | ConstrainedBox::new( |
| 83 | Text::new_inline("Fixed 100", self.font_family, 16.).finish(), |
| 84 | ) |
| 85 | .with_width(100.) |
| 86 | .with_height(50.) |
| 87 | .finish(), |
| 88 | ) |
| 89 | .with_background_color(ColorU::new(255, 0, 0, 255)) |
| 90 | .finish(), |
| 91 | ) |
| 92 | .with_child( |
| 93 | Shrinkable::new( |
| 94 | 1.0, |
| 95 | Container::new( |
| 96 | ConstrainedBox::new( |
| 97 | Text::new_inline("Max Width 500, Min 200", self.font_family, 16.) |
| 98 | .finish(), |
| 99 | ) |
| 100 | .with_max_width(500.) |
| 101 | .with_min_width(200.) |
| 102 | .with_height(50.) |
| 103 | .finish(), |
| 104 | ) |
| 105 | .with_background_color(ColorU::new(0, 150, 0, 255)) |
| 106 | .finish(), |
| 107 | ) |
| 108 | .finish(), |
| 109 | ) |
| 110 | .with_child( |
| 111 | Container::new( |
| 112 | ConstrainedBox::new( |
| 113 | Text::new_inline("Fixed 100", self.font_family, 16.).finish(), |
| 114 | ) |
| 115 | .with_width(100.) |
| 116 | .with_height(50.) |
| 117 | .finish(), |
| 118 | ) |
| 119 | .with_background_color(ColorU::new(0, 0, 255, 255)) |
| 120 | .finish(), |
| 121 | ) |
| 122 | .with_main_axis_size(MainAxisSize::Max) |
| 123 | } |
| 124 | |
| 125 | fn make_multiple_expanded_row(&self) -> Flex { |
| 126 | Flex::row() |
| 127 | .with_child( |
| 128 | Expanded::new( |
| 129 | 3.0, |
| 130 | Container::new(Text::new_inline("Flex: 3.0", self.font_family, 16.).finish()) |
| 131 | .with_background_color(ColorU::new(255, 0, 0, 255)) |
| 132 | .finish(), |
| 133 | ) |
| 134 | .finish(), |
| 135 | ) |
| 136 | .with_child( |
| 137 | Expanded::new( |
| 138 | 1.0, |
| 139 | Container::new(Text::new_inline("Flex: 1.0", self.font_family, 16.).finish()) |
| 140 | .with_background_color(ColorU::new(0, 150, 0, 255)) |
| 141 | .finish(), |
| 142 | ) |
| 143 | .finish(), |
| 144 | ) |
| 145 | .with_child( |
| 146 | Expanded::new( |
| 147 | 2.0, |
| 148 | Container::new(Text::new_inline("Flex: 2.0", self.font_family, 16.).finish()) |
| 149 | .with_background_color(ColorU::new(0, 0, 255, 255)) |
| 150 | .finish(), |
| 151 | ) |
| 152 | .finish(), |
| 153 | ) |
| 154 | .with_main_axis_size(MainAxisSize::Max) |
| 155 | } |
| 156 | |
| 157 | fn make_multiple_expanded_with_constraints_row(&self) -> Flex { |
| 158 | Flex::row() |
| 159 | .with_child( |
| 160 | Expanded::new( |
| 161 | 1.0, |
| 162 | Container::new( |
| 163 | ConstrainedBox::new( |
| 164 | Text::new_inline("Min 100, Max 200", self.font_family, 16.).finish(), |
| 165 | ) |
| 166 | .with_max_width(200.) |
| 167 | .with_min_width(100.) |
| 168 | .with_height(50.) |
| 169 | .finish(), |
| 170 | ) |
| 171 | .with_background_color(ColorU::new(255, 0, 0, 255)) |
| 172 | .finish(), |
| 173 | ) |
| 174 | .finish(), |
| 175 | ) |
| 176 | .with_child( |
| 177 | Expanded::new( |
| 178 | 1.0, |
| 179 | Container::new( |
| 180 | ConstrainedBox::new( |
| 181 | Text::new_inline("Min 100, Max 200", self.font_family, 16.).finish(), |
| 182 | ) |
| 183 | .with_max_width(200.) |
| 184 | .with_min_width(100.) |
| 185 | .with_height(50.) |
| 186 | .finish(), |
| 187 | ) |
| 188 | .with_background_color(ColorU::new(0, 150, 0, 255)) |
| 189 | .finish(), |
| 190 | ) |
| 191 | .finish(), |
| 192 | ) |
| 193 | .with_child( |
| 194 | Expanded::new( |
| 195 | 1.0, |
| 196 | Container::new( |
| 197 | ConstrainedBox::new( |
| 198 | Text::new_inline("Min 100, Max 200", self.font_family, 16.).finish(), |
| 199 | ) |
| 200 | .with_max_width(200.) |
| 201 | .with_min_width(100.) |
| 202 | .finish(), |
| 203 | ) |
| 204 | .with_background_color(ColorU::new(0, 0, 255, 255)) |
| 205 | .finish(), |
| 206 | ) |
| 207 | .finish(), |
| 208 | ) |
| 209 | .with_main_axis_size(MainAxisSize::Min) |
| 210 | } |
| 211 | |
| 212 | fn make_multiple_expanded_with_constraints_varying_flex_row(&self) -> Flex { |
| 213 | Flex::row() |
| 214 | .with_child( |
| 215 | Expanded::new( |
| 216 | 3.0, |
| 217 | Container::new( |
| 218 | ConstrainedBox::new( |
| 219 | Text::new_inline("Min 100, Max 200, Flex: 3.0", self.font_family, 16.) |
| 220 | .finish(), |
| 221 | ) |
| 222 | .with_max_width(200.) |
| 223 | .with_min_width(100.) |
| 224 | .with_height(50.) |
| 225 | .finish(), |
| 226 | ) |
| 227 | .with_background_color(ColorU::new(255, 0, 0, 255)) |
| 228 | .finish(), |
| 229 | ) |
| 230 | .finish(), |
| 231 | ) |
| 232 | .with_child( |
| 233 | Expanded::new( |
| 234 | 1.0, |
| 235 | Container::new( |
| 236 | ConstrainedBox::new( |
| 237 | Text::new_inline("Min 100, Max 200, Flex: 1.0", self.font_family, 16.) |
| 238 | .finish(), |
| 239 | ) |
| 240 | .with_max_width(200.) |
| 241 | .with_min_width(100.) |
| 242 | .with_height(50.) |
| 243 | .finish(), |
| 244 | ) |
| 245 | .with_background_color(ColorU::new(0, 150, 0, 255)) |
| 246 | .finish(), |
| 247 | ) |
| 248 | .finish(), |
| 249 | ) |
| 250 | .with_child( |
| 251 | Expanded::new( |
| 252 | 2.0, |
| 253 | Container::new( |
| 254 | ConstrainedBox::new( |
| 255 | Text::new_inline("Min 100, Max 200, Flex: 2.0", self.font_family, 16.) |
| 256 | .finish(), |
| 257 | ) |
| 258 | .with_max_width(200.) |
| 259 | .with_min_width(100.) |
| 260 | .finish(), |
| 261 | ) |
| 262 | .with_background_color(ColorU::new(0, 0, 255, 255)) |
| 263 | .finish(), |
| 264 | ) |
| 265 | .finish(), |
| 266 | ) |
| 267 | .with_main_axis_size(MainAxisSize::Min) |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | impl Entity for RootView { |
| 272 | type Event = (); |
| 273 | } |
| 274 | impl View for RootView { |
| 275 | fn ui_name() -> &'static str { |
| 276 | "RootView" |
| 277 | } |
| 278 | |
| 279 | // Let's render a simple black rect background. |
| 280 | fn render(&self, _: &AppContext) -> Box<dyn Element> { |
| 281 | let row_expanded = Container::new( |
| 282 | self.make_expanded_row() |
| 283 | .with_main_axis_alignment(MainAxisAlignment::Start) |
| 284 | .finish(), |
| 285 | ) |
| 286 | .with_border(Border::all(2.).with_border_color(ColorU::white())) |
| 287 | .finish(); |
| 288 | let row_shrinkable = Container::new( |
| 289 | self.make_shrinkable_row() |
| 290 | .with_main_axis_alignment(MainAxisAlignment::Start) |
| 291 | .finish(), |
| 292 | ) |
| 293 | .with_margin_bottom(32.) |
| 294 | .with_border(Border::all(2.).with_border_color(ColorU::white())) |
| 295 | .finish(); |
| 296 | |
| 297 | let multiple_expanded_row = Container::new( |
| 298 | self.make_multiple_expanded_row() |
| 299 | .with_main_axis_alignment(MainAxisAlignment::Start) |
| 300 | .finish(), |
| 301 | ) |
| 302 | .with_border(Border::all(2.).with_border_color(ColorU::white())) |
| 303 | .finish(); |
| 304 | |
| 305 | let multiple_expanded_with_constraints_row = Container::new( |
| 306 | self.make_multiple_expanded_with_constraints_row() |
| 307 | .with_main_axis_alignment(MainAxisAlignment::Start) |
| 308 | .finish(), |
| 309 | ) |
| 310 | .with_border(Border::all(2.).with_border_color(ColorU::white())) |
| 311 | .finish(); |
| 312 | |
| 313 | let multiple_expanded_with_constraints_varying_flex_row = Container::new( |
| 314 | self.make_multiple_expanded_with_constraints_varying_flex_row() |
| 315 | .with_main_axis_alignment(MainAxisAlignment::Start) |
| 316 | .finish(), |
| 317 | ) |
| 318 | .with_border(Border::all(2.).with_border_color(ColorU::white())) |
| 319 | .finish(); |
| 320 | |
| 321 | Stack::new() |
| 322 | .with_child(Rect::new().with_background_color(ColorU::black()).finish()) |
| 323 | .with_child( |
| 324 | Container::new( |
| 325 | Flex::column() |
| 326 | .with_child(self.make_label("Expanded - FlexFit::Tight".to_owned())) |
| 327 | .with_child(row_expanded) |
| 328 | .with_child( |
| 329 | self.make_label( |
| 330 | "Shrinkable (Old Expanded) - FlexFit::Loose ".to_owned(), |
| 331 | ), |
| 332 | ) |
| 333 | .with_child(row_shrinkable) |
| 334 | .with_child(self.make_label("Multiple Expanded with varying flex amounts".to_owned())) |
| 335 | .with_child(multiple_expanded_row) |
| 336 | .with_child(self.make_label("Multiple Expanded with constraints in Flex with MainAxisSize::Min".to_owned())) |
| 337 | .with_child(multiple_expanded_with_constraints_row) |
| 338 | .with_child(self.make_label("Multiple Expanded with constraints and varying flex amounts in Flex with MainAxisSize::Min".to_owned())) |
| 339 | .with_child(self.make_label("Note that this results in children beginning to shrink at different times and rates".to_owned())) |
| 340 | .with_child(multiple_expanded_with_constraints_varying_flex_row) |
| 341 | .finish(), |
| 342 | ) |
| 343 | .with_margin_top(32.) |
| 344 | .finish(), |
| 345 | ) |
| 346 | .finish() |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | impl TypedActionView for RootView { |
| 351 | type Action = (); |
| 352 | } |
| 353 |