assets/images/zed-logo-90x90.png 🔗
Mikayla Maki and Nathan created
add zed logo into welcome experience
Co-authored-by: Nathan <nathan@zed.dev>
assets/images/zed-logo-90x90.png | 0
crates/collab_ui/src/collab_titlebar_item.rs | 2
crates/collab_ui/src/contact_finder.rs | 2
crates/collab_ui/src/contact_list.rs | 6
crates/collab_ui/src/incoming_call_notification.rs | 2
crates/collab_ui/src/notifications.rs | 2
crates/collab_ui/src/project_shared_notification.rs | 2
crates/gpui/src/assets.rs | 21 +++++
crates/gpui/src/elements/image.rs | 56 ++++++++++----
crates/project_panel/src/project_panel.rs | 2
crates/welcome/src/welcome.rs | 14 +--
11 files changed, 76 insertions(+), 33 deletions(-)
@@ -823,7 +823,7 @@ impl CollabTitlebarItem {
avatar_style: AvatarStyle,
background_color: Color,
) -> ElementBox {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(avatar_style.image)
.aligned()
.contained()
@@ -128,7 +128,7 @@ impl PickerDelegate for ContactFinder {
.style_for(mouse_state, selected);
Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.contact_finder.contact_avatar)
.aligned()
.left()
@@ -726,7 +726,7 @@ impl ContactList {
) -> ElementBox {
Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.contact_avatar)
.aligned()
.left()
@@ -1080,7 +1080,7 @@ impl ContactList {
};
Stack::new()
.with_child(
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.contact_avatar)
.aligned()
.left()
@@ -1173,7 +1173,7 @@ impl ContactList {
let mut row = Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.contact_avatar)
.aligned()
.left()
@@ -108,7 +108,7 @@ impl IncomingCallNotification {
.unwrap_or(&default_project);
Flex::row()
.with_children(self.call.calling_user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.caller_avatar)
.aligned()
.boxed()
@@ -24,7 +24,7 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
.with_child(
Flex::row()
.with_children(user.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.header_avatar)
.aligned()
.constrained()
@@ -108,7 +108,7 @@ impl ProjectSharedNotification {
let theme = &cx.global::<Settings>().theme.project_shared_notification;
Flex::row()
.with_children(self.owner.avatar.clone().map(|avatar| {
- Image::new(avatar)
+ Image::from_data(avatar)
.with_style(theme.owner_avatar)
.aligned()
.boxed()
@@ -1,5 +1,8 @@
use anyhow::{anyhow, Result};
-use std::{borrow::Cow, cell::RefCell, collections::HashMap};
+use image::ImageFormat;
+use std::{borrow::Cow, cell::RefCell, collections::HashMap, sync::Arc};
+
+use crate::ImageData;
pub trait AssetSource: 'static + Send + Sync {
fn load(&self, path: &str) -> Result<Cow<[u8]>>;
@@ -22,6 +25,7 @@ impl AssetSource for () {
pub struct AssetCache {
source: Box<dyn AssetSource>,
svgs: RefCell<HashMap<String, usvg::Tree>>,
+ pngs: RefCell<HashMap<String, Arc<ImageData>>>,
}
impl AssetCache {
@@ -29,6 +33,7 @@ impl AssetCache {
Self {
source: Box::new(source),
svgs: RefCell::new(HashMap::new()),
+ pngs: RefCell::new(HashMap::new()),
}
}
@@ -43,4 +48,18 @@ impl AssetCache {
Ok(svg)
}
}
+
+ pub fn png(&self, path: &str) -> Result<Arc<ImageData>> {
+ let mut pngs = self.pngs.borrow_mut();
+ if let Some(png) = pngs.get(path) {
+ Ok(png.clone())
+ } else {
+ let bytes = self.source.load(path)?;
+ let image = ImageData::new(
+ image::load_from_memory_with_format(&bytes, ImageFormat::Png)?.into_bgra8(),
+ );
+ pngs.insert(path.to_string(), image.clone());
+ Ok(image)
+ }
+ }
}
@@ -11,8 +11,13 @@ use crate::{
use serde::Deserialize;
use std::{ops::Range, sync::Arc};
+enum ImageSource {
+ Path(&'static str),
+ Data(Arc<ImageData>),
+}
+
pub struct Image {
- data: Arc<ImageData>,
+ source: ImageSource,
style: ImageStyle,
}
@@ -31,9 +36,16 @@ pub struct ImageStyle {
}
impl Image {
- pub fn new(data: Arc<ImageData>) -> Self {
+ pub fn new(asset_path: &'static str) -> Self {
+ Self {
+ source: ImageSource::Path(asset_path),
+ style: Default::default(),
+ }
+ }
+
+ pub fn from_data(data: Arc<ImageData>) -> Self {
Self {
- data,
+ source: ImageSource::Data(data),
style: Default::default(),
}
}
@@ -45,39 +57,53 @@ impl Image {
}
impl Element for Image {
- type LayoutState = ();
+ type LayoutState = Option<Arc<ImageData>>;
type PaintState = ();
fn layout(
&mut self,
constraint: SizeConstraint,
- _: &mut LayoutContext,
+ cx: &mut LayoutContext,
) -> (Vector2F, Self::LayoutState) {
+ let data = match &self.source {
+ ImageSource::Path(path) => match cx.asset_cache.png(path) {
+ Ok(data) => data,
+ Err(error) => {
+ log::error!("could not load image: {}", error);
+ return (Vector2F::zero(), None);
+ }
+ },
+ ImageSource::Data(data) => data.clone(),
+ };
+
let desired_size = vec2f(
self.style.width.unwrap_or_else(|| constraint.max.x()),
self.style.height.unwrap_or_else(|| constraint.max.y()),
);
let size = constrain_size_preserving_aspect_ratio(
constraint.constrain(desired_size),
- self.data.size().to_f32(),
+ data.size().to_f32(),
);
- (size, ())
+
+ (size, Some(data))
}
fn paint(
&mut self,
bounds: RectF,
_: RectF,
- _: &mut Self::LayoutState,
+ layout: &mut Self::LayoutState,
cx: &mut PaintContext,
) -> Self::PaintState {
- cx.scene.push_image(scene::Image {
- bounds,
- border: self.style.border,
- corner_radius: self.style.corner_radius,
- grayscale: self.style.grayscale,
- data: self.data.clone(),
- });
+ if let Some(data) = layout {
+ cx.scene.push_image(scene::Image {
+ bounds,
+ border: self.style.border,
+ corner_radius: self.style.corner_radius,
+ grayscale: self.style.grayscale,
+ data: data.clone(),
+ });
+ }
}
fn rect_for_text_range(
@@ -1325,7 +1325,7 @@ impl View for ProjectPanel {
Canvas::new(|bounds, _visible_bounds, cx| {
cx.scene.push_quad(gpui::Quad {
bounds,
- background: Some(Color::red()),
+ background: Some(Color::transparent_black()),
..Default::default()
})
})
@@ -1,14 +1,13 @@
use std::borrow::Cow;
use gpui::{
- color::Color,
- elements::{Canvas, Empty, Flex, Label, MouseEventHandler, ParentElement, Stack, Svg},
+ elements::{Canvas, Empty, Flex, Image, Label, MouseEventHandler, ParentElement, Stack},
geometry::rect::RectF,
Action, Element, ElementBox, Entity, MouseButton, MouseRegion, MutableAppContext,
RenderContext, Subscription, View, ViewContext,
};
use settings::{settings_file::SettingsFile, Settings, SettingsFileContent};
-use theme::{CheckboxStyle, ContainedText, Interactive};
+use theme::CheckboxStyle;
use workspace::{item::Item, Welcome, Workspace};
pub fn init(cx: &mut MutableAppContext) {
@@ -72,15 +71,14 @@ impl View for WelcomePage {
.with_children([
Flex::row()
.with_children([
- Svg::new("icons/terminal_16.svg")
- .with_color(Color::red())
+ Image::new("images/zed-logo-90x90.png")
.constrained()
- .with_width(100.)
- .with_height(100.)
+ .with_width(90.)
+ .with_height(90.)
.aligned()
.contained()
.boxed(),
- Label::new("Zed", theme.editor.hover_popover.prose.clone()).boxed(),
+ // Label::new("Zed", theme.editor.hover_popover.prose.clone()).boxed(),
])
.boxed(),
Label::new(