button_icon.rs

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