1//! `EditorInfo` โ a read-only View over an `ExampleEditor` entity.
2//!
3//! Demonstrates zero-wiring reactivity: just return the entity from `entity()`,
4//! read from it in `render()`, and caching + invalidation happen automatically.
5//! No observers, no subscriptions, no manual `cx.notify()`.
6
7use gpui::{App, Entity, IntoViewElement, Window, div, hsla, prelude::*, px};
8
9use crate::example_editor::ExampleEditor;
10use crate::example_render_log::RenderLog;
11
12#[derive(Hash, IntoViewElement)]
13pub struct EditorInfo {
14 editor: Entity<ExampleEditor>,
15 render_log: Entity<RenderLog>,
16}
17
18impl EditorInfo {
19 pub fn new(editor: Entity<ExampleEditor>, render_log: Entity<RenderLog>) -> Self {
20 Self { editor, render_log }
21 }
22}
23
24impl gpui::View for EditorInfo {
25 type Entity = ExampleEditor;
26
27 fn entity(&self) -> Option<Entity<ExampleEditor>> {
28 Some(self.editor.clone())
29 }
30
31 fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
32 self.render_log.update(cx, |log, _cx| log.log("EditorInfo"));
33
34 let editor = self.editor.read(cx);
35 let char_count = editor.content.len();
36 let cursor = editor.cursor;
37 let is_focused = editor.focus_handle.is_focused(window);
38
39 div()
40 .flex()
41 .gap(px(8.))
42 .text_xs()
43 .text_color(hsla(0., 0., 0.45, 1.))
44 .child(format!("{char_count} chars"))
45 .child("ยท")
46 .child(format!("cursor {cursor}"))
47 .child("ยท")
48 .child(if is_focused { "focused" } else { "unfocused" })
49 }
50}