agent_setup_button.rs

  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}