mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 10:29:35 +03:00
Add the ability to render icons as indicators (#11273)
This PR adds the ability to render `Icon`s as an `Indicator`. Release Notes: - N/A Co-authored-by: Nate Butler <nate@zed.dev>
This commit is contained in:
parent
4f5312804d
commit
4739797e5d
@ -72,6 +72,15 @@ pub struct AnimationElement<E> {
|
||||
animator: Box<dyn Fn(E, f32) -> E + 'static>,
|
||||
}
|
||||
|
||||
impl<E> AnimationElement<E> {
|
||||
/// Returns a new [`AnimationElement<E>`] after applying the given function
|
||||
/// to the element being animated.
|
||||
pub fn map_element(mut self, f: impl FnOnce(E) -> E) -> AnimationElement<E> {
|
||||
self.element = self.element.map(f);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: IntoElement + 'static> IntoElement for AnimationElement<E> {
|
||||
type Element = AnimationElement<E>;
|
||||
|
||||
|
@ -1,8 +1,46 @@
|
||||
use gpui::{svg, Hsla, IntoElement, Rems, Transformation};
|
||||
use gpui::{svg, AnimationElement, Hsla, IntoElement, Rems, Transformation};
|
||||
use strum::EnumIter;
|
||||
|
||||
use crate::{prelude::*, Indicator};
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub enum AnyIcon {
|
||||
Icon(Icon),
|
||||
AnimatedIcon(AnimationElement<Icon>),
|
||||
}
|
||||
|
||||
impl AnyIcon {
|
||||
/// Returns a new [`AnyIcon`] after applying the given mapping function
|
||||
/// to the contained [`Icon`].
|
||||
pub fn map(self, f: impl FnOnce(Icon) -> Icon) -> Self {
|
||||
match self {
|
||||
Self::Icon(icon) => Self::Icon(f(icon)),
|
||||
Self::AnimatedIcon(animated_icon) => Self::AnimatedIcon(animated_icon.map_element(f)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Icon> for AnyIcon {
|
||||
fn from(value: Icon) -> Self {
|
||||
Self::Icon(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnimationElement<Icon>> for AnyIcon {
|
||||
fn from(value: AnimationElement<Icon>) -> Self {
|
||||
Self::AnimatedIcon(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for AnyIcon {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
match self {
|
||||
Self::Icon(icon) => icon.into_any_element(),
|
||||
Self::AnimatedIcon(animated_icon) => animated_icon.into_any_element(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Copy, Clone)]
|
||||
pub enum IconSize {
|
||||
Indicator,
|
||||
@ -236,7 +274,7 @@ impl IconName {
|
||||
pub struct Icon {
|
||||
path: SharedString,
|
||||
color: Color,
|
||||
size: IconSize,
|
||||
size: Rems,
|
||||
transformation: Transformation,
|
||||
}
|
||||
|
||||
@ -245,7 +283,7 @@ impl Icon {
|
||||
Self {
|
||||
path: icon.path().into(),
|
||||
color: Color::default(),
|
||||
size: IconSize::default(),
|
||||
size: IconSize::default().rems(),
|
||||
transformation: Transformation::default(),
|
||||
}
|
||||
}
|
||||
@ -254,7 +292,7 @@ impl Icon {
|
||||
Self {
|
||||
path: path.into(),
|
||||
color: Color::default(),
|
||||
size: IconSize::default(),
|
||||
size: IconSize::default().rems(),
|
||||
transformation: Transformation::default(),
|
||||
}
|
||||
}
|
||||
@ -265,6 +303,14 @@ impl Icon {
|
||||
}
|
||||
|
||||
pub fn size(mut self, size: IconSize) -> Self {
|
||||
self.size = size.rems();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets a custom size for the icon, in [`Rems`].
|
||||
///
|
||||
/// Not to be exposed outside of the `ui` crate.
|
||||
pub(crate) fn custom_size(mut self, size: Rems) -> Self {
|
||||
self.size = size;
|
||||
self
|
||||
}
|
||||
@ -279,7 +325,7 @@ impl RenderOnce for Icon {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
svg()
|
||||
.with_transformation(self.transformation)
|
||||
.size(self.size.rems())
|
||||
.size(self.size)
|
||||
.flex_none()
|
||||
.path(self.path)
|
||||
.text_color(self.color.color(cx))
|
||||
|
@ -1,17 +1,17 @@
|
||||
use gpui::Position;
|
||||
use gpui::Transformation;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::{prelude::*, AnyIcon};
|
||||
|
||||
#[derive(Default)]
|
||||
pub enum IndicatorStyle {
|
||||
#[default]
|
||||
Dot,
|
||||
Bar,
|
||||
Icon(AnyIcon),
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct Indicator {
|
||||
position: Position,
|
||||
style: IndicatorStyle,
|
||||
pub color: Color,
|
||||
}
|
||||
@ -19,7 +19,6 @@ pub struct Indicator {
|
||||
impl Indicator {
|
||||
pub fn dot() -> Self {
|
||||
Self {
|
||||
position: Position::Relative,
|
||||
style: IndicatorStyle::Dot,
|
||||
color: Color::Default,
|
||||
}
|
||||
@ -27,32 +26,71 @@ impl Indicator {
|
||||
|
||||
pub fn bar() -> Self {
|
||||
Self {
|
||||
position: Position::Relative,
|
||||
style: IndicatorStyle::Dot,
|
||||
color: Color::Default,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn icon(icon: impl Into<AnyIcon>) -> Self {
|
||||
Self {
|
||||
style: IndicatorStyle::Icon(icon.into()),
|
||||
color: Color::Default,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn color(mut self, color: Color) -> Self {
|
||||
self.color = color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn absolute(mut self) -> Self {
|
||||
self.position = Position::Absolute;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for Indicator {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
div()
|
||||
.flex_none()
|
||||
.map(|this| match self.style {
|
||||
IndicatorStyle::Dot => this.w_1p5().h_1p5().rounded_full(),
|
||||
IndicatorStyle::Bar => this.w_full().h_1p5().rounded_t_md(),
|
||||
})
|
||||
.when(self.position == Position::Absolute, |this| this.absolute())
|
||||
.bg(self.color.color(cx))
|
||||
let container = div().flex_none();
|
||||
|
||||
match self.style {
|
||||
IndicatorStyle::Icon(icon) => container
|
||||
.child(icon.map(|icon| icon.custom_size(rems_from_px(8.)).color(self.color))),
|
||||
IndicatorStyle::Dot => container
|
||||
.w_1p5()
|
||||
.h_1p5()
|
||||
.rounded_full()
|
||||
.bg(self.color.color(cx)),
|
||||
IndicatorStyle::Bar => container
|
||||
.w_full()
|
||||
.h_1p5()
|
||||
.rounded_t_md()
|
||||
.bg(self.color.color(cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct IndicatorIcon {
|
||||
icon: Icon,
|
||||
transformation: Option<Transformation>,
|
||||
}
|
||||
|
||||
impl IndicatorIcon {
|
||||
pub fn new(icon: Icon) -> Self {
|
||||
Self {
|
||||
icon,
|
||||
transformation: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transformation(mut self, transformation: Transformation) -> Self {
|
||||
self.transformation = Some(transformation);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for IndicatorIcon {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
self.icon
|
||||
.custom_size(rems_from_px(8.))
|
||||
.when_some(self.transformation, |this, transformation| {
|
||||
this.transform(transformation)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user