Implement Tinted buttons and selected_style for buttons
This commit is contained in:
parent
e5af1cb9a2
commit
9d4d58a915
6 changed files with 88 additions and 12 deletions
|
@ -92,6 +92,13 @@ impl Selectable for Button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SelectableButton for Button {
|
||||||
|
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||||
|
self.base = self.base.selected_style(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Disableable for Button {
|
impl Disableable for Button {
|
||||||
fn disabled(mut self, disabled: bool) -> Self {
|
fn disabled(mut self, disabled: bool) -> Self {
|
||||||
self.base = self.base.disabled(disabled);
|
self.base = self.base.disabled(disabled);
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub(super) struct ButtonIcon {
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
selected_icon: Option<Icon>,
|
selected_icon: Option<Icon>,
|
||||||
|
selected_style: Option<ButtonStyle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ButtonIcon {
|
impl ButtonIcon {
|
||||||
|
@ -23,6 +24,7 @@ impl ButtonIcon {
|
||||||
disabled: false,
|
disabled: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
selected_icon: None,
|
selected_icon: None,
|
||||||
|
selected_style: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +64,13 @@ impl Selectable for ButtonIcon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SelectableButton for ButtonIcon {
|
||||||
|
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||||
|
self.selected_style = Some(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RenderOnce for ButtonIcon {
|
impl RenderOnce for ButtonIcon {
|
||||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||||
let icon = self
|
let icon = self
|
||||||
|
@ -71,6 +80,8 @@ impl RenderOnce for ButtonIcon {
|
||||||
|
|
||||||
let icon_color = if self.disabled {
|
let icon_color = if self.disabled {
|
||||||
Color::Disabled
|
Color::Disabled
|
||||||
|
} else if self.selected_style.is_some() && self.selected {
|
||||||
|
self.selected_style.unwrap().into()
|
||||||
} else if self.selected {
|
} else if self.selected {
|
||||||
Color::Selected
|
Color::Selected
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,6 +4,10 @@ use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub trait SelectableButton: Selectable {
|
||||||
|
fn selected_style(self, style: ButtonStyle) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ButtonCommon: Clickable + Disableable {
|
pub trait ButtonCommon: Clickable + Disableable {
|
||||||
/// A unique element ID to identify the button.
|
/// A unique element ID to identify the button.
|
||||||
fn id(&self) -> &ElementId;
|
fn id(&self) -> &ElementId;
|
||||||
|
@ -41,7 +45,6 @@ pub enum TintColor {
|
||||||
#[default]
|
#[default]
|
||||||
Accent,
|
Accent,
|
||||||
Negative,
|
Negative,
|
||||||
Positive,
|
|
||||||
Warning,
|
Warning,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,13 +57,38 @@ impl TintColor {
|
||||||
label_color: cx.theme().colors().text,
|
label_color: cx.theme().colors().text,
|
||||||
icon_color: cx.theme().colors().text,
|
icon_color: cx.theme().colors().text,
|
||||||
},
|
},
|
||||||
// TODO: Finish tint colors.
|
TintColor::Negative => ButtonLikeStyles {
|
||||||
_ => ButtonLikeStyles {
|
background: cx.theme().status().error_background,
|
||||||
background: gpui::red(),
|
border_color: cx.theme().status().error_border,
|
||||||
border_color: gpui::red(),
|
label_color: cx.theme().colors().text,
|
||||||
label_color: gpui::red(),
|
icon_color: cx.theme().colors().text,
|
||||||
icon_color: gpui::red(),
|
|
||||||
},
|
},
|
||||||
|
TintColor::Warning => ButtonLikeStyles {
|
||||||
|
background: cx.theme().status().warning_background,
|
||||||
|
border_color: cx.theme().status().warning_border,
|
||||||
|
label_color: cx.theme().colors().text,
|
||||||
|
icon_color: cx.theme().colors().text,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TintColor> for Color {
|
||||||
|
fn from(tint: TintColor) -> Self {
|
||||||
|
match tint {
|
||||||
|
TintColor::Accent => Color::Accent,
|
||||||
|
TintColor::Negative => Color::Error,
|
||||||
|
TintColor::Warning => Color::Warning,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to go from ButtonStyle -> Color through tint colors.
|
||||||
|
impl From<ButtonStyle> for Color {
|
||||||
|
fn from(style: ButtonStyle) -> Self {
|
||||||
|
match style {
|
||||||
|
ButtonStyle::Tinted(tint) => tint.into(),
|
||||||
|
_ => Color::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,6 +294,7 @@ pub struct ButtonLike {
|
||||||
pub(super) style: ButtonStyle,
|
pub(super) style: ButtonStyle,
|
||||||
pub(super) disabled: bool,
|
pub(super) disabled: bool,
|
||||||
pub(super) selected: bool,
|
pub(super) selected: bool,
|
||||||
|
pub(super) selected_style: Option<ButtonStyle>,
|
||||||
pub(super) width: Option<DefiniteLength>,
|
pub(super) width: Option<DefiniteLength>,
|
||||||
size: ButtonSize,
|
size: ButtonSize,
|
||||||
rounding: Option<ButtonLikeRounding>,
|
rounding: Option<ButtonLikeRounding>,
|
||||||
|
@ -282,6 +311,7 @@ impl ButtonLike {
|
||||||
style: ButtonStyle::default(),
|
style: ButtonStyle::default(),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
|
selected_style: None,
|
||||||
width: None,
|
width: None,
|
||||||
size: ButtonSize::Default,
|
size: ButtonSize::Default,
|
||||||
rounding: Some(ButtonLikeRounding::All),
|
rounding: Some(ButtonLikeRounding::All),
|
||||||
|
@ -311,6 +341,13 @@ impl Selectable for ButtonLike {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SelectableButton for ButtonLike {
|
||||||
|
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||||
|
self.selected_style = Some(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clickable for ButtonLike {
|
impl Clickable for ButtonLike {
|
||||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||||
self.on_click = Some(Box::new(handler));
|
self.on_click = Some(Box::new(handler));
|
||||||
|
@ -366,6 +403,11 @@ impl ParentElement for ButtonLike {
|
||||||
|
|
||||||
impl RenderOnce for ButtonLike {
|
impl RenderOnce for ButtonLike {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||||
|
let style = self
|
||||||
|
.selected_style
|
||||||
|
.filter(|_| self.selected)
|
||||||
|
.unwrap_or(self.style);
|
||||||
|
|
||||||
self.base
|
self.base
|
||||||
.h_flex()
|
.h_flex()
|
||||||
.id(self.id.clone())
|
.id(self.id.clone())
|
||||||
|
@ -384,12 +426,12 @@ impl RenderOnce for ButtonLike {
|
||||||
ButtonSize::Default | ButtonSize::Compact => this.px_1(),
|
ButtonSize::Default | ButtonSize::Compact => this.px_1(),
|
||||||
ButtonSize::None => this,
|
ButtonSize::None => this,
|
||||||
})
|
})
|
||||||
.bg(self.style.enabled(cx).background)
|
.bg(style.enabled(cx).background)
|
||||||
.when(self.disabled, |this| this.cursor_not_allowed())
|
.when(self.disabled, |this| this.cursor_not_allowed())
|
||||||
.when(!self.disabled, |this| {
|
.when(!self.disabled, |this| {
|
||||||
this.cursor_pointer()
|
this.cursor_pointer()
|
||||||
.hover(|hover| hover.bg(self.style.hovered(cx).background))
|
.hover(|hover| hover.bg(style.hovered(cx).background))
|
||||||
.active(|active| active.bg(self.style.active(cx).background))
|
.active(|active| active.bg(style.active(cx).background))
|
||||||
})
|
})
|
||||||
.when_some(
|
.when_some(
|
||||||
self.on_click.filter(|_| !self.disabled),
|
self.on_click.filter(|_| !self.disabled),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use gpui::{AnyView, DefiniteLength};
|
use gpui::{AnyView, DefiniteLength};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::{prelude::*, SelectableButton};
|
||||||
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize};
|
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize};
|
||||||
|
|
||||||
use super::button_icon::ButtonIcon;
|
use super::button_icon::ButtonIcon;
|
||||||
|
@ -55,6 +55,13 @@ impl Selectable for IconButton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SelectableButton for IconButton {
|
||||||
|
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||||
|
self.base = self.base.selected_style(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clickable for IconButton {
|
impl Clickable for IconButton {
|
||||||
fn on_click(
|
fn on_click(
|
||||||
mut self,
|
mut self,
|
||||||
|
@ -109,12 +116,14 @@ impl RenderOnce for IconButton {
|
||||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||||
let is_disabled = self.base.disabled;
|
let is_disabled = self.base.disabled;
|
||||||
let is_selected = self.base.selected;
|
let is_selected = self.base.selected;
|
||||||
|
let selected_style = self.base.selected_style;
|
||||||
|
|
||||||
self.base.child(
|
self.base.child(
|
||||||
ButtonIcon::new(self.icon)
|
ButtonIcon::new(self.icon)
|
||||||
.disabled(is_disabled)
|
.disabled(is_disabled)
|
||||||
.selected(is_selected)
|
.selected(is_selected)
|
||||||
.selected_icon(self.selected_icon)
|
.selected_icon(self.selected_icon)
|
||||||
|
.when_some(selected_style, |this, style| this.selected_style(style))
|
||||||
.size(self.icon_size)
|
.size(self.icon_size)
|
||||||
.color(self.icon_color),
|
.color(self.icon_color),
|
||||||
)
|
)
|
||||||
|
|
|
@ -63,6 +63,13 @@ impl Selectable for ToggleButton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SelectableButton for ToggleButton {
|
||||||
|
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||||
|
self.base.selected_style = Some(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Disableable for ToggleButton {
|
impl Disableable for ToggleButton {
|
||||||
fn disabled(mut self, disabled: bool) -> Self {
|
fn disabled(mut self, disabled: bool) -> Self {
|
||||||
self.base = self.base.disabled(disabled);
|
self.base = self.base.disabled(disabled);
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub use crate::selectable::*;
|
||||||
pub use crate::styles::{vh, vw};
|
pub use crate::styles::{vh, vw};
|
||||||
pub use crate::visible_on_hover::*;
|
pub use crate::visible_on_hover::*;
|
||||||
pub use crate::{h_stack, v_stack};
|
pub use crate::{h_stack, v_stack};
|
||||||
pub use crate::{Button, ButtonSize, ButtonStyle, IconButton};
|
pub use crate::{Button, ButtonSize, ButtonStyle, IconButton, SelectableButton};
|
||||||
pub use crate::{ButtonCommon, Color, StyledExt};
|
pub use crate::{ButtonCommon, Color, StyledExt};
|
||||||
pub use crate::{Icon, IconElement, IconPosition, IconSize};
|
pub use crate::{Icon, IconElement, IconPosition, IconSize};
|
||||||
pub use crate::{Label, LabelCommon, LabelSize, LineHeightStyle};
|
pub use crate::{Label, LabelCommon, LabelSize, LineHeightStyle};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue