diff --git a/Cargo.lock b/Cargo.lock index b3e5c38a46..b04fea24b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3371,6 +3371,7 @@ dependencies = [ "project", "settings", "theme", + "util", "workspace", ] diff --git a/crates/activity_indicator/src/activity_indicator.rs b/crates/activity_indicator/src/activity_indicator.rs index 2fd8774398..c49348b832 100644 --- a/crates/activity_indicator/src/activity_indicator.rs +++ b/crates/activity_indicator/src/activity_indicator.rs @@ -2,10 +2,10 @@ use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage}; use editor::Editor; use futures::StreamExt; use gpui::{ - actions, + actions, anyhow, elements::*, platform::{CursorStyle, MouseButton}, - Action, AppContext, Entity, ModelHandle, RenderContext, View, ViewContext, ViewHandle, + Action, AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle, }; use language::{LanguageRegistry, LanguageServerBinaryStatus}; use project::{LanguageServerProgress, Project}; @@ -73,11 +73,12 @@ impl ActivityIndicator { status: event, }); cx.notify(); - }); + })?; } else { break; } } + anyhow::Ok(()) }) .detach(); cx.observe(&project, |_, _, cx| cx.notify()).detach(); @@ -172,7 +173,7 @@ impl ActivityIndicator { .flatten() } - fn content_to_render(&mut self, cx: &mut RenderContext) -> Content { + fn content_to_render(&mut self, cx: &mut ViewContext) -> Content { // Show any language server has pending activity. let mut pending_work = self.pending_language_server_work(cx); if let Some(PendingWork { @@ -314,14 +315,14 @@ impl View for ActivityIndicator { "ActivityIndicator" } - fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> Element { let Content { icon, message, action, } = self.content_to_render(cx); - let mut element = MouseEventHandler::::new(0, cx, |state, cx| { + let mut element = MouseEventHandler::::new(0, cx, |state, cx| { let theme = &cx .global::() .theme @@ -361,7 +362,7 @@ impl View for ActivityIndicator { if let Some(action) = action { element = element .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_any_action(action.boxed_clone()) }); } diff --git a/crates/auto_update/src/auto_update.rs b/crates/auto_update/src/auto_update.rs index a12a5dd3a9..b0aa9f1159 100644 --- a/crates/auto_update/src/auto_update.rs +++ b/crates/auto_update/src/auto_update.rs @@ -113,7 +113,7 @@ pub fn notify_of_any_new_update( .read(cx) .set_should_show_update_notification(false, cx) .detach_and_log_err(cx); - }); + })?; } } anyhow::Ok(()) diff --git a/crates/auto_update/src/update_notification.rs b/crates/auto_update/src/update_notification.rs index 414dcdf5a1..6ba87a68b9 100644 --- a/crates/auto_update/src/update_notification.rs +++ b/crates/auto_update/src/update_notification.rs @@ -2,7 +2,7 @@ use crate::ViewReleaseNotes; use gpui::{ elements::{Flex, MouseEventHandler, Padding, ParentElement, Svg, Text}, platform::{AppVersion, CursorStyle, MouseButton}, - Element, Entity, View, ViewContext, + Drawable, Entity, View, ViewContext, }; use menu::Cancel; use settings::Settings; @@ -26,13 +26,13 @@ impl View for UpdateNotification { "UpdateNotification" } - fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { + fn render(&mut self, cx: &mut gpui::ViewContext) -> gpui::Element { let theme = cx.global::().theme.clone(); let theme = &theme.update_notification; let app_name = cx.global::().display_name(); - MouseEventHandler::::new(0, cx, |state, cx| { + MouseEventHandler::::new(0, cx, |state, cx| { Flex::column() .with_child( Flex::row() @@ -50,7 +50,7 @@ impl View for UpdateNotification { .boxed(), ) .with_child( - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |state, _| { let style = theme.dismiss_button.style_for(state, false); Svg::new("icons/x_mark_8.svg") .with_color(style.color) @@ -65,7 +65,9 @@ impl View for UpdateNotification { .boxed() }) .with_padding(Padding::uniform(5.)) - .on_click(MouseButton::Left, move |_, cx| cx.dispatch_action(Cancel)) + .on_click(MouseButton::Left, move |_, _, cx| { + cx.dispatch_action(Cancel) + }) .aligned() .constrained() .with_height(cx.font_cache().line_height(theme.message.text.font_size)) @@ -87,7 +89,7 @@ impl View for UpdateNotification { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, |_, cx| { + .on_click(MouseButton::Left, |_, _, cx| { cx.dispatch_action(ViewReleaseNotes) }) .boxed() diff --git a/crates/breadcrumbs/src/breadcrumbs.rs b/crates/breadcrumbs/src/breadcrumbs.rs index 6c8cbc5516..ff4443a570 100644 --- a/crates/breadcrumbs/src/breadcrumbs.rs +++ b/crates/breadcrumbs/src/breadcrumbs.rs @@ -1,6 +1,6 @@ use gpui::{ - elements::*, platform::MouseButton, AppContext, Entity, RenderContext, Subscription, View, - ViewContext, ViewHandle, + elements::*, platform::MouseButton, AppContext, Entity, Subscription, View, ViewContext, + ViewHandle, }; use itertools::Itertools; use search::ProjectSearchView; @@ -41,7 +41,7 @@ impl View for Breadcrumbs { "Breadcrumbs" } - fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> Element { let active_item = match &self.active_item { Some(active_item) => active_item, None => return Empty::new().boxed(), @@ -54,10 +54,22 @@ impl View for Breadcrumbs { let breadcrumbs = match active_item.breadcrumbs(&theme, cx) { Some(breadcrumbs) => breadcrumbs, None => return Empty::new().boxed(), - }; + } + .into_iter() + .map(|breadcrumb| { + let text = Text::new( + breadcrumb.text, + theme.workspace.breadcrumbs.default.text.clone(), + ); + if let Some(highlights) = breadcrumb.highlights { + text.with_highlights(highlights).boxed() + } else { + text.boxed() + } + }); let crumbs = Flex::row() - .with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || { + .with_children(Itertools::intersperse_with(breadcrumbs, || { Label::new(" 〉 ", style.default.text.clone()).boxed() })) .constrained() @@ -72,14 +84,14 @@ impl View for Breadcrumbs { .boxed(); } - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |state, _| { let style = style.style_for(state, false); crumbs.with_style(style.container).boxed() }) - .on_click(MouseButton::Left, |_, cx| { + .on_click(MouseButton::Left, |_, _, cx| { cx.dispatch_action(outline::Toggle); }) - .with_tooltip::( + .with_tooltip::( 0, "Show symbol outline".to_owned(), Some(Box::new(outline::Toggle)), @@ -136,7 +148,7 @@ impl ToolbarItemView for Breadcrumbs { } } - fn pane_focus_update(&mut self, pane_focused: bool, _: &mut gpui::AppContext) { + fn pane_focus_update(&mut self, pane_focused: bool, _: &mut ViewContext) { self.pane_focused = pane_focused; } } diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 206064dc38..d42c4b3ebc 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -1470,7 +1470,8 @@ async fn test_host_disconnect( deterministic.run_until_parked(); assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared())); - let (_, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx)); + let (window_id_b, workspace_b) = + cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx)); let editor_b = workspace_b .update(cx_b, |workspace, cx| { workspace.open_path((worktree_id, "b.txt"), None, true, cx) @@ -1479,12 +1480,9 @@ async fn test_host_disconnect( .unwrap() .downcast::() .unwrap(); - cx_b.read(|cx| { - assert_eq!( - cx.focused_view_id(workspace_b.window_id()), - Some(editor_b.id()) - ); - }); + assert!(cx_b + .read_window(window_id_b, |cx| editor_b.is_focused(cx)) + .unwrap()); editor_b.update(cx_b, |editor, cx| editor.insert("X", cx)); assert!(cx_b.is_window_edited(workspace_b.window_id())); @@ -1498,8 +1496,8 @@ async fn test_host_disconnect( assert!(worktree_a.read_with(cx_a, |tree, _| !tree.as_local().unwrap().is_shared())); // Ensure client B's edited state is reset and that the whole window is blurred. - cx_b.read(|cx| { - assert_eq!(cx.focused_view_id(workspace_b.window_id()), None); + cx_b.read_window(window_id_b, |cx| { + assert_eq!(cx.focused_view_id(), None); }); assert!(!cx_b.is_window_edited(workspace_b.window_id())); @@ -6228,7 +6226,8 @@ async fn test_basic_following( .update(cx_a, |workspace, cx| { workspace::Pane::go_back(workspace, None, cx) }) - .await; + .await + .unwrap(); deterministic.run_until_parked(); workspace_b.read_with(cx_b, |workspace, cx| { assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b1.id()); @@ -6238,7 +6237,8 @@ async fn test_basic_following( .update(cx_a, |workspace, cx| { workspace::Pane::go_back(workspace, None, cx) }) - .await; + .await + .unwrap(); deterministic.run_until_parked(); workspace_b.read_with(cx_b, |workspace, cx| { assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b2.id()); @@ -6248,7 +6248,8 @@ async fn test_basic_following( .update(cx_a, |workspace, cx| { workspace::Pane::go_forward(workspace, None, cx) }) - .await; + .await + .unwrap(); deterministic.run_until_parked(); workspace_b.read_with(cx_b, |workspace, cx| { assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b1.id()); diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index b0b734f9cf..4c177f0f00 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -16,7 +16,7 @@ use gpui::{ impl_internal_actions, json::{self, ToJson}, platform::{CursorStyle, MouseButton}, - AppContext, Entity, ImageData, ModelHandle, RenderContext, Subscription, View, ViewContext, + AppContext, Entity, ImageData, ModelHandle, SceneBuilder, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, }; use settings::Settings; @@ -68,7 +68,7 @@ impl View for CollabTitlebarItem { "CollabTitlebarItem" } - fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> Element { let workspace = if let Some(workspace) = self.workspace.upgrade(cx) { workspace } else { @@ -325,8 +325,8 @@ impl CollabTitlebarItem { fn render_toggle_contacts_button( &self, theme: &Theme, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { let titlebar = &theme.workspace.titlebar; let badge = if self @@ -352,7 +352,7 @@ impl CollabTitlebarItem { Stack::new() .with_child( - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |state, _| { let style = titlebar .toggle_contacts_button .style_for(state, self.contacts_popover.is_some()); @@ -369,10 +369,10 @@ impl CollabTitlebarItem { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(ToggleContactsMenu); }) - .with_tooltip::( + .with_tooltip::( 0, "Show contacts menu".into(), Some(Box::new(ToggleContactsMenu)), @@ -390,8 +390,8 @@ impl CollabTitlebarItem { &self, theme: &Theme, room: &ModelHandle, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { let icon; let tooltip; if room.read(cx).is_screen_sharing() { @@ -403,7 +403,7 @@ impl CollabTitlebarItem { } let titlebar = &theme.workspace.titlebar; - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |state, _| { let style = titlebar.call_control.style_for(state, false); Svg::new(icon) .with_color(style.color) @@ -418,10 +418,10 @@ impl CollabTitlebarItem { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(ToggleScreenSharing); }) - .with_tooltip::( + .with_tooltip::( 0, tooltip.into(), Some(Box::new(ToggleScreenSharing)), @@ -436,8 +436,8 @@ impl CollabTitlebarItem { &self, workspace: &ViewHandle, theme: &Theme, - cx: &mut RenderContext, - ) -> Option { + cx: &mut ViewContext, + ) -> Option> { let project = workspace.read(cx).project(); if project.read(cx).is_remote() { return None; @@ -457,7 +457,7 @@ impl CollabTitlebarItem { Some( Stack::new() .with_child( - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |state, _| { //TODO: Ensure this button has consistant width for both text variations let style = titlebar.share_button.style_for(state, false); Label::new(label, style.text.clone()) @@ -466,14 +466,14 @@ impl CollabTitlebarItem { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { if is_shared { cx.dispatch_action(UnshareProject); } else { cx.dispatch_action(ShareProject); } }) - .with_tooltip::( + .with_tooltip::( 0, tooltip.to_owned(), None, @@ -489,12 +489,12 @@ impl CollabTitlebarItem { ) } - fn render_user_menu_button(&self, theme: &Theme, cx: &mut RenderContext) -> ElementBox { + fn render_user_menu_button(&self, theme: &Theme, cx: &mut ViewContext) -> Element { let titlebar = &theme.workspace.titlebar; Stack::new() .with_child( - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |state, _| { let style = titlebar.call_control.style_for(state, false); Svg::new("icons/ellipsis_14.svg") .with_color(style.color) @@ -509,10 +509,10 @@ impl CollabTitlebarItem { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(ToggleUserMenu); }) - .with_tooltip::( + .with_tooltip::( 0, "Toggle user menu".to_owned(), Some(Box::new(ToggleUserMenu)), @@ -533,9 +533,9 @@ impl CollabTitlebarItem { .boxed() } - fn render_sign_in_button(&self, theme: &Theme, cx: &mut RenderContext) -> ElementBox { + fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext) -> Element { let titlebar = &theme.workspace.titlebar; - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |state, _| { let style = titlebar.sign_in_prompt.style_for(state, false); Label::new("Sign In", style.text.clone()) .contained() @@ -543,7 +543,7 @@ impl CollabTitlebarItem { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(SignIn); }) .boxed() @@ -552,8 +552,8 @@ impl CollabTitlebarItem { fn render_contacts_popover_host<'a>( &'a self, _theme: &'a theme::Titlebar, - cx: &'a RenderContext, - ) -> Option { + cx: &'a ViewContext, + ) -> Option> { self.contacts_popover.as_ref().map(|popover| { Overlay::new(ChildView::new(popover, cx).boxed()) .with_fit_mode(OverlayFitMode::SwitchAnchor) @@ -571,8 +571,8 @@ impl CollabTitlebarItem { workspace: &ViewHandle, theme: &Theme, room: &ModelHandle, - cx: &mut RenderContext, - ) -> Vec { + cx: &mut ViewContext, + ) -> Vec> { let mut participants = room .read(cx) .remote_participants() @@ -613,8 +613,8 @@ impl CollabTitlebarItem { theme: &Theme, user: &Arc, peer_id: PeerId, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { let replica_id = workspace.read(cx).project().read(cx).replica_id(); Container::new(self.render_face_pile( user, @@ -637,8 +637,8 @@ impl CollabTitlebarItem { location: Option, workspace: &ViewHandle, theme: &Theme, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { let project_id = workspace.read(cx).project().read(cx).remote_id(); let room = ActiveCall::global(cx).read(cx).room(); let is_being_followed = workspace.read(cx).is_being_followed(peer_id); @@ -749,41 +749,42 @@ impl CollabTitlebarItem { if let Some(location) = location { if let Some(replica_id) = replica_id { - content = - MouseEventHandler::::new(replica_id.into(), cx, move |_, _| { - content - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { - cx.dispatch_action(ToggleFollow(peer_id)) - }) - .with_tooltip::( - peer_id.as_u64() as usize, - if is_being_followed { - format!("Unfollow {}", user.github_login) - } else { - format!("Follow {}", user.github_login) - }, - Some(Box::new(FollowNextCollaborator)), - theme.tooltip.clone(), - cx, - ) - .boxed(); + content = MouseEventHandler::::new( + replica_id.into(), + cx, + move |_, _| content, + ) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, _, cx| { + cx.dispatch_action(ToggleFollow(peer_id)) + }) + .with_tooltip::( + peer_id.as_u64() as usize, + if is_being_followed { + format!("Unfollow {}", user.github_login) + } else { + format!("Follow {}", user.github_login) + }, + Some(Box::new(FollowNextCollaborator)), + theme.tooltip.clone(), + cx, + ) + .boxed(); } else if let ParticipantLocation::SharedProject { project_id } = location { let user_id = user.id; - content = MouseEventHandler::::new( + content = MouseEventHandler::::new( peer_id.as_u64() as usize, cx, move |_, _| content, ) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(JoinProject { project_id, follow_user_id: user_id, }) }) - .with_tooltip::( + .with_tooltip::( peer_id.as_u64() as usize, format!("Follow {} into external project", user.github_login), Some(Box::new(FollowNextCollaborator)), @@ -800,7 +801,7 @@ impl CollabTitlebarItem { workspace: &ViewHandle, location: Option, mut style: AvatarStyle, - cx: &RenderContext, + cx: &ViewContext, ) -> AvatarStyle { if let Some(location) = location { if let ParticipantLocation::SharedProject { project_id } = location { @@ -815,11 +816,11 @@ impl CollabTitlebarItem { style } - fn render_face( + fn render_face( avatar: Arc, avatar_style: AvatarStyle, background_color: Color, - ) -> ElementBox { + ) -> Element { Image::from_data(avatar) .with_style(avatar_style.image) .aligned() @@ -836,8 +837,8 @@ impl CollabTitlebarItem { fn render_connection_status( &self, status: &client::Status, - cx: &mut RenderContext, - ) -> Option { + cx: &mut ViewContext, + ) -> Option> { enum ConnectionStatusButton {} let theme = &cx.global::().theme.clone(); @@ -863,7 +864,7 @@ impl CollabTitlebarItem { .boxed(), ), client::Status::UpgradeRequired => Some( - MouseEventHandler::::new(0, cx, |_, _| { + MouseEventHandler::::new(0, cx, |_, _| { Label::new( "Please update Zed to collaborate", theme.workspace.titlebar.outdated_warning.text.clone(), @@ -874,7 +875,7 @@ impl CollabTitlebarItem { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, |_, cx| { + .on_click(MouseButton::Left, |_, _, cx| { cx.dispatch_action(auto_update::Check); }) .boxed(), @@ -894,7 +895,7 @@ impl AvatarRibbon { } } -impl Element for AvatarRibbon { +impl Drawable for AvatarRibbon { type LayoutState = (); type PaintState = (); @@ -902,17 +903,20 @@ impl Element for AvatarRibbon { fn layout( &mut self, constraint: gpui::SizeConstraint, - _: &mut gpui::LayoutContext, + _: &mut CollabTitlebarItem, + _: &mut ViewContext, ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { (constraint.max, ()) } fn paint( &mut self, - bounds: gpui::geometry::rect::RectF, - _: gpui::geometry::rect::RectF, + scene: &mut SceneBuilder, + bounds: RectF, + _: RectF, _: &mut Self::LayoutState, - cx: &mut gpui::PaintContext, + _: &mut CollabTitlebarItem, + _: &mut ViewContext, ) -> Self::PaintState { let mut path = PathBuilder::new(); path.reset(bounds.lower_left()); @@ -923,7 +927,7 @@ impl Element for AvatarRibbon { path.line_to(bounds.upper_right() - vec2f(bounds.height(), 0.)); path.curve_to(bounds.lower_right(), bounds.upper_right()); path.line_to(bounds.lower_left()); - cx.scene.push_path(path.build(self.color, None)); + scene.push_path(path.build(self.color, None)); } fn rect_for_text_range( @@ -933,17 +937,19 @@ impl Element for AvatarRibbon { _: RectF, _: &Self::LayoutState, _: &Self::PaintState, - _: &gpui::MeasurementContext, + _: &CollabTitlebarItem, + _: &ViewContext, ) -> Option { None } fn debug( &self, - bounds: gpui::geometry::rect::RectF, + bounds: RectF, _: &Self::LayoutState, _: &Self::PaintState, - _: &gpui::DebugContext, + _: &CollabTitlebarItem, + _: &ViewContext, ) -> gpui::json::Value { json::json!({ "type": "AvatarRibbon", diff --git a/crates/collab_ui/src/collab_ui.rs b/crates/collab_ui/src/collab_ui.rs index 7d991f8c94..2902172684 100644 --- a/crates/collab_ui/src/collab_ui.rs +++ b/crates/collab_ui/src/collab_ui.rs @@ -126,7 +126,7 @@ fn join_project(action: &JoinProject, app_state: Arc, cx: &mut AppCont } } } - }); + })?; anyhow::Ok(()) }) diff --git a/crates/collab_ui/src/collaborator_list_popover.rs b/crates/collab_ui/src/collaborator_list_popover.rs index c409b541c9..32df35c1fa 100644 --- a/crates/collab_ui/src/collaborator_list_popover.rs +++ b/crates/collab_ui/src/collaborator_list_popover.rs @@ -1,10 +1,7 @@ use call::ActiveCall; use client::UserStore; use gpui::Action; -use gpui::{ - actions, elements::*, platform::MouseButton, Entity, ModelHandle, RenderContext, View, - ViewContext, -}; +use gpui::{actions, elements::*, platform::MouseButton, Entity, ModelHandle, View, ViewContext}; use settings::Settings; use crate::collab_titlebar_item::ToggleCollaboratorList; @@ -21,7 +18,7 @@ enum Collaborator { actions!(collaborator_list_popover, [NoOp]); pub(crate) struct CollaboratorListPopover { - list_state: ListState, + list_state: ListState, } impl Entity for CollaboratorListPopover { @@ -33,10 +30,10 @@ impl View for CollaboratorListPopover { "CollaboratorListPopover" } - fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> Element { let theme = cx.global::().theme.clone(); - MouseEventHandler::::new(0, cx, |_, _| { + MouseEventHandler::::new(0, cx, |_, _| { List::new(self.list_state.clone()) .contained() .with_style(theme.contacts_popover.container) //TODO: Change the name of this theme key @@ -45,7 +42,7 @@ impl View for CollaboratorListPopover { .with_height(theme.contacts_popover.height) .boxed() }) - .on_down_out(MouseButton::Left, move |_, cx| { + .on_down_out(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(ToggleCollaboratorList); }) .boxed() @@ -83,7 +80,6 @@ impl CollaboratorListPopover { collaborators.len(), Orientation::Top, 0., - cx, move |_, index, cx| match &collaborators[index] { Collaborator::SelfUser { username } => render_collaborator_list_entry( index, @@ -120,8 +116,8 @@ fn render_collaborator_list_entry( icon: Svg, icon_action: IA, icon_tooltip: String, - cx: &mut RenderContext, -) -> ElementBox { + cx: &mut ViewContext, +) -> Element { enum Username {} enum UsernameTooltip {} enum Icon {} @@ -131,19 +127,20 @@ fn render_collaborator_list_entry( let username_theme = theme.contact_list.contact_username.text.clone(); let tooltip_theme = theme.tooltip.clone(); - let username = MouseEventHandler::::new(index, cx, |_, _| { - Label::new(username.to_owned(), username_theme.clone()).boxed() - }) - .on_click(MouseButton::Left, move |_, cx| { - if let Some(username_action) = username_action.clone() { - cx.dispatch_action(username_action); - } - }); + let username = + MouseEventHandler::::new(index, cx, |_, _| { + Label::new(username.to_owned(), username_theme.clone()).boxed() + }) + .on_click(MouseButton::Left, move |_, _, cx| { + if let Some(username_action) = username_action.clone() { + cx.dispatch_action(username_action); + } + }); Flex::row() .with_child(if let Some(username_tooltip) = username_tooltip { username - .with_tooltip::( + .with_tooltip::( index, username_tooltip, None, @@ -155,11 +152,11 @@ fn render_collaborator_list_entry( username.boxed() }) .with_child( - MouseEventHandler::::new(index, cx, |_, _| icon.boxed()) - .on_click(MouseButton::Left, move |_, cx| { + MouseEventHandler::::new(index, cx, |_, _| icon.boxed()) + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(icon_action.clone()) }) - .with_tooltip::(index, icon_tooltip, None, tooltip_theme, cx) + .with_tooltip::(index, icon_tooltip, None, tooltip_theme, cx) .boxed(), ) .boxed() diff --git a/crates/collab_ui/src/contact_finder.rs b/crates/collab_ui/src/contact_finder.rs index d34a344cd6..0d4e3aff3d 100644 --- a/crates/collab_ui/src/contact_finder.rs +++ b/crates/collab_ui/src/contact_finder.rs @@ -1,49 +1,41 @@ use client::{ContactRequestStatus, User, UserStore}; -use gpui::{ - elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, RenderContext, Task, - View, ViewContext, ViewHandle, -}; -use picker::{Picker, PickerDelegate}; +use gpui::{elements::*, AppContext, ModelHandle, MouseState, Task, ViewContext}; +use picker::{Picker, PickerDelegate, PickerEvent}; use settings::Settings; use std::sync::Arc; use util::TryFutureExt; pub fn init(cx: &mut AppContext) { - Picker::::init(cx); + Picker::::init(cx); } -pub struct ContactFinder { - picker: ViewHandle>, +pub type ContactFinder = Picker; + +pub fn build_contact_finder( + user_store: ModelHandle, + cx: &mut ViewContext, +) -> ContactFinder { + Picker::new( + ContactFinderDelegate { + user_store, + potential_contacts: Arc::from([]), + selected_index: 0, + }, + cx, + ) +} + +pub struct ContactFinderDelegate { potential_contacts: Arc<[Arc]>, user_store: ModelHandle, selected_index: usize, } -pub enum Event { - Dismissed, -} - -impl Entity for ContactFinder { - type Event = Event; -} - -impl View for ContactFinder { - fn ui_name() -> &'static str { - "ContactFinder" +impl PickerDelegate for ContactFinderDelegate { + fn placeholder_text(&self) -> Arc { + "Search collaborator by username...".into() } - fn render(&mut self, cx: &mut RenderContext) -> ElementBox { - ChildView::new(&self.picker, cx).boxed() - } - - fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - if cx.is_self_focused() { - cx.focus(&self.picker); - } - } -} - -impl PickerDelegate for ContactFinder { fn match_count(&self) -> usize { self.potential_contacts.len() } @@ -52,22 +44,22 @@ impl PickerDelegate for ContactFinder { self.selected_index } - fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext) { + fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext>) { self.selected_index = ix; } - fn update_matches(&mut self, query: String, cx: &mut ViewContext) -> Task<()> { + fn update_matches(&mut self, query: String, cx: &mut ViewContext>) -> Task<()> { let search_users = self .user_store .update(cx, |store, cx| store.fuzzy_search_users(query, cx)); - cx.spawn(|this, mut cx| async move { + cx.spawn(|picker, mut cx| async move { async { let potential_contacts = search_users.await?; - this.update(&mut cx, |this, cx| { - this.potential_contacts = potential_contacts.into(); + picker.update(&mut cx, |picker, cx| { + picker.delegate_mut().potential_contacts = potential_contacts.into(); cx.notify(); - }); + })?; anyhow::Ok(()) } .log_err() @@ -75,7 +67,7 @@ impl PickerDelegate for ContactFinder { }) } - fn confirm(&mut self, cx: &mut ViewContext) { + fn confirm(&mut self, cx: &mut ViewContext>) { if let Some(user) = self.potential_contacts.get(self.selected_index) { let user_store = self.user_store.read(cx); match user_store.contact_request_status(user) { @@ -94,8 +86,8 @@ impl PickerDelegate for ContactFinder { } } - fn dismiss(&mut self, cx: &mut ViewContext) { - cx.emit(Event::Dismissed); + fn dismissed(&mut self, cx: &mut ViewContext>) { + cx.emit(PickerEvent::Dismiss); } fn render_match( @@ -104,7 +96,7 @@ impl PickerDelegate for ContactFinder { mouse_state: &mut MouseState, selected: bool, cx: &gpui::AppContext, - ) -> ElementBox { + ) -> Element> { let theme = &cx.global::().theme; let user = &self.potential_contacts[ix]; let request_status = self.user_store.read(cx).contact_request_status(user); @@ -164,28 +156,3 @@ impl PickerDelegate for ContactFinder { .boxed() } } - -impl ContactFinder { - pub fn new(user_store: ModelHandle, cx: &mut ViewContext) -> Self { - let this = cx.weak_handle(); - Self { - picker: cx.add_view(|cx| { - Picker::new("Search collaborator by username...", this, cx) - .with_theme(|theme| theme.contact_finder.picker.clone()) - }), - potential_contacts: Arc::from([]), - user_store, - selected_index: 0, - } - } - - pub fn editor_text(&self, cx: &AppContext) -> String { - self.picker.read(cx).query(cx) - } - - pub fn with_editor_text(self, editor_text: String, cx: &mut ViewContext) -> Self { - self.picker - .update(cx, |picker, cx| picker.set_query(editor_text, cx)); - self - } -} diff --git a/crates/collab_ui/src/contact_list.rs b/crates/collab_ui/src/contact_list.rs index adbc4d7ec8..76538b6a7e 100644 --- a/crates/collab_ui/src/contact_list.rs +++ b/crates/collab_ui/src/contact_list.rs @@ -11,7 +11,7 @@ use gpui::{ impl_actions, impl_internal_actions, keymap_matcher::KeymapContext, platform::{CursorStyle, MouseButton, PromptLevel}, - AppContext, Entity, ModelHandle, RenderContext, Subscription, View, ViewContext, ViewHandle, + AppContext, Entity, ModelHandle, Subscription, View, ViewContext, ViewHandle, }; use menu::{Confirm, SelectNext, SelectPrev}; use project::Project; @@ -159,7 +159,7 @@ pub enum Event { pub struct ContactList { entries: Vec, match_candidates: Vec, - list_state: ListState, + list_state: ListState, project: ModelHandle, user_store: ModelHandle, filter_editor: ViewHandle, @@ -202,7 +202,7 @@ impl ContactList { }) .detach(); - let list_state = ListState::new(0, Orientation::Top, 1000., cx, move |this, ix, cx| { + let list_state = ListState::::new(0, Orientation::Top, 1000., move |this, ix, cx| { let theme = cx.global::().theme.clone(); let is_selected = this.selection == Some(ix); let current_project_id = this.project.read(cx).remote_id(); @@ -748,7 +748,7 @@ impl ContactList { is_pending: bool, is_selected: bool, theme: &theme::ContactList, - ) -> ElementBox { + ) -> Element { Flex::row() .with_children(user.avatar.clone().map(|avatar| { Image::from_data(avatar) @@ -799,8 +799,8 @@ impl ContactList { is_last: bool, is_selected: bool, theme: &theme::ContactList, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { let font_cache = cx.font_cache(); let host_avatar_height = theme .contact_avatar @@ -819,7 +819,7 @@ impl ContactList { worktree_root_names.join(", ") }; - MouseEventHandler::::new(project_id as usize, cx, |mouse_state, _| { + MouseEventHandler::::new(project_id as usize, cx, |mouse_state, _| { let tree_branch = *tree_branch.style_for(mouse_state, is_selected); let row = theme.project_row.style_for(mouse_state, is_selected); @@ -827,14 +827,14 @@ impl ContactList { .with_child( Stack::new() .with_child( - Canvas::new(move |bounds, _, cx| { + Canvas::new(move |scene, bounds, _, _, _| { let start_x = bounds.min_x() + (bounds.width() / 2.) - (tree_branch.width / 2.); let end_x = bounds.max_x(); let start_y = bounds.min_y(); let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.); - cx.scene.push_quad(gpui::Quad { + scene.push_quad(gpui::Quad { bounds: RectF::from_points( vec2f(start_x, start_y), vec2f( @@ -846,7 +846,7 @@ impl ContactList { border: gpui::Border::default(), corner_radius: 0., }); - cx.scene.push_quad(gpui::Quad { + scene.push_quad(gpui::Quad { bounds: RectF::from_points( vec2f(start_x, end_y), vec2f(end_x, end_y + tree_branch.width), @@ -882,7 +882,7 @@ impl ContactList { } else { CursorStyle::Arrow }) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { if !is_current { cx.dispatch_global_action(JoinProject { project_id, @@ -898,8 +898,8 @@ impl ContactList { is_last: bool, is_selected: bool, theme: &theme::ContactList, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { let font_cache = cx.font_cache(); let host_avatar_height = theme .contact_avatar @@ -913,7 +913,7 @@ impl ContactList { let baseline_offset = row.name.text.baseline_offset(font_cache) + (theme.row_height - line_height) / 2.; - MouseEventHandler::::new( + MouseEventHandler::::new( peer_id.as_u64() as usize, cx, |mouse_state, _| { @@ -924,7 +924,7 @@ impl ContactList { .with_child( Stack::new() .with_child( - Canvas::new(move |bounds, _, cx| { + Canvas::new(move |scene, bounds, _, _, _| { let start_x = bounds.min_x() + (bounds.width() / 2.) - (tree_branch.width / 2.); let end_x = bounds.max_x(); @@ -932,7 +932,7 @@ impl ContactList { let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.); - cx.scene.push_quad(gpui::Quad { + scene.push_quad(gpui::Quad { bounds: RectF::from_points( vec2f(start_x, start_y), vec2f( @@ -944,7 +944,7 @@ impl ContactList { border: gpui::Border::default(), corner_radius: 0., }); - cx.scene.push_quad(gpui::Quad { + scene.push_quad(gpui::Quad { bounds: RectF::from_points( vec2f(start_x, end_y), vec2f(end_x, end_y + tree_branch.width), @@ -988,7 +988,7 @@ impl ContactList { }, ) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(OpenSharedScreen { peer_id }); }) .boxed() @@ -999,8 +999,8 @@ impl ContactList { theme: &theme::ContactList, is_selected: bool, is_collapsed: bool, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { enum Header {} enum LeaveCallContactList {} @@ -1015,14 +1015,14 @@ impl ContactList { }; let leave_call = if section == Section::ActiveCall { Some( - MouseEventHandler::::new(0, cx, |state, _| { + MouseEventHandler::::new(0, cx, |state, _| { let style = theme.leave_call.style_for(state, false); Label::new("Leave Call", style.text.clone()) .contained() .with_style(style.container) .boxed() }) - .on_click(MouseButton::Left, |_, cx| cx.dispatch_action(LeaveCall)) + .on_click(MouseButton::Left, |_, _, cx| cx.dispatch_action(LeaveCall)) .aligned() .boxed(), ) @@ -1031,7 +1031,7 @@ impl ContactList { }; let icon_size = theme.section_icon_size; - MouseEventHandler::
::new(section as usize, cx, |_, _| { + MouseEventHandler::::new(section as usize, cx, |_, _| { Flex::row() .with_child( Svg::new(if is_collapsed { @@ -1065,7 +1065,7 @@ impl ContactList { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(ToggleExpanded(section)) }) .boxed() @@ -1077,15 +1077,15 @@ impl ContactList { project: &ModelHandle, theme: &theme::ContactList, is_selected: bool, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { let online = contact.online; let busy = contact.busy || calling; let user_id = contact.user.id; let github_login = contact.user.github_login.clone(); let initial_project = project.clone(); let mut element = - MouseEventHandler::::new(contact.user.id as usize, cx, |_, cx| { + MouseEventHandler::::new(contact.user.id as usize, cx, |_, cx| { Flex::row() .with_children(contact.user.avatar.clone().map(|avatar| { let status_badge = if contact.online { @@ -1128,7 +1128,7 @@ impl ContactList { .boxed(), ) .with_child( - MouseEventHandler::::new( + MouseEventHandler::::new( contact.user.id as usize, cx, |mouse_state, _| { @@ -1142,7 +1142,7 @@ impl ContactList { ) .with_padding(Padding::uniform(2.)) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(RemoveContact { user_id, github_login: github_login.clone(), @@ -1172,7 +1172,7 @@ impl ContactList { ) .boxed() }) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { if online && !busy { cx.dispatch_action(Call { recipient_user_id: user_id, @@ -1194,8 +1194,8 @@ impl ContactList { theme: &theme::ContactList, is_incoming: bool, is_selected: bool, - cx: &mut RenderContext, - ) -> ElementBox { + cx: &mut ViewContext, + ) -> Element { enum Decline {} enum Accept {} enum Cancel {} @@ -1228,7 +1228,7 @@ impl ContactList { if is_incoming { row.add_children([ - MouseEventHandler::::new(user.id as usize, cx, |mouse_state, _| { + MouseEventHandler::::new(user.id as usize, cx, |mouse_state, _| { let button_style = if is_contact_request_pending { &theme.disabled_button } else { @@ -1239,7 +1239,7 @@ impl ContactList { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(RespondToContactRequest { user_id, accept: false, @@ -1248,7 +1248,7 @@ impl ContactList { .contained() .with_margin_right(button_spacing) .boxed(), - MouseEventHandler::::new(user.id as usize, cx, |mouse_state, _| { + MouseEventHandler::::new(user.id as usize, cx, |mouse_state, _| { let button_style = if is_contact_request_pending { &theme.disabled_button } else { @@ -1260,7 +1260,7 @@ impl ContactList { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(RespondToContactRequest { user_id, accept: true, @@ -1270,7 +1270,7 @@ impl ContactList { ]); } else { row.add_child( - MouseEventHandler::::new(user.id as usize, cx, |mouse_state, _| { + MouseEventHandler::::new(user.id as usize, cx, |mouse_state, _| { let button_style = if is_contact_request_pending { &theme.disabled_button } else { @@ -1283,7 +1283,7 @@ impl ContactList { }) .with_padding(Padding::uniform(2.)) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(RemoveContact { user_id, github_login: github_login.clone(), @@ -1331,7 +1331,7 @@ impl View for ContactList { cx } - fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> Element { enum AddContact {} let theme = cx.global::().theme.clone(); @@ -1346,7 +1346,7 @@ impl View for ContactList { .boxed(), ) .with_child( - MouseEventHandler::::new(0, cx, |_, _| { + MouseEventHandler::::new(0, cx, |_, _| { render_icon_button( &theme.contact_list.add_contact_button, "icons/user_plus_16.svg", @@ -1354,10 +1354,10 @@ impl View for ContactList { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, |_, cx| { + .on_click(MouseButton::Left, |_, _, cx| { cx.dispatch_action(contacts_popover::ToggleContactFinder) }) - .with_tooltip::( + .with_tooltip::( 0, "Search for new contact".into(), None, @@ -1387,7 +1387,7 @@ impl View for ContactList { } } -fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Element { +fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Drawable { Svg::new(svg_path) .with_color(style.color) .constrained() diff --git a/crates/collab_ui/src/contact_notification.rs b/crates/collab_ui/src/contact_notification.rs index 5badae695b..82f90041be 100644 --- a/crates/collab_ui/src/contact_notification.rs +++ b/crates/collab_ui/src/contact_notification.rs @@ -3,8 +3,7 @@ use std::sync::Arc; use crate::notifications::render_user_notification; use client::{ContactEventKind, User, UserStore}; use gpui::{ - elements::*, impl_internal_actions, AppContext, Entity, ModelHandle, RenderContext, View, - ViewContext, + elements::*, impl_internal_actions, AppContext, Entity, ModelHandle, View, ViewContext, }; use workspace::notifications::Notification; @@ -43,7 +42,7 @@ impl View for ContactNotification { "ContactNotification" } - fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> Element { match self.kind { ContactEventKind::Requested => render_user_notification( self.user.clone(), diff --git a/crates/collab_ui/src/contacts_popover.rs b/crates/collab_ui/src/contacts_popover.rs index 52925738b7..6cfe173a8d 100644 --- a/crates/collab_ui/src/contacts_popover.rs +++ b/crates/collab_ui/src/contacts_popover.rs @@ -1,9 +1,14 @@ -use crate::{contact_finder::ContactFinder, contact_list::ContactList, ToggleContactsMenu}; +use crate::{ + contact_finder::{build_contact_finder, ContactFinder}, + contact_list::ContactList, + ToggleContactsMenu, +}; use client::UserStore; use gpui::{ - actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, RenderContext, - View, ViewContext, ViewHandle, + actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, View, + ViewContext, ViewHandle, }; +use picker::PickerEvent; use project::Project; use settings::Settings; @@ -50,19 +55,19 @@ impl ContactsPopover { fn toggle_contact_finder(&mut self, _: &ToggleContactFinder, cx: &mut ViewContext) { match &self.child { Child::ContactList(list) => self.show_contact_finder(list.read(cx).editor_text(cx), cx), - Child::ContactFinder(finder) => { - self.show_contact_list(finder.read(cx).editor_text(cx), cx) - } + Child::ContactFinder(finder) => self.show_contact_list(finder.read(cx).query(cx), cx), } } fn show_contact_finder(&mut self, editor_text: String, cx: &mut ViewContext) { let child = cx.add_view(|cx| { - ContactFinder::new(self.user_store.clone(), cx).with_editor_text(editor_text, cx) + let finder = build_contact_finder(self.user_store.clone(), cx); + finder.set_query(editor_text, cx); + finder }); cx.focus(&child); self._subscription = Some(cx.subscribe(&child, |_, _, event, cx| match event { - crate::contact_finder::Event::Dismissed => cx.emit(Event::Dismissed), + PickerEvent::Dismiss => cx.emit(Event::Dismissed), })); self.child = Child::ContactFinder(child); cx.notify(); @@ -91,14 +96,14 @@ impl View for ContactsPopover { "ContactsPopover" } - fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> Element { let theme = cx.global::().theme.clone(); let child = match &self.child { Child::ContactList(child) => ChildView::new(child, cx), Child::ContactFinder(child) => ChildView::new(child, cx), }; - MouseEventHandler::::new(0, cx, |_, _| { + MouseEventHandler::::new(0, cx, |_, _| { Flex::column() .with_child(child.flex(1., true).boxed()) .contained() @@ -108,7 +113,7 @@ impl View for ContactsPopover { .with_height(theme.contacts_popover.height) .boxed() }) - .on_down_out(MouseButton::Left, move |_, cx| { + .on_down_out(MouseButton::Left, move |_, _, cx| { cx.dispatch_action(ToggleContactsMenu); }) .boxed() diff --git a/crates/collab_ui/src/face_pile.rs b/crates/collab_ui/src/face_pile.rs index 3b95443fee..c426e44804 100644 --- a/crates/collab_ui/src/face_pile.rs +++ b/crates/collab_ui/src/face_pile.rs @@ -7,12 +7,14 @@ use gpui::{ }, json::ToJson, serde_json::{self, json}, - Axis, DebugContext, Element, ElementBox, MeasurementContext, PaintContext, + Axis, Drawable, Element, SceneBuilder, ViewContext, }; +use crate::CollabTitlebarItem; + pub(crate) struct FacePile { overlap: f32, - faces: Vec, + faces: Vec>, } impl FacePile { @@ -24,20 +26,21 @@ impl FacePile { } } -impl Element for FacePile { +impl Drawable for FacePile { type LayoutState = (); type PaintState = (); fn layout( &mut self, constraint: gpui::SizeConstraint, - cx: &mut gpui::LayoutContext, + view: &mut CollabTitlebarItem, + cx: &mut ViewContext, ) -> (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 += face.layout(constraint, view, cx).x(); } width -= self.overlap * self.faces.len().saturating_sub(1) as f32; @@ -46,10 +49,12 @@ impl Element for FacePile { fn paint( &mut self, + scene: &mut SceneBuilder, bounds: RectF, visible_bounds: RectF, _layout: &mut Self::LayoutState, - cx: &mut PaintContext, + view: &mut CollabTitlebarItem, + cx: &mut ViewContext, ) -> Self::PaintState { let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); @@ -59,8 +64,8 @@ impl Element for FacePile { for face in self.faces.iter_mut().rev() { let size = face.size(); origin_x -= size.x(); - cx.paint_layer(None, |cx| { - face.paint(vec2f(origin_x, origin_y), visible_bounds, cx); + scene.paint_layer(None, |scene| { + face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx); }); origin_x += self.overlap; } @@ -75,7 +80,8 @@ impl Element for FacePile { _: RectF, _: &Self::LayoutState, _: &Self::PaintState, - _: &MeasurementContext, + _: &CollabTitlebarItem, + _: &ViewContext, ) -> Option { None } @@ -85,7 +91,8 @@ impl Element for FacePile { bounds: RectF, _: &Self::LayoutState, _: &Self::PaintState, - _: &DebugContext, + _: &CollabTitlebarItem, + _: &ViewContext, ) -> serde_json::Value { json!({ "type": "FacePile", @@ -94,8 +101,8 @@ impl Element for FacePile { } } -impl Extend for FacePile { - fn extend>(&mut self, children: T) { +impl Extend> for FacePile { + fn extend>>(&mut self, children: T) { self.faces.extend(children); } } diff --git a/crates/collab_ui/src/incoming_call_notification.rs b/crates/collab_ui/src/incoming_call_notification.rs index 58c42f919f..02767daf95 100644 --- a/crates/collab_ui/src/incoming_call_notification.rs +++ b/crates/collab_ui/src/incoming_call_notification.rs @@ -6,7 +6,7 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f}, impl_internal_actions, platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions}, - AppContext, Entity, RenderContext, View, ViewContext, + AppContext, Element, Entity, View, ViewContext, }; use settings::Settings; use util::ResultExt; @@ -99,7 +99,7 @@ impl IncomingCallNotification { } } - fn render_caller(&self, cx: &mut RenderContext) -> ElementBox { + fn render_caller(&self, cx: &mut ViewContext) -> Element { let theme = &cx.global::().theme.incoming_call_notification; let default_project = proto::ParticipantProject::default(); let initial_project = self @@ -165,13 +165,13 @@ impl IncomingCallNotification { .boxed() } - fn render_buttons(&self, cx: &mut RenderContext) -> ElementBox { + fn render_buttons(&self, cx: &mut ViewContext) -> Element { enum Accept {} enum Decline {} Flex::column() .with_child( - MouseEventHandler::::new(0, cx, |_, cx| { + MouseEventHandler::::new(0, cx, |_, cx| { let theme = &cx.global::().theme.incoming_call_notification; Label::new("Accept", theme.accept_button.text.clone()) .aligned() @@ -180,14 +180,14 @@ impl IncomingCallNotification { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, |_, cx| { + .on_click(MouseButton::Left, |_, _, cx| { cx.dispatch_action(RespondToCall { accept: true }); }) .flex(1., true) .boxed(), ) .with_child( - MouseEventHandler::::new(0, cx, |_, cx| { + MouseEventHandler::::new(0, cx, |_, cx| { let theme = &cx.global::().theme.incoming_call_notification; Label::new("Decline", theme.decline_button.text.clone()) .aligned() @@ -196,7 +196,7 @@ impl IncomingCallNotification { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, |_, cx| { + .on_click(MouseButton::Left, |_, _, cx| { cx.dispatch_action(RespondToCall { accept: false }); }) .flex(1., true) @@ -222,7 +222,7 @@ impl View for IncomingCallNotification { "IncomingCallNotification" } - fn render(&mut self, cx: &mut RenderContext) -> gpui::ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> Element { let background = cx .global::() .theme diff --git a/crates/collab_ui/src/notifications.rs b/crates/collab_ui/src/notifications.rs index 0353557681..e57c3bf793 100644 --- a/crates/collab_ui/src/notifications.rs +++ b/crates/collab_ui/src/notifications.rs @@ -2,7 +2,7 @@ use client::User; use gpui::{ elements::*, platform::{CursorStyle, MouseButton}, - Action, Element, ElementBox, RenderContext, View, + Action, Drawable, Element, View, ViewContext, }; use settings::Settings; use std::sync::Arc; @@ -16,8 +16,8 @@ pub fn render_user_notification( body: Option<&'static str>, dismiss_action: A, buttons: Vec<(&'static str, Box)>, - cx: &mut RenderContext, -) -> ElementBox { + cx: &mut ViewContext, +) -> Element { let theme = cx.global::().theme.clone(); let theme = &theme.contact_notification; @@ -51,7 +51,7 @@ pub fn render_user_notification( .boxed(), ) .with_child( - MouseEventHandler::::new(user.id as usize, cx, |state, _| { + MouseEventHandler::::new(user.id as usize, cx, |state, _| { let style = theme.dismiss_button.style_for(state, false); Svg::new("icons/x_mark_8.svg") .with_color(style.color) @@ -67,7 +67,7 @@ pub fn render_user_notification( }) .with_cursor_style(CursorStyle::PointingHand) .with_padding(Padding::uniform(5.)) - .on_click(MouseButton::Left, move |_, cx| { + .on_click(MouseButton::Left, move |_, _, cx| { cx.dispatch_any_action(dismiss_action.boxed_clone()) }) .aligned() @@ -96,7 +96,7 @@ pub fn render_user_notification( Flex::row() .with_children(buttons.into_iter().enumerate().map( |(ix, (message, action))| { - MouseEventHandler::