1use crate::prelude::*;
2use gpui::{ClickEvent, SharedString};
3
4#[derive(IntoElement, RegisterComponent)]
5pub struct AgentSetupButton {
6 id: ElementId,
7 icon: Option<Icon>,
8 name: Option<SharedString>,
9 state: Option<AnyElement>,
10 disabled: bool,
11 on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
12}
13
14impl AgentSetupButton {
15 pub fn new(id: impl Into<ElementId>) -> Self {
16 Self {
17 id: id.into(),
18 icon: None,
19 name: None,
20 state: None,
21 disabled: false,
22 on_click: None,
23 }
24 }
25
26 pub fn icon(mut self, icon: Icon) -> Self {
27 self.icon = Some(icon);
28 self
29 }
30
31 pub fn name(mut self, name: impl Into<SharedString>) -> Self {
32 self.name = Some(name.into());
33 self
34 }
35
36 pub fn state(mut self, element: impl IntoElement) -> Self {
37 self.state = Some(element.into_any_element());
38 self
39 }
40
41 pub fn disabled(mut self, disabled: bool) -> Self {
42 self.disabled = disabled;
43 self
44 }
45
46 pub fn on_click(
47 mut self,
48 handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
49 ) -> Self {
50 self.on_click = Some(Box::new(handler));
51 self
52 }
53}
54
55impl Component for AgentSetupButton {
56 fn scope() -> ComponentScope {
57 ComponentScope::Agent
58 }
59
60 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
61 None
62 }
63}
64
65impl RenderOnce for AgentSetupButton {
66 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
67 let is_clickable = !self.disabled && self.on_click.is_some();
68
69 let has_top_section = self.icon.is_some() || self.name.is_some();
70 let top_section = has_top_section.then(|| {
71 h_flex()
72 .p_1p5()
73 .gap_1()
74 .justify_center()
75 .when_some(self.icon, |this, icon| this.child(icon))
76 .when_some(self.name, |this, name| {
77 this.child(Label::new(name).size(LabelSize::Small))
78 })
79 });
80
81 let bottom_section = self.state.map(|state_element| {
82 h_flex()
83 .p_0p5()
84 .h_full()
85 .justify_center()
86 .border_t_1()
87 .border_color(cx.theme().colors().border_variant)
88 .bg(cx.theme().colors().element_background.opacity(0.5))
89 .child(state_element)
90 });
91
92 v_flex()
93 .id(self.id)
94 .border_1()
95 .border_color(cx.theme().colors().border_variant)
96 .rounded_sm()
97 .when(is_clickable, |this| {
98 this.cursor_pointer().hover(|style| {
99 style
100 .bg(cx.theme().colors().element_hover)
101 .border_color(cx.theme().colors().border)
102 })
103 })
104 .when_some(top_section, |this, section| this.child(section))
105 .when_some(bottom_section, |this, section| this.child(section))
106 .when_some(self.on_click.filter(|_| is_clickable), |this, on_click| {
107 this.on_click(on_click)
108 })
109 }
110}