gpui: Add tree example (#34942)

Piotr Osiewicz created

This commit adds an example with deep children hierarchy.
The depth of a tree can be tweaked with GPUI_TREE_DEPTH env variable.
With depth=100
<img width="301" height="330" alt="image"
src="https://github.com/user-attachments/assets/844cd285-c5f3-4410-a74e-981bf093ba2e"
/>
With this example, I can trigger a stack overflow at depth=633 (and
higher).


Release Notes:

- N/A

Change summary

crates/gpui/Cargo.toml       |  4 +++
crates/gpui/examples/tree.rs | 46 ++++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+)

Detailed changes

crates/gpui/Cargo.toml 🔗

@@ -295,6 +295,10 @@ path = "examples/text.rs"
 name = "text_wrapper"
 path = "examples/text_wrapper.rs"
 
+[[example]]
+name = "tree"
+path = "examples/tree.rs"
+
 [[example]]
 name = "uniform_list"
 path = "examples/uniform_list.rs"

crates/gpui/examples/tree.rs 🔗

@@ -0,0 +1,46 @@
+//! Renders a div with deep children hierarchy. This example is useful to exemplify that Zed can
+//! handle deep hierarchies (even though it cannot just yet!).
+use std::sync::LazyLock;
+
+use gpui::{
+    App, Application, Bounds, Context, Window, WindowBounds, WindowOptions, div, prelude::*, px,
+    size,
+};
+
+struct Tree {}
+
+static DEPTH: LazyLock<u64> = LazyLock::new(|| {
+    std::env::var("GPUI_TREE_DEPTH")
+        .ok()
+        .and_then(|depth| depth.parse().ok())
+        .unwrap_or_else(|| 50)
+});
+
+impl Render for Tree {
+    fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
+        let mut depth = *DEPTH;
+        static COLORS: [gpui::Hsla; 4] = [gpui::red(), gpui::blue(), gpui::green(), gpui::yellow()];
+        let mut colors = COLORS.iter().cycle().copied();
+        let mut next_div = || div().p_0p5().bg(colors.next().unwrap());
+        let mut innermost_node = next_div();
+        while depth > 0 {
+            innermost_node = next_div().child(innermost_node);
+            depth -= 1;
+        }
+        innermost_node
+    }
+}
+
+fn main() {
+    Application::new().run(|cx: &mut App| {
+        let bounds = Bounds::centered(None, size(px(300.0), px(300.0)), cx);
+        cx.open_window(
+            WindowOptions {
+                window_bounds: Some(WindowBounds::Windowed(bounds)),
+                ..Default::default()
+            },
+            |_, cx| cx.new(|_| Tree {}),
+        )
+        .unwrap();
+    });
+}