mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-09 21:26:14 +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>,
|
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> {
|
impl<E: IntoElement + 'static> IntoElement for AnimationElement<E> {
|
||||||
type Element = 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 strum::EnumIter;
|
||||||
|
|
||||||
use crate::{prelude::*, Indicator};
|
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)]
|
#[derive(Default, PartialEq, Copy, Clone)]
|
||||||
pub enum IconSize {
|
pub enum IconSize {
|
||||||
Indicator,
|
Indicator,
|
||||||
@ -236,7 +274,7 @@ impl IconName {
|
|||||||
pub struct Icon {
|
pub struct Icon {
|
||||||
path: SharedString,
|
path: SharedString,
|
||||||
color: Color,
|
color: Color,
|
||||||
size: IconSize,
|
size: Rems,
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +283,7 @@ impl Icon {
|
|||||||
Self {
|
Self {
|
||||||
path: icon.path().into(),
|
path: icon.path().into(),
|
||||||
color: Color::default(),
|
color: Color::default(),
|
||||||
size: IconSize::default(),
|
size: IconSize::default().rems(),
|
||||||
transformation: Transformation::default(),
|
transformation: Transformation::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,7 +292,7 @@ impl Icon {
|
|||||||
Self {
|
Self {
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
color: Color::default(),
|
color: Color::default(),
|
||||||
size: IconSize::default(),
|
size: IconSize::default().rems(),
|
||||||
transformation: Transformation::default(),
|
transformation: Transformation::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,6 +303,14 @@ impl Icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(mut self, size: IconSize) -> Self {
|
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.size = size;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -279,7 +325,7 @@ impl RenderOnce for Icon {
|
|||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||||
svg()
|
svg()
|
||||||
.with_transformation(self.transformation)
|
.with_transformation(self.transformation)
|
||||||
.size(self.size.rems())
|
.size(self.size)
|
||||||
.flex_none()
|
.flex_none()
|
||||||
.path(self.path)
|
.path(self.path)
|
||||||
.text_color(self.color.color(cx))
|
.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)]
|
#[derive(Default)]
|
||||||
pub enum IndicatorStyle {
|
pub enum IndicatorStyle {
|
||||||
#[default]
|
#[default]
|
||||||
Dot,
|
Dot,
|
||||||
Bar,
|
Bar,
|
||||||
|
Icon(AnyIcon),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct Indicator {
|
pub struct Indicator {
|
||||||
position: Position,
|
|
||||||
style: IndicatorStyle,
|
style: IndicatorStyle,
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
}
|
}
|
||||||
@ -19,7 +19,6 @@ pub struct Indicator {
|
|||||||
impl Indicator {
|
impl Indicator {
|
||||||
pub fn dot() -> Self {
|
pub fn dot() -> Self {
|
||||||
Self {
|
Self {
|
||||||
position: Position::Relative,
|
|
||||||
style: IndicatorStyle::Dot,
|
style: IndicatorStyle::Dot,
|
||||||
color: Color::Default,
|
color: Color::Default,
|
||||||
}
|
}
|
||||||
@ -27,32 +26,71 @@ impl Indicator {
|
|||||||
|
|
||||||
pub fn bar() -> Self {
|
pub fn bar() -> Self {
|
||||||
Self {
|
Self {
|
||||||
position: Position::Relative,
|
|
||||||
style: IndicatorStyle::Dot,
|
style: IndicatorStyle::Dot,
|
||||||
color: Color::Default,
|
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 {
|
pub fn color(mut self, color: Color) -> Self {
|
||||||
self.color = color;
|
self.color = color;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn absolute(mut self) -> Self {
|
|
||||||
self.position = Position::Absolute;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderOnce for Indicator {
|
impl RenderOnce for Indicator {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||||
div()
|
let container = div().flex_none();
|
||||||
.flex_none()
|
|
||||||
.map(|this| match self.style {
|
match self.style {
|
||||||
IndicatorStyle::Dot => this.w_1p5().h_1p5().rounded_full(),
|
IndicatorStyle::Icon(icon) => container
|
||||||
IndicatorStyle::Bar => this.w_full().h_1p5().rounded_t_md(),
|
.child(icon.map(|icon| icon.custom_size(rems_from_px(8.)).color(self.color))),
|
||||||
})
|
IndicatorStyle::Dot => container
|
||||||
.when(self.position == Position::Absolute, |this| this.absolute())
|
.w_1p5()
|
||||||
.bg(self.color.color(cx))
|
.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