Add button port example

This commit is contained in:
Mikayla 2023-11-19 19:11:51 -08:00
parent 88024ca7c9
commit f3eb1d4abf
No known key found for this signature in database

View file

@ -1,25 +1,27 @@
use std::sync::Arc; use std::sync::Arc;
use gpui::{DefiniteLength, Hsla, MouseButton, StatefulInteractiveComponent, WindowContext}; use gpui::{
CallbackHandle, DefiniteLength, Hsla, MouseButton, StatefulInteractiveComponent, WindowContext,
};
use crate::prelude::*; use crate::prelude::*;
use crate::{h_stack, Icon, IconButton, IconElement, Label, LineHeightStyle, TextColor}; use crate::{h_stack, Icon, IconButton, IconElement, Label, LineHeightStyle, TextColor};
/// Provides the flexibility to use either a standard /// Provides the flexibility to use either a standard
/// button or an icon button in a given context. /// button or an icon button in a given context.
pub enum ButtonOrIconButton<V: 'static> { pub enum ButtonOrIconButton {
Button(Button<V>), Button(Button),
IconButton(IconButton<V>), IconButton(IconButton),
} }
impl<V: 'static> From<Button<V>> for ButtonOrIconButton<V> { impl From<Button> for ButtonOrIconButton {
fn from(value: Button<V>) -> Self { fn from(value: Button) -> Self {
Self::Button(value) Self::Button(value)
} }
} }
impl<V: 'static> From<IconButton<V>> for ButtonOrIconButton<V> { impl From<IconButton> for ButtonOrIconButton {
fn from(value: IconButton<V>) -> Self { fn from(value: IconButton) -> Self {
Self::IconButton(value) Self::IconButton(value)
} }
} }
@ -61,25 +63,10 @@ impl ButtonVariant {
} }
} }
pub type ClickHandler<V> = Arc<dyn Fn(&mut V, &mut ViewContext<V>)>; // #[derive(Component)] <- todo
pub struct Button {
struct ButtonHandlers<V: 'static> {
click: Option<ClickHandler<V>>,
}
unsafe impl<S> Send for ButtonHandlers<S> {}
unsafe impl<S> Sync for ButtonHandlers<S> {}
impl<V: 'static> Default for ButtonHandlers<V> {
fn default() -> Self {
Self { click: None }
}
}
#[derive(Component)]
pub struct Button<V: 'static> {
disabled: bool, disabled: bool,
handlers: ButtonHandlers<V>, click_handler: Option<CallbackHandle<()>>,
icon: Option<Icon>, icon: Option<Icon>,
icon_position: Option<IconPosition>, icon_position: Option<IconPosition>,
label: SharedString, label: SharedString,
@ -88,11 +75,11 @@ pub struct Button<V: 'static> {
color: Option<TextColor>, color: Option<TextColor>,
} }
impl<V: 'static> Button<V> { impl Button {
pub fn new(label: impl Into<SharedString>) -> Self { pub fn new(label: impl Into<SharedString>) -> Self {
Self { Self {
disabled: false, disabled: false,
handlers: ButtonHandlers::default(), click_handler: None,
icon: None, icon: None,
icon_position: None, icon_position: None,
label: label.into(), label: label.into(),
@ -129,7 +116,7 @@ impl<V: 'static> Button<V> {
self self
} }
pub fn on_click(mut self, handler: ClickHandler<V>) -> Self { pub fn on_click(mut self, handler: CallbackHandle<()>) -> Self {
self.handlers.click = Some(handler); self.handlers.click = Some(handler);
self self
} }
@ -164,7 +151,7 @@ impl<V: 'static> Button<V> {
self.icon.map(|i| IconElement::new(i).color(icon_color)) self.icon.map(|i| IconElement::new(i).color(icon_color))
} }
pub fn render(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> { pub fn render(self, cx: &mut WindowContext) -> impl Component {
let (icon_color, label_color) = match (self.disabled, self.color) { let (icon_color, label_color) = match (self.disabled, self.color) {
(true, _) => (TextColor::Disabled, TextColor::Disabled), (true, _) => (TextColor::Disabled, TextColor::Disabled),
(_, None) => (TextColor::Default, TextColor::Default), (_, None) => (TextColor::Default, TextColor::Default),
@ -212,21 +199,20 @@ impl<V: 'static> Button<V> {
} }
} }
#[derive(Component)] pub struct ButtonGroup {
pub struct ButtonGroup<V: 'static> { buttons: Vec<Button>,
buttons: Vec<Button<V>>,
} }
impl<V: 'static> ButtonGroup<V> { impl ButtonGroup {
pub fn new(buttons: Vec<Button<V>>) -> Self { pub fn new(buttons: Vec<Button>) -> Self {
Self { buttons } Self { buttons }
} }
fn render(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> { fn render(self, cx: &mut WindowContext) -> impl Component {
let mut el = h_stack().text_ui(); let mut el = h_stack().text_ui();
for button in self.buttons { for button in self.buttons {
el = el.child(button.render(_view, cx)); el = el.child(button.render(cx));
} }
el el
@ -246,13 +232,13 @@ mod stories {
pub struct ButtonStory; pub struct ButtonStory;
impl Render for ButtonStory { impl Render for ButtonStory {
type Element = Div<Self>; type Element = Div;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let states = InteractionState::iter(); let states = InteractionState::iter();
Story::container(cx) Story::container(cx)
.child(Story::title_for::<_, Button<Self>>(cx)) .child(Story::title_for::<_, Button>(cx))
.child( .child(
div() div()
.flex() .flex()
@ -395,7 +381,7 @@ mod stories {
.child( .child(
Button::new("Label") Button::new("Label")
.variant(ButtonVariant::Ghost) .variant(ButtonVariant::Ghost)
.on_click(Arc::new(|_view, _cx| println!("Button clicked."))), .on_click(cx.callback(|_view, _, cx| println!("Button clicked."))),
) )
} }
} }