use crate::theme::{ActiveTheme, Themeable};
use crate::traits::disableable::Disableable;
use crate::traits::orientable::{Orientable, Orientation};
use gpui::{
div, rems, AnyElement, App, ElementId, InteractiveElement, IntoElement, ParentElement,
RenderOnce, Styled, Window,
};
pub fn button_group(id: impl Into<ElementId>) -> ButtonGroup {
ButtonGroup::new(id)
}
#[derive(IntoElement)]
pub struct ButtonGroup {
id: ElementId,
children: Vec<AnyElement>,
orientation: Orientation,
disabled: bool,
}
impl ButtonGroup {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
id: id.into(),
children: Vec::new(),
orientation: Orientation::Horizontal,
disabled: false,
}
}
pub fn child(mut self, child: impl IntoElement) -> Self {
self.children.push(child.into_any_element());
self
}
pub fn children(mut self, children: impl IntoIterator<Item = impl IntoElement>) -> Self {
self.children
.extend(children.into_iter().map(|c| c.into_any_element()));
self
}
}
impl RenderOnce for ButtonGroup {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let theme = cx.theme();
let child_count = self.children.len();
let is_horizontal = self.orientation == Orientation::Horizontal;
let mut container = div()
.id(self.id)
.flex()
.flex_none()
.overflow_hidden()
.border_1()
.border_color(theme.button_border())
.rounded(rems(0.25));
container = if is_horizontal {
container.flex_row()
} else {
container.flex_col()
};
if self.disabled {
container = container.opacity(0.65).cursor_not_allowed();
}
container.children(self.children.into_iter().enumerate().map(|(index, child)| {
let is_first = index == 0;
let is_last = index == child_count - 1;
let mut wrapper = div()
.flex()
.items_center()
.justify_center()
.bg(theme.button_bg())
.text_color(theme.fg());
if !is_last {
wrapper = if is_horizontal {
wrapper.border_r_1().border_color(theme.button_border())
} else {
wrapper.border_b_1().border_color(theme.button_border())
};
}
if is_horizontal {
if is_first {
wrapper = wrapper.rounded_l(rems(0.2));
}
if is_last {
wrapper = wrapper.rounded_r(rems(0.2));
}
} else {
if is_first {
wrapper = wrapper.rounded_t(rems(0.2));
}
if is_last {
wrapper = wrapper.rounded_b(rems(0.2));
}
}
wrapper.child(child)
}))
}
}
impl Orientable for ButtonGroup {
fn orientation(mut self, orientation: Orientation) -> Self {
self.orientation = orientation;
self
}
}
impl Disableable for ButtonGroup {
fn is_disabled(&self) -> bool {
self.disabled
}
fn disabled(mut self, disabled: bool) -> Self {
self.disabled = disabled;
self
}
}