button_icon.rs

  1#![allow(missing_docs)]
  2use crate::{prelude::*, Icon, IconName, IconSize, IconWithIndicator, Indicator};
  3use gpui::Hsla;
  4
  5/// An icon that appears within a button.
  6///
  7/// Can be used as either an icon alongside a label, like in [`Button`](crate::Button),
  8/// or as a standalone icon, like in [`IconButton`](crate::IconButton).
  9#[derive(IntoElement)]
 10pub(super) struct ButtonIcon {
 11    icon: IconName,
 12    size: IconSize,
 13    color: Color,
 14    disabled: bool,
 15    selected: bool,
 16    selected_icon: Option<IconName>,
 17    selected_icon_color: Option<Color>,
 18    selected_style: Option<ButtonStyle>,
 19    indicator: Option<Indicator>,
 20    indicator_border_color: Option<Hsla>,
 21}
 22
 23impl ButtonIcon {
 24    pub fn new(icon: IconName) -> Self {
 25        Self {
 26            icon,
 27            size: IconSize::default(),
 28            color: Color::default(),
 29            disabled: false,
 30            selected: false,
 31            selected_icon: None,
 32            selected_icon_color: None,
 33            selected_style: None,
 34            indicator: None,
 35            indicator_border_color: None,
 36        }
 37    }
 38
 39    pub fn size(mut self, size: impl Into<Option<IconSize>>) -> Self {
 40        if let Some(size) = size.into() {
 41            self.size = size;
 42        }
 43
 44        self
 45    }
 46
 47    pub fn color(mut self, color: impl Into<Option<Color>>) -> Self {
 48        if let Some(color) = color.into() {
 49            self.color = color;
 50        }
 51
 52        self
 53    }
 54
 55    pub fn selected_icon(mut self, icon: impl Into<Option<IconName>>) -> Self {
 56        self.selected_icon = icon.into();
 57        self
 58    }
 59
 60    pub fn selected_icon_color(mut self, color: impl Into<Option<Color>>) -> Self {
 61        self.selected_icon_color = color.into();
 62        self
 63    }
 64
 65    pub fn indicator(mut self, indicator: Indicator) -> Self {
 66        self.indicator = Some(indicator);
 67        self
 68    }
 69
 70    pub fn indicator_border_color(mut self, color: Option<Hsla>) -> Self {
 71        self.indicator_border_color = color;
 72        self
 73    }
 74}
 75
 76impl Disableable for ButtonIcon {
 77    fn disabled(mut self, disabled: bool) -> Self {
 78        self.disabled = disabled;
 79        self
 80    }
 81}
 82
 83impl Toggleable for ButtonIcon {
 84    fn toggle_state(mut self, selected: bool) -> Self {
 85        self.selected = selected;
 86        self
 87    }
 88}
 89
 90impl SelectableButton for ButtonIcon {
 91    fn selected_style(mut self, style: ButtonStyle) -> Self {
 92        self.selected_style = Some(style);
 93        self
 94    }
 95}
 96
 97impl RenderOnce for ButtonIcon {
 98    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
 99        let icon = self
100            .selected_icon
101            .filter(|_| self.selected)
102            .unwrap_or(self.icon);
103
104        let icon_color = if self.disabled {
105            Color::Disabled
106        } else if self.selected_style.is_some() && self.selected {
107            self.selected_style.unwrap().into()
108        } else if self.selected {
109            self.selected_icon_color.unwrap_or(Color::Selected)
110        } else {
111            self.color
112        };
113
114        let icon = Icon::new(icon).size(self.size).color(icon_color);
115
116        match self.indicator {
117            Some(indicator) => IconWithIndicator::new(icon, Some(indicator))
118                .indicator_border_color(self.indicator_border_color)
119                .into_any_element(),
120            None => icon.into_any_element(),
121        }
122    }
123}