mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-02 18:51:34 +03:00
Initial dedicated face pile element
Rather than overload Flex with yet another special case, add a dedicated element to handle this overlap instead Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
parent
6a731233c5
commit
7f4da80386
@ -1,6 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
collaborator_list_popover, collaborator_list_popover::CollaboratorListPopover,
|
collaborator_list_popover, collaborator_list_popover::CollaboratorListPopover,
|
||||||
contact_notification::ContactNotification, contacts_popover, ToggleScreenSharing,
|
contact_notification::ContactNotification, contacts_popover, face_pile::FacePile,
|
||||||
|
ToggleScreenSharing,
|
||||||
};
|
};
|
||||||
use call::{ActiveCall, ParticipantLocation, Room};
|
use call::{ActiveCall, ParticipantLocation, Room};
|
||||||
use client::{proto::PeerId, Authenticate, ContactEventKind, User, UserStore};
|
use client::{proto::PeerId, Authenticate, ContactEventKind, User, UserStore};
|
||||||
@ -627,7 +628,7 @@ impl CollabTitlebarItem {
|
|||||||
|
|
||||||
let content = Stack::new()
|
let content = Stack::new()
|
||||||
.with_children(user.avatar.as_ref().map(|avatar| {
|
.with_children(user.avatar.as_ref().map(|avatar| {
|
||||||
let flex = Flex::row()
|
let face_pile = FacePile::new(theme.workspace.titlebar.follower_avatar_overlap)
|
||||||
.with_child(Self::render_face(avatar.clone(), avatar_style.clone()))
|
.with_child(Self::render_face(avatar.clone(), avatar_style.clone()))
|
||||||
.with_children(
|
.with_children(
|
||||||
(|| {
|
(|| {
|
||||||
@ -652,16 +653,10 @@ impl CollabTitlebarItem {
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Some(
|
Some(Self::render_face(
|
||||||
Container::new(Self::render_face(
|
avatar.clone(),
|
||||||
avatar.clone(),
|
theme.workspace.titlebar.follower_avatar.clone(),
|
||||||
theme.workspace.titlebar.follower_avatar.clone(),
|
))
|
||||||
))
|
|
||||||
.with_margin_left(
|
|
||||||
-1.0 * theme.workspace.titlebar.follower_avatar_overlap,
|
|
||||||
)
|
|
||||||
.boxed(),
|
|
||||||
)
|
|
||||||
}))
|
}))
|
||||||
})()
|
})()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -679,11 +674,11 @@ impl CollabTitlebarItem {
|
|||||||
});
|
});
|
||||||
if followed_by_self {
|
if followed_by_self {
|
||||||
let color = theme.editor.replica_selection_style(replica_id).selection;
|
let color = theme.editor.replica_selection_style(replica_id).selection;
|
||||||
return flex.contained().with_background_color(color).boxed();
|
return face_pile.contained().with_background_color(color).boxed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flex.boxed()
|
face_pile.boxed()
|
||||||
}))
|
}))
|
||||||
.with_children((|| {
|
.with_children((|| {
|
||||||
let replica_id = replica_id?;
|
let replica_id = replica_id?;
|
||||||
|
@ -4,6 +4,7 @@ mod contact_finder;
|
|||||||
mod contact_list;
|
mod contact_list;
|
||||||
mod contact_notification;
|
mod contact_notification;
|
||||||
mod contacts_popover;
|
mod contacts_popover;
|
||||||
|
mod face_pile;
|
||||||
mod incoming_call_notification;
|
mod incoming_call_notification;
|
||||||
mod notifications;
|
mod notifications;
|
||||||
mod project_shared_notification;
|
mod project_shared_notification;
|
||||||
|
99
crates/collab_ui/src/face_pile.rs
Normal file
99
crates/collab_ui/src/face_pile.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
|
use gpui::{
|
||||||
|
geometry::{
|
||||||
|
rect::RectF,
|
||||||
|
vector::{vec2f, Vector2F},
|
||||||
|
},
|
||||||
|
json::ToJson,
|
||||||
|
serde_json::{self, json},
|
||||||
|
Axis, DebugContext, Element, ElementBox, MeasurementContext, PaintContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) struct FacePile {
|
||||||
|
overlap: f32,
|
||||||
|
faces: Vec<ElementBox>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FacePile {
|
||||||
|
pub fn new(overlap: f32) -> FacePile {
|
||||||
|
FacePile {
|
||||||
|
overlap,
|
||||||
|
faces: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Element for FacePile {
|
||||||
|
type LayoutState = ();
|
||||||
|
type PaintState = ();
|
||||||
|
|
||||||
|
fn layout(
|
||||||
|
&mut self,
|
||||||
|
constraint: gpui::SizeConstraint,
|
||||||
|
cx: &mut gpui::LayoutContext,
|
||||||
|
) -> (Vector2F, Self::LayoutState) {
|
||||||
|
debug_assert!(constraint.max_along(Axis::Horizontal) == f32::INFINITY);
|
||||||
|
|
||||||
|
let mut width = 0.;
|
||||||
|
for face in &mut self.faces {
|
||||||
|
width += face.layout(constraint, cx).x();
|
||||||
|
}
|
||||||
|
width -= self.overlap * self.faces.len().saturating_sub(1) as f32;
|
||||||
|
|
||||||
|
(Vector2F::new(width, constraint.max.y()), ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(
|
||||||
|
&mut self,
|
||||||
|
bounds: RectF,
|
||||||
|
visible_bounds: RectF,
|
||||||
|
_layout: &mut Self::LayoutState,
|
||||||
|
cx: &mut PaintContext,
|
||||||
|
) -> Self::PaintState {
|
||||||
|
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
|
||||||
|
|
||||||
|
let origin_y = bounds.upper_right().y();
|
||||||
|
let mut origin_x = bounds.upper_right().x();
|
||||||
|
|
||||||
|
for face in self.faces.iter_mut().rev() {
|
||||||
|
let size = face.size();
|
||||||
|
origin_x -= size.x();
|
||||||
|
face.paint(vec2f(origin_x, origin_y), visible_bounds, cx);
|
||||||
|
origin_x += self.overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rect_for_text_range(
|
||||||
|
&self,
|
||||||
|
_: Range<usize>,
|
||||||
|
_: RectF,
|
||||||
|
_: RectF,
|
||||||
|
_: &Self::LayoutState,
|
||||||
|
_: &Self::PaintState,
|
||||||
|
_: &MeasurementContext,
|
||||||
|
) -> Option<RectF> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug(
|
||||||
|
&self,
|
||||||
|
bounds: RectF,
|
||||||
|
_: &Self::LayoutState,
|
||||||
|
_: &Self::PaintState,
|
||||||
|
_: &DebugContext,
|
||||||
|
) -> serde_json::Value {
|
||||||
|
json!({
|
||||||
|
"type": "FacePile",
|
||||||
|
"bounds": bounds.to_json()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Extend<ElementBox> for FacePile {
|
||||||
|
fn extend<T: IntoIterator<Item = ElementBox>>(&mut self, children: T) {
|
||||||
|
self.faces.extend(children);
|
||||||
|
}
|
||||||
|
}
|
@ -119,7 +119,7 @@ export default function workspace(colorScheme: ColorScheme) {
|
|||||||
width: 1,
|
width: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
followerAvatarOverlap: 4,
|
followerAvatarOverlap: 6,
|
||||||
avatarRibbon: {
|
avatarRibbon: {
|
||||||
height: 3,
|
height: 3,
|
||||||
width: 12,
|
width: 12,
|
||||||
|
Loading…
Reference in New Issue
Block a user