1use gpui_kit::{
2 App, ElementId, Entity, FontWeight, InteractiveElement as _, IntoElement, ParentElement as _,
3 RenderOnce, SharedString, StatefulInteractiveElement as _, StyleRefinement, Styled,
4 TestSupportExt as _, Window,
5 base::{
6 Disableable, StyledExt as _,
7 input::{InputBaseState, InputModeKind},
8 },
9 div,
10 prelude::FluentBuilder as _,
11};
12
13use crate::ActiveTheme as _;
14
15type FocusField = Box<dyn Fn(&mut Window, &mut App)>;
16
17#[derive(IntoElement)]
32#[non_exhaustive]
33pub struct Label {
34 id: ElementId,
35 text: SharedString,
36 style: StyleRefinement,
37 disabled: bool,
38 focus_field: Option<FocusField>,
39}
40
41impl Label {
42 pub fn new(id: impl Into<ElementId>, text: impl Into<SharedString>) -> Self {
44 Self {
45 id: id.into(),
46 text: text.into(),
47 style: StyleRefinement::default(),
48 disabled: false,
49 focus_field: None,
50 }
51 }
52
53 pub fn for_field<M: InputModeKind>(mut self, state: &Entity<InputBaseState<M>>) -> Self {
55 let state = state.clone();
56 self.focus_field = Some(Box::new(move |window, cx| {
57 state.update(cx, |state, cx| state.focus(window, cx));
58 }));
59 self
60 }
61}
62
63impl Disableable for Label {
64 fn disabled(mut self, disabled: bool) -> Self {
65 self.disabled = disabled;
66 self
67 }
68}
69
70impl Styled for Label {
71 fn style(&mut self) -> &mut StyleRefinement {
72 &mut self.style
73 }
74}
75
76impl RenderOnce for Label {
77 fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
78 let (text, color) = {
79 let theme = cx.theme();
80 let color = theme.foreground();
81 (
82 theme.text_control,
83 if self.disabled {
84 color.opacity(theme.disabled_opacity)
85 } else {
86 color
87 },
88 )
89 };
90 div()
91 .id(self.id)
92 .test_support()
93 .text_size(text.size)
94 .line_height(text.line_height)
95 .font_weight(FontWeight::MEDIUM)
96 .text_color(color)
97 .cursor_default()
98 .when_some(
99 self.focus_field.filter(|_| !self.disabled),
100 |this, focus_field| this.on_click(move |_, window, cx| focus_field(window, cx)),
101 )
102 .refine_style(&self.style)
103 .child(self.text)
104 }
105}