2023-08-19 21:40:05 +00:00
|
|
|
use gpui::{elements::SafeStylable, Action};
|
2023-08-17 22:30:40 +00:00
|
|
|
|
|
|
|
use crate::{Interactive, Toggleable};
|
|
|
|
|
2023-08-19 12:18:53 +00:00
|
|
|
use self::{action_button::ButtonStyle, disclosure::Disclosable, svg::SvgStyle, toggle::Toggle};
|
2023-08-17 22:30:40 +00:00
|
|
|
|
2023-08-23 23:25:17 +00:00
|
|
|
pub type IconButtonStyle = Interactive<ButtonStyle<SvgStyle>>;
|
|
|
|
pub type ToggleIconButtonStyle = Toggleable<IconButtonStyle>;
|
2023-08-17 22:30:40 +00:00
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
pub trait ComponentExt<C: SafeStylable> {
|
2023-08-17 22:30:40 +00:00
|
|
|
fn toggleable(self, active: bool) -> Toggle<C, ()>;
|
2023-08-19 21:40:05 +00:00
|
|
|
fn disclosable(self, disclosed: Option<bool>, action: Box<dyn Action>) -> Disclosable<C, ()>;
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl<C: SafeStylable> ComponentExt<C> for C {
|
2023-08-17 22:30:40 +00:00
|
|
|
fn toggleable(self, active: bool) -> Toggle<C, ()> {
|
|
|
|
Toggle::new(self, active)
|
|
|
|
}
|
2023-08-19 12:18:53 +00:00
|
|
|
|
|
|
|
/// Some(True) => disclosed => content is visible
|
|
|
|
/// Some(false) => closed => content is hidden
|
2023-08-19 21:40:05 +00:00
|
|
|
/// None => No disclosure button, but reserve disclosure spacing
|
|
|
|
fn disclosable(self, disclosed: Option<bool>, action: Box<dyn Action>) -> Disclosable<C, ()> {
|
|
|
|
Disclosable::new(disclosed, self, action)
|
2023-08-19 12:18:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub mod disclosure {
|
|
|
|
use gpui::{
|
2023-08-23 23:25:17 +00:00
|
|
|
elements::{Component, ContainerStyle, Empty, Flex, ParentElement, SafeStylable},
|
2023-08-19 12:18:53 +00:00
|
|
|
Action, Element,
|
|
|
|
};
|
|
|
|
use schemars::JsonSchema;
|
|
|
|
use serde_derive::Deserialize;
|
|
|
|
|
2023-08-23 23:30:27 +00:00
|
|
|
use super::{action_button::Button, svg::Svg, IconButtonStyle};
|
2023-08-19 12:18:53 +00:00
|
|
|
|
|
|
|
#[derive(Clone, Default, Deserialize, JsonSchema)]
|
|
|
|
pub struct DisclosureStyle<S> {
|
2023-08-23 23:25:17 +00:00
|
|
|
pub button: IconButtonStyle,
|
|
|
|
#[serde(flatten)]
|
|
|
|
pub container: ContainerStyle,
|
2023-08-19 12:18:53 +00:00
|
|
|
pub spacing: f32,
|
|
|
|
#[serde(flatten)]
|
|
|
|
content: S,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S> DisclosureStyle<S> {
|
|
|
|
pub fn button_space(&self) -> f32 {
|
|
|
|
self.spacing + self.button.button_width.unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Disclosable<C, S> {
|
|
|
|
disclosed: Option<bool>,
|
|
|
|
action: Box<dyn Action>,
|
|
|
|
id: usize,
|
|
|
|
content: C,
|
|
|
|
style: S,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Disclosable<(), ()> {
|
|
|
|
pub fn new<C>(
|
|
|
|
disclosed: Option<bool>,
|
|
|
|
content: C,
|
|
|
|
action: Box<dyn Action>,
|
|
|
|
) -> Disclosable<C, ()> {
|
|
|
|
Disclosable {
|
|
|
|
disclosed,
|
|
|
|
content,
|
|
|
|
action,
|
2023-08-19 21:40:05 +00:00
|
|
|
id: 0,
|
2023-08-19 12:18:53 +00:00
|
|
|
style: (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl<C> Disclosable<C, ()> {
|
2023-08-19 23:29:24 +00:00
|
|
|
pub fn with_id(mut self, id: usize) -> Disclosable<C, ()> {
|
|
|
|
self.id = id;
|
|
|
|
self
|
2023-08-19 21:40:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C: SafeStylable> SafeStylable for Disclosable<C, ()> {
|
2023-08-19 12:18:53 +00:00
|
|
|
type Style = DisclosureStyle<C::Style>;
|
|
|
|
|
|
|
|
type Output = Disclosable<C, Self::Style>;
|
|
|
|
|
|
|
|
fn with_style(self, style: Self::Style) -> Self::Output {
|
|
|
|
Disclosable {
|
|
|
|
disclosed: self.disclosed,
|
|
|
|
action: self.action,
|
|
|
|
content: self.content,
|
|
|
|
id: self.id,
|
|
|
|
style,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl<C: SafeStylable> Component for Disclosable<C, DisclosureStyle<C::Style>> {
|
2023-08-23 23:30:27 +00:00
|
|
|
fn render<V: 'static>(self, cx: &mut gpui::ViewContext<V>) -> gpui::AnyElement<V> {
|
2023-08-19 12:18:53 +00:00
|
|
|
Flex::row()
|
2023-08-23 23:25:17 +00:00
|
|
|
.with_spacing(self.style.spacing)
|
2023-08-19 12:18:53 +00:00
|
|
|
.with_child(if let Some(disclosed) = self.disclosed {
|
2023-08-19 21:40:05 +00:00
|
|
|
Button::dynamic_action(self.action)
|
2023-08-19 12:18:53 +00:00
|
|
|
.with_id(self.id)
|
|
|
|
.with_contents(Svg::new(if disclosed {
|
|
|
|
"icons/file_icons/chevron_down.svg"
|
|
|
|
} else {
|
|
|
|
"icons/file_icons/chevron_right.svg"
|
|
|
|
}))
|
|
|
|
.with_style(self.style.button)
|
|
|
|
.element()
|
|
|
|
.into_any()
|
|
|
|
} else {
|
|
|
|
Empty::new()
|
|
|
|
.into_any()
|
|
|
|
.constrained()
|
|
|
|
// TODO: Why is this optional at all?
|
|
|
|
.with_width(self.style.button.button_width.unwrap())
|
|
|
|
.into_any()
|
|
|
|
})
|
|
|
|
.with_child(
|
|
|
|
self.content
|
|
|
|
.with_style(self.style.content)
|
2023-08-19 21:40:05 +00:00
|
|
|
.render(cx)
|
2023-08-19 12:18:53 +00:00
|
|
|
.flex(1., true),
|
|
|
|
)
|
|
|
|
.align_children_center()
|
2023-08-23 23:25:17 +00:00
|
|
|
.contained()
|
|
|
|
.with_style(self.style.container)
|
2023-08-19 12:18:53 +00:00
|
|
|
.into_any()
|
|
|
|
}
|
|
|
|
}
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub mod toggle {
|
2023-08-19 21:40:05 +00:00
|
|
|
use gpui::elements::{Component, SafeStylable};
|
2023-08-17 22:30:40 +00:00
|
|
|
|
|
|
|
use crate::Toggleable;
|
|
|
|
|
|
|
|
pub struct Toggle<C, S> {
|
|
|
|
style: S,
|
|
|
|
active: bool,
|
|
|
|
component: C,
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl<C: SafeStylable> Toggle<C, ()> {
|
2023-08-17 22:30:40 +00:00
|
|
|
pub fn new(component: C, active: bool) -> Self {
|
|
|
|
Toggle {
|
|
|
|
active,
|
|
|
|
component,
|
|
|
|
style: (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl<C: SafeStylable> SafeStylable for Toggle<C, ()> {
|
2023-08-17 22:30:40 +00:00
|
|
|
type Style = Toggleable<C::Style>;
|
|
|
|
|
|
|
|
type Output = Toggle<C, Self::Style>;
|
|
|
|
|
|
|
|
fn with_style(self, style: Self::Style) -> Self::Output {
|
|
|
|
Toggle {
|
|
|
|
active: self.active,
|
|
|
|
component: self.component,
|
|
|
|
style,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl<C: SafeStylable> Component for Toggle<C, Toggleable<C::Style>> {
|
2023-08-23 23:30:27 +00:00
|
|
|
fn render<V: 'static>(self, cx: &mut gpui::ViewContext<V>) -> gpui::AnyElement<V> {
|
2023-08-17 22:30:40 +00:00
|
|
|
self.component
|
|
|
|
.with_style(self.style.in_state(self.active).clone())
|
2023-08-19 21:40:05 +00:00
|
|
|
.render(cx)
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub mod action_button {
|
|
|
|
use std::borrow::Cow;
|
|
|
|
|
|
|
|
use gpui::{
|
2023-08-19 21:40:05 +00:00
|
|
|
elements::{Component, ContainerStyle, MouseEventHandler, SafeStylable, TooltipStyle},
|
2023-08-17 22:30:40 +00:00
|
|
|
platform::{CursorStyle, MouseButton},
|
2023-08-23 23:30:27 +00:00
|
|
|
Action, Element, TypeTag,
|
2023-08-17 22:30:40 +00:00
|
|
|
};
|
|
|
|
use schemars::JsonSchema;
|
|
|
|
use serde_derive::Deserialize;
|
|
|
|
|
|
|
|
use crate::Interactive;
|
|
|
|
|
2023-08-19 12:18:53 +00:00
|
|
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
|
|
|
pub struct ButtonStyle<C> {
|
|
|
|
#[serde(flatten)]
|
|
|
|
pub container: ContainerStyle,
|
|
|
|
// TODO: These are incorrect for the intended usage of the buttons.
|
|
|
|
// The size should be constant, but putting them here duplicates them
|
|
|
|
// across the states the buttons can be in
|
|
|
|
pub button_width: Option<f32>,
|
|
|
|
pub button_height: Option<f32>,
|
|
|
|
#[serde(flatten)]
|
|
|
|
contents: C,
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
pub struct Button<C, S> {
|
2023-08-17 22:30:40 +00:00
|
|
|
action: Box<dyn Action>,
|
2023-08-18 21:54:05 +00:00
|
|
|
tooltip: Option<(Cow<'static, str>, TooltipStyle)>,
|
2023-08-17 22:30:40 +00:00
|
|
|
tag: TypeTag,
|
2023-08-19 12:18:53 +00:00
|
|
|
id: usize,
|
2023-08-17 22:30:40 +00:00
|
|
|
contents: C,
|
|
|
|
style: Interactive<S>,
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl Button<(), ()> {
|
2023-08-19 23:29:24 +00:00
|
|
|
pub fn dynamic_action(action: Box<dyn Action>) -> Button<(), ()> {
|
2023-08-17 22:30:40 +00:00
|
|
|
Self {
|
|
|
|
contents: (),
|
|
|
|
tag: action.type_tag(),
|
2023-08-19 23:29:24 +00:00
|
|
|
action,
|
2023-08-17 22:30:40 +00:00
|
|
|
style: Interactive::new_blank(),
|
2023-08-18 21:54:05 +00:00
|
|
|
tooltip: None,
|
2023-08-19 12:18:53 +00:00
|
|
|
id: 0,
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
pub fn action<A: Action + Clone>(action: A) -> Self {
|
|
|
|
Self::dynamic_action(Box::new(action))
|
2023-08-18 21:54:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_tooltip(
|
|
|
|
mut self,
|
2023-08-17 22:30:40 +00:00
|
|
|
tooltip: impl Into<Cow<'static, str>>,
|
|
|
|
tooltip_style: TooltipStyle,
|
|
|
|
) -> Self {
|
2023-08-18 21:54:05 +00:00
|
|
|
self.tooltip = Some((tooltip.into(), tooltip_style));
|
|
|
|
self
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
|
2023-08-19 12:18:53 +00:00
|
|
|
pub fn with_id(mut self, id: usize) -> Self {
|
|
|
|
self.id = id;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
pub fn with_contents<C: SafeStylable>(self, contents: C) -> Button<C, ()> {
|
|
|
|
Button {
|
2023-08-17 22:30:40 +00:00
|
|
|
action: self.action,
|
|
|
|
tag: self.tag,
|
|
|
|
style: self.style,
|
|
|
|
tooltip: self.tooltip,
|
2023-08-19 12:18:53 +00:00
|
|
|
id: self.id,
|
2023-08-17 22:30:40 +00:00
|
|
|
contents,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl<C: SafeStylable> SafeStylable for Button<C, ()> {
|
2023-08-17 22:30:40 +00:00
|
|
|
type Style = Interactive<ButtonStyle<C::Style>>;
|
2023-08-19 21:40:05 +00:00
|
|
|
type Output = Button<C, ButtonStyle<C::Style>>;
|
2023-08-17 22:30:40 +00:00
|
|
|
|
|
|
|
fn with_style(self, style: Self::Style) -> Self::Output {
|
2023-08-19 21:40:05 +00:00
|
|
|
Button {
|
2023-08-17 22:30:40 +00:00
|
|
|
action: self.action,
|
|
|
|
tag: self.tag,
|
|
|
|
contents: self.contents,
|
|
|
|
tooltip: self.tooltip,
|
2023-08-19 12:18:53 +00:00
|
|
|
id: self.id,
|
2023-08-17 22:30:40 +00:00
|
|
|
style,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl<C: SafeStylable> Component for Button<C, ButtonStyle<C::Style>> {
|
2023-08-23 23:30:27 +00:00
|
|
|
fn render<V: 'static>(self, cx: &mut gpui::ViewContext<V>) -> gpui::AnyElement<V> {
|
2023-08-19 12:18:53 +00:00
|
|
|
let mut button = MouseEventHandler::new_dynamic(self.tag, self.id, cx, |state, cx| {
|
2023-08-17 22:30:40 +00:00
|
|
|
let style = self.style.style_for(state);
|
|
|
|
let mut contents = self
|
|
|
|
.contents
|
|
|
|
.with_style(style.contents.to_owned())
|
2023-08-19 21:40:05 +00:00
|
|
|
.render(cx)
|
2023-08-17 22:30:40 +00:00
|
|
|
.contained()
|
|
|
|
.with_style(style.container)
|
|
|
|
.constrained();
|
|
|
|
|
|
|
|
if let Some(height) = style.button_height {
|
|
|
|
contents = contents.with_height(height);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(width) = style.button_width {
|
|
|
|
contents = contents.with_width(width);
|
|
|
|
}
|
|
|
|
|
|
|
|
contents.into_any()
|
|
|
|
})
|
|
|
|
.on_click(MouseButton::Left, {
|
|
|
|
let action = self.action.boxed_clone();
|
|
|
|
move |_, _, cx| {
|
2023-08-19 12:18:53 +00:00
|
|
|
let window = cx.window();
|
|
|
|
let view = cx.view_id();
|
|
|
|
let action = action.boxed_clone();
|
|
|
|
cx.spawn(|_, mut cx| async move {
|
|
|
|
window.dispatch_action(view, action.as_ref(), &mut cx)
|
|
|
|
})
|
|
|
|
.detach();
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.with_cursor_style(CursorStyle::PointingHand)
|
2023-08-18 21:54:05 +00:00
|
|
|
.into_any();
|
|
|
|
|
|
|
|
if let Some((tooltip, style)) = self.tooltip {
|
|
|
|
button = button
|
|
|
|
.with_dynamic_tooltip(self.tag, 0, tooltip, Some(self.action), style, cx)
|
|
|
|
.into_any()
|
|
|
|
}
|
|
|
|
|
|
|
|
button
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub mod svg {
|
|
|
|
use std::borrow::Cow;
|
|
|
|
|
|
|
|
use gpui::{
|
2023-08-19 21:40:05 +00:00
|
|
|
elements::{Component, Empty, SafeStylable},
|
2023-08-17 22:30:40 +00:00
|
|
|
Element,
|
|
|
|
};
|
|
|
|
use schemars::JsonSchema;
|
|
|
|
use serde::Deserialize;
|
|
|
|
|
|
|
|
#[derive(Clone, Default, JsonSchema)]
|
|
|
|
pub struct SvgStyle {
|
|
|
|
icon_width: f32,
|
|
|
|
icon_height: f32,
|
|
|
|
color: gpui::color::Color,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'de> Deserialize<'de> for SvgStyle {
|
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
|
|
where
|
|
|
|
D: serde::Deserializer<'de>,
|
|
|
|
{
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
#[serde(untagged)]
|
|
|
|
pub enum IconSize {
|
|
|
|
IconSize { icon_size: f32 },
|
|
|
|
Dimensions { width: f32, height: f32 },
|
2023-08-19 12:18:53 +00:00
|
|
|
IconDimensions { icon_width: f32, icon_height: f32 },
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
struct SvgStyleHelper {
|
|
|
|
#[serde(flatten)]
|
|
|
|
size: IconSize,
|
|
|
|
color: gpui::color::Color,
|
|
|
|
}
|
|
|
|
|
|
|
|
let json = SvgStyleHelper::deserialize(deserializer)?;
|
|
|
|
let color = json.color;
|
|
|
|
|
|
|
|
let result = match json.size {
|
|
|
|
IconSize::IconSize { icon_size } => SvgStyle {
|
|
|
|
icon_width: icon_size,
|
|
|
|
icon_height: icon_size,
|
|
|
|
color,
|
|
|
|
},
|
|
|
|
IconSize::Dimensions { width, height } => SvgStyle {
|
|
|
|
icon_width: width,
|
|
|
|
icon_height: height,
|
|
|
|
color,
|
|
|
|
},
|
2023-08-19 12:18:53 +00:00
|
|
|
IconSize::IconDimensions {
|
|
|
|
icon_width,
|
|
|
|
icon_height,
|
|
|
|
} => SvgStyle {
|
|
|
|
icon_width,
|
|
|
|
icon_height,
|
|
|
|
color,
|
|
|
|
},
|
2023-08-17 22:30:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Svg<S> {
|
2023-08-19 12:18:53 +00:00
|
|
|
path: Option<Cow<'static, str>>,
|
2023-08-17 22:30:40 +00:00
|
|
|
style: S,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Svg<()> {
|
|
|
|
pub fn new(path: impl Into<Cow<'static, str>>) -> Self {
|
|
|
|
Self {
|
2023-08-19 12:18:53 +00:00
|
|
|
path: Some(path.into()),
|
|
|
|
style: (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn optional(path: Option<impl Into<Cow<'static, str>>>) -> Self {
|
|
|
|
Self {
|
|
|
|
path: path.map(Into::into),
|
2023-08-17 22:30:40 +00:00
|
|
|
style: (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl SafeStylable for Svg<()> {
|
2023-08-17 22:30:40 +00:00
|
|
|
type Style = SvgStyle;
|
|
|
|
|
|
|
|
type Output = Svg<SvgStyle>;
|
|
|
|
|
|
|
|
fn with_style(self, style: Self::Style) -> Self::Output {
|
|
|
|
Svg {
|
|
|
|
path: self.path,
|
|
|
|
style,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 12:18:53 +00:00
|
|
|
impl Component for Svg<SvgStyle> {
|
2023-08-23 23:30:27 +00:00
|
|
|
fn render<V: 'static>(self, _: &mut gpui::ViewContext<V>) -> gpui::AnyElement<V> {
|
2023-08-19 12:18:53 +00:00
|
|
|
if let Some(path) = self.path {
|
|
|
|
gpui::elements::Svg::new(path)
|
|
|
|
.with_color(self.style.color)
|
|
|
|
.constrained()
|
|
|
|
} else {
|
|
|
|
Empty::new().constrained()
|
|
|
|
}
|
|
|
|
.constrained()
|
|
|
|
.with_width(self.style.icon_width)
|
|
|
|
.with_height(self.style.icon_height)
|
|
|
|
.into_any()
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub mod label {
|
|
|
|
use std::borrow::Cow;
|
|
|
|
|
|
|
|
use gpui::{
|
2023-08-19 21:40:05 +00:00
|
|
|
elements::{Component, LabelStyle, SafeStylable},
|
2023-08-19 23:29:24 +00:00
|
|
|
fonts::TextStyle,
|
2023-08-17 22:30:40 +00:00
|
|
|
Element,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub struct Label<S> {
|
|
|
|
text: Cow<'static, str>,
|
|
|
|
style: S,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Label<()> {
|
|
|
|
pub fn new(text: impl Into<Cow<'static, str>>) -> Self {
|
|
|
|
Self {
|
|
|
|
text: text.into(),
|
|
|
|
style: (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 21:40:05 +00:00
|
|
|
impl SafeStylable for Label<()> {
|
2023-08-19 23:29:24 +00:00
|
|
|
type Style = TextStyle;
|
2023-08-17 22:30:40 +00:00
|
|
|
|
|
|
|
type Output = Label<LabelStyle>;
|
|
|
|
|
|
|
|
fn with_style(self, style: Self::Style) -> Self::Output {
|
|
|
|
Label {
|
|
|
|
text: self.text,
|
2023-08-19 23:29:24 +00:00
|
|
|
style: style.into(),
|
2023-08-17 22:30:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-19 12:18:53 +00:00
|
|
|
impl Component for Label<LabelStyle> {
|
2023-08-23 23:30:27 +00:00
|
|
|
fn render<V: 'static>(self, _: &mut gpui::ViewContext<V>) -> gpui::AnyElement<V> {
|
2023-08-17 22:30:40 +00:00
|
|
|
gpui::elements::Label::new(self.text, self.style).into_any()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|