Detailed changes
@@ -304,7 +304,7 @@ impl ActivityIndicator {
impl EventEmitter<Event> for ActivityIndicator {}
impl Render for ActivityIndicator {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let content = self.content_to_render(cx);
let mut result = h_stack()
@@ -1101,7 +1101,7 @@ fn build_api_key_editor(cx: &mut ViewContext<AssistantPanel>) -> View<Editor> {
}
impl Render for AssistantPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
if let Some(api_key_editor) = self.api_key_editor.clone() {
v_stack()
.on_action(cx.listener(AssistantPanel::save_credentials))
@@ -1,5 +1,5 @@
use gpui::{
- div, DismissEvent, Element, EventEmitter, InteractiveElement, ParentElement, Render,
+ div, DismissEvent, EventEmitter, InteractiveElement, IntoElement, ParentElement, Render,
SemanticVersion, StatefulInteractiveElement, Styled, ViewContext,
};
use menu::Cancel;
@@ -13,7 +13,7 @@ pub struct UpdateNotification {
impl EventEmitter<DismissEvent> for UpdateNotification {}
impl Render for UpdateNotification {
- fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
let app_name = cx.global::<ReleaseChannel>().display_name();
v_stack()
@@ -30,7 +30,7 @@ impl Breadcrumbs {
impl EventEmitter<ToolbarItemEvent> for Breadcrumbs {}
impl Render for Breadcrumbs {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let element = h_stack().text_ui();
let Some(active_item) = self.active_item.as_ref() else {
return element;
@@ -222,7 +222,7 @@ impl ChannelView {
impl EventEmitter<EditorEvent> for ChannelView {}
impl Render for ChannelView {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
self.editor.clone()
}
}
@@ -549,7 +549,7 @@ impl ChatPanel {
impl EventEmitter<Event> for ChatPanel {}
impl Render for ChatPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
.full()
.child(if self.client.user_id().is_some() {
@@ -3,7 +3,7 @@ use client::UserId;
use collections::HashMap;
use editor::{AnchorRangeExt, Editor};
use gpui::{
- AsyncWindowContext, Element, FocusableView, Model, Render, SharedString, Task, View,
+ AsyncWindowContext, FocusableView, IntoElement, Model, Render, SharedString, Task, View,
ViewContext, WeakView,
};
use language::{language_settings::SoftWrap, Buffer, BufferSnapshot, LanguageRegistry};
@@ -196,7 +196,7 @@ impl MessageEditor {
}
impl Render for MessageEditor {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
self.editor.to_any()
}
}
@@ -2323,7 +2323,7 @@ fn render_tree_branch(is_last: bool, cx: &mut WindowContext) -> impl IntoElement
}
impl Render for CollabPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack()
.key_context("CollabPanel")
.on_action(cx.listener(CollabPanel::cancel))
@@ -142,7 +142,7 @@ impl FocusableView for ChannelModal {
}
impl Render for ChannelModal {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let channel_store = self.channel_store.read(cx);
let Some(channel) = channel_store.channel_for_id(self.channel_id) else {
return div();
@@ -35,7 +35,7 @@ impl ContactFinder {
}
impl Render for ContactFinder {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack()
.elevation_3(cx)
.child(
@@ -56,7 +56,7 @@ pub struct CollabTitlebarItem {
}
impl Render for CollabTitlebarItem {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let room = ActiveCall::global(cx).read(cx).room().cloned();
let current_user = self.user_store.read(cx).current_user();
let client = self.client.clone();
@@ -1,5 +1,5 @@
use gpui::{
- div, AnyElement, Div, ElementId, IntoElement, ParentElement, RenderOnce, Styled, WindowContext,
+ div, AnyElement, ElementId, IntoElement, ParentElement, RenderOnce, Styled, WindowContext,
};
use smallvec::SmallVec;
@@ -9,9 +9,7 @@ pub struct FacePile {
}
impl RenderOnce for FacePile {
- type Output = Div;
-
- fn render(self, _: &mut WindowContext) -> Self::Output {
+ fn render(self, _: &mut WindowContext) -> impl IntoElement {
let player_count = self.faces.len();
let player_list = self.faces.into_iter().enumerate().map(|(ix, player)| {
let isnt_last = ix < player_count - 1;
@@ -540,7 +540,7 @@ impl NotificationPanel {
}
impl Render for NotificationPanel {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack()
.size_full()
.child(
@@ -708,7 +708,7 @@ impl NotificationToast {
}
impl Render for NotificationToast {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let user = self.actor.clone();
h_stack()
@@ -117,7 +117,7 @@ impl IncomingCallNotification {
}
impl Render for IncomingCallNotification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
// TODO: Is there a better place for us to initialize the font?
let (ui_font, ui_font_size) = {
let theme_settings = ThemeSettings::get_global(cx);
@@ -118,7 +118,7 @@ impl ProjectSharedNotification {
}
impl Render for ProjectSharedNotification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
// TODO: Is there a better place for us to initialize the font?
let (ui_font, ui_font_size) = {
let theme_settings = ThemeSettings::get_global(cx);
@@ -83,7 +83,7 @@ impl FocusableView for CommandPalette {
}
impl Render for CommandPalette {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack().w(rems(34.)).child(self.picker.clone())
}
}
@@ -181,7 +181,7 @@ impl CopilotCodeVerification {
}
impl Render for CopilotCodeVerification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let prompt = match &self.status {
Status::SigningIn {
prompt: Some(prompt),
@@ -3,7 +3,7 @@ use copilot::{Copilot, SignOut, Status};
use editor::{scroll::autoscroll::Autoscroll, Editor};
use fs::Fs;
use gpui::{
- div, Action, AnchorCorner, AppContext, AsyncWindowContext, Element, Entity, ParentElement,
+ div, Action, AnchorCorner, AppContext, AsyncWindowContext, Entity, IntoElement, ParentElement,
Render, Subscription, View, ViewContext, WeakView, WindowContext,
};
use language::{
@@ -34,7 +34,7 @@ pub struct CopilotButton {
}
impl Render for CopilotButton {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let all_language_settings = all_language_settings(None, cx);
if !all_language_settings.copilot.feature_enabled {
return div();
@@ -21,7 +21,7 @@ pub struct DiagnosticIndicator {
}
impl Render for DiagnosticIndicator {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) {
(0, 0) => h_stack().child(
IconElement::new(Icon::Check)
@@ -9,7 +9,7 @@ pub struct ToolbarControls {
}
impl Render for ToolbarControls {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let include_warnings = self
.editor
.as_ref()
@@ -9287,7 +9287,7 @@ impl FocusableView for Editor {
}
impl Render for Editor {
- fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl 'static + Element {
+ fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = match self.mode {
EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
@@ -1193,7 +1193,7 @@ impl CursorPosition {
}
impl Render for CursorPosition {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
div().when_some(self.position, |el, position| {
let mut text = format!(
"{}{FILE_ROW_COLUMN_DELIMITER}{}",
@@ -17,7 +17,7 @@ impl DeployFeedbackButton {
}
impl Render for DeployFeedbackButton {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let is_open = self
.workspace
.upgrade()
@@ -396,7 +396,7 @@ impl FeedbackModal {
}
impl Render for FeedbackModal {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
self.update_submission_state(cx);
let submit_button_text = if self.awaiting_submission() {
@@ -118,7 +118,7 @@ impl FocusableView for FileFinder {
}
}
impl Render for FileFinder {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack().w(rems(34.)).child(self.picker.clone())
}
}
@@ -152,7 +152,7 @@ impl GoToLine {
}
impl Render for GoToLine {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
.elevation_2(cx)
.key_context("GoToLine")
@@ -1,7 +1,7 @@
use crate::{
div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
- BackgroundExecutor, Bounds, ClipboardItem, Context, Element, Entity, EventEmitter,
- ForegroundExecutor, InputEvent, KeyDownEvent, Keystroke, Model, ModelContext, Pixels, Platform,
+ BackgroundExecutor, Bounds, ClipboardItem, Context, Entity, EventEmitter, ForegroundExecutor,
+ InputEvent, IntoElement, KeyDownEvent, Keystroke, Model, ModelContext, Pixels, Platform,
PlatformWindow, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow,
TestWindowHandlers, TextSystem, View, ViewContext, VisualContext, WindowBounds, WindowContext,
WindowHandle, WindowOptions,
@@ -731,7 +731,7 @@ impl AnyWindowHandle {
pub struct EmptyView {}
impl Render for EmptyView {
- fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> impl IntoElement {
div()
}
}
@@ -6,6 +6,10 @@ use derive_more::{Deref, DerefMut};
pub(crate) use smallvec::SmallVec;
use std::{any::Any, fmt::Debug};
+/// Implemented by types that participate in laying out and painting the contents of a window.
+/// Elements form a tree and are laid out according to web-based layout rules.
+/// Rather than calling methods on implementers of this trait directly, you'll usually call `into_any` to convert them into an AnyElement, which manages state internally.
+/// You can create custom elements by implementing this trait.
pub trait Element: 'static + IntoElement {
type State: 'static;
@@ -107,15 +111,13 @@ pub trait IntoElement: Sized {
}
pub trait Render: 'static + Sized {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element;
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement;
}
/// You can derive [IntoElement] on any type that implements this trait.
/// It is used to allow views to be expressed in terms of abstract data.
pub trait RenderOnce: 'static {
- type Output: IntoElement;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output;
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement;
}
pub trait ParentElement {
@@ -139,62 +141,29 @@ pub trait ParentElement {
}
}
-pub struct Component<C> {
- component: Option<C>,
-}
-
-pub struct ComponentState<C: RenderOnce> {
- rendered_element: Option<<C::Output as IntoElement>::Element>,
- rendered_element_state: Option<<<C::Output as IntoElement>::Element as Element>::State>,
-}
+pub struct Component<C: RenderOnce>(Option<C>);
-impl<C> Component<C> {
+impl<C: RenderOnce> Component<C> {
pub fn new(component: C) -> Self {
- Component {
- component: Some(component),
- }
+ Component(Some(component))
}
}
impl<C: RenderOnce> Element for Component<C> {
- type State = ComponentState<C>;
+ type State = AnyElement;
fn request_layout(
&mut self,
- state: Option<Self::State>,
+ _: Option<Self::State>,
cx: &mut WindowContext,
) -> (LayoutId, Self::State) {
- let mut element = self.component.take().unwrap().render(cx).into_element();
- if let Some(element_id) = element.element_id() {
- let layout_id =
- cx.with_element_state(element_id, |state, cx| element.request_layout(state, cx));
- let state = ComponentState {
- rendered_element: Some(element),
- rendered_element_state: None,
- };
- (layout_id, state)
- } else {
- let (layout_id, state) =
- element.request_layout(state.and_then(|s| s.rendered_element_state), cx);
- let state = ComponentState {
- rendered_element: Some(element),
- rendered_element_state: Some(state),
- };
- (layout_id, state)
- }
+ let mut element = self.0.take().unwrap().render(cx).into_any_element();
+ let layout_id = element.request_layout(cx);
+ (layout_id, element)
}
- fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
- let mut element = state.rendered_element.take().unwrap();
- if let Some(element_id) = element.element_id() {
- cx.with_element_state(element_id, |element_state, cx| {
- let mut element_state = element_state.unwrap();
- element.paint(bounds, &mut element_state, cx);
- ((), element_state)
- });
- } else {
- element.paint(bounds, state.rendered_element_state.as_mut().unwrap(), cx);
- }
+ fn paint(&mut self, _: Bounds<Pixels>, element: &mut Self::State, cx: &mut WindowContext) {
+ element.paint(cx)
}
}
@@ -216,7 +185,7 @@ pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
trait ElementObject {
fn element_id(&self) -> Option<ElementId>;
- fn layout(&mut self, cx: &mut WindowContext) -> LayoutId;
+ fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId;
fn paint(&mut self, cx: &mut WindowContext);
@@ -391,7 +360,7 @@ where
self.as_ref().unwrap().element_id()
}
- fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
+ fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId {
DrawableElement::request_layout(self.as_mut().unwrap(), cx)
}
@@ -431,8 +400,8 @@ impl AnyElement {
AnyElement(element)
}
- pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
- self.0.layout(cx)
+ pub fn request_layout(&mut self, cx: &mut WindowContext) -> LayoutId {
+ self.0.request_layout(cx)
}
pub fn paint(&mut self, cx: &mut WindowContext) {
@@ -471,7 +440,7 @@ impl Element for AnyElement {
_: Option<Self::State>,
cx: &mut WindowContext,
) -> (LayoutId, Self::State) {
- let layout_id = self.layout(cx);
+ let layout_id = self.request_layout(cx);
(layout_id, ())
}
@@ -781,7 +781,7 @@ impl Element for Div {
child_layout_ids = self
.children
.iter_mut()
- .map(|child| child.layout(cx))
+ .map(|child| child.request_layout(cx))
.collect::<SmallVec<_>>();
cx.request_layout(&style, child_layout_ids.iter().copied())
})
@@ -68,7 +68,7 @@ impl Element for Overlay {
let child_layout_ids = self
.children
.iter_mut()
- .map(|child| child.layout(cx))
+ .map(|child| child.request_layout(cx))
.collect::<SmallVec<_>>();
let overlay_style = Style {
@@ -205,7 +205,7 @@ impl ExternalPaths {
}
impl Render for ExternalPaths {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
div() // Intentionally left empty because the platform will render icons for the dragged files
}
}
@@ -87,7 +87,7 @@ impl<V: Render> Element for View<V> {
cx: &mut WindowContext,
) -> (LayoutId, Self::State) {
let mut element = self.update(cx, |view, cx| view.render(cx).into_any_element());
- let layout_id = element.layout(cx);
+ let layout_id = element.request_layout(cx);
(layout_id, Some(element))
}
@@ -321,7 +321,7 @@ mod any_view {
) -> (LayoutId, AnyElement) {
let view = view.clone().downcast::<V>().unwrap();
let mut element = view.update(cx, |view, cx| view.render(cx).into_any_element());
- let layout_id = element.layout(cx);
+ let layout_id = element.request_layout(cx);
(layout_id, element)
}
@@ -1,7 +1,5 @@
use editor::Editor;
-use gpui::{
- div, Element, IntoElement, ParentElement, Render, Subscription, View, ViewContext, WeakView,
-};
+use gpui::{div, IntoElement, ParentElement, Render, Subscription, View, ViewContext, WeakView};
use std::sync::Arc;
use ui::{Button, ButtonCommon, Clickable, LabelSize, Tooltip};
use workspace::{item::ItemHandle, StatusItemView, Workspace};
@@ -38,7 +36,7 @@ impl ActiveBufferLanguage {
}
impl Render for ActiveBufferLanguage {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
div().when_some(self.active_language.as_ref(), |el, active_language| {
let active_language_text = if let Some(active_language_text) = active_language {
active_language_text.to_string()
@@ -67,7 +67,7 @@ impl LanguageSelector {
}
impl Render for LanguageSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack().w(rems(34.)).child(self.picker.clone())
}
}
@@ -2,9 +2,9 @@ use collections::{HashMap, VecDeque};
use editor::{Editor, EditorEvent, MoveToEnd};
use futures::{channel::mpsc, StreamExt};
use gpui::{
- actions, div, AnchorCorner, AnyElement, AppContext, Context, Element, EventEmitter,
- FocusHandle, FocusableView, IntoElement, Model, ModelContext, ParentElement, Render, Styled,
- Subscription, View, ViewContext, VisualContext, WeakModel, WindowContext,
+ actions, div, AnchorCorner, AnyElement, AppContext, Context, EventEmitter, FocusHandle,
+ FocusableView, IntoElement, Model, ModelContext, ParentElement, Render, Styled, Subscription,
+ View, ViewContext, VisualContext, WeakModel, WindowContext,
};
use language::{LanguageServerId, LanguageServerName};
use lsp::IoKind;
@@ -595,9 +595,9 @@ fn log_contents(lines: &VecDeque<String>) -> String {
}
impl Render for LspLogView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
self.editor
- .update(cx, |editor, cx| editor.render(cx).into_any())
+ .update(cx, |editor, cx| editor.render(cx).into_any_element())
}
}
@@ -708,7 +708,7 @@ impl ToolbarItemView for LspLogToolbarItemView {
}
impl Render for LspLogToolbarItemView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let Some(log_view) = self.log_view.clone() else {
return div();
};
@@ -1,6 +1,6 @@
use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId};
use gpui::{
- actions, canvas, div, rems, uniform_list, AnyElement, AppContext, AvailableSpace, Div, Element,
+ actions, canvas, div, rems, uniform_list, AnyElement, AppContext, AvailableSpace, Div,
EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model,
MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Render, Styled,
UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext,
@@ -305,7 +305,7 @@ impl SyntaxTreeView {
}
impl Render for SyntaxTreeView {
- fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> impl Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let line_height = cx
.text_style()
@@ -505,7 +505,7 @@ fn format_node_range(node: Node) -> String {
}
impl Render for SyntaxTreeToolbarItemView {
- fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> impl IntoElement {
self.render_menu(cx)
.unwrap_or_else(|| popover_menu("Empty Syntax Tree"))
}
@@ -57,7 +57,7 @@ impl EventEmitter<DismissEvent> for OutlineView {}
impl ModalView for OutlineView {}
impl Render for OutlineView {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack().w(rems(34.)).child(self.picker.clone())
}
}
@@ -235,7 +235,7 @@ impl<D: PickerDelegate> EventEmitter<DismissEvent> for Picker<D> {}
impl<D: PickerDelegate> ModalView for Picker<D> {}
impl<D: PickerDelegate> Render for Picker<D> {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let picker_editor = h_stack()
.overflow_hidden()
.flex_none()
@@ -1480,7 +1480,7 @@ impl ProjectPanel {
}
impl Render for ProjectPanel {
- fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
let has_worktree = self.visible_entries.len() != 0;
if has_worktree {
@@ -36,7 +36,7 @@ impl QuickActionBar {
}
impl Render for QuickActionBar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let Some(editor) = self.active_editor() else {
return div().id("empty quick action bar");
};
@@ -136,9 +136,7 @@ impl QuickActionBarButton {
}
impl RenderOnce for QuickActionBarButton {
- type Output = IconButton;
-
- fn render(self, _: &mut WindowContext) -> Self::Output {
+ fn render(self, _: &mut WindowContext) -> impl IntoElement {
let tooltip = self.tooltip.clone();
let action = self.action.boxed_clone();
@@ -43,9 +43,7 @@ impl HighlightedText {
}
impl RenderOnce for HighlightedText {
- type Output = HighlightedLabel;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
HighlightedLabel::new(self.text, self.highlight_positions)
}
}
@@ -103,7 +103,7 @@ impl FocusableView for RecentProjects {
}
impl Render for RecentProjects {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack()
.w(rems(self.rem_width))
.child(self.picker.clone())
@@ -101,7 +101,7 @@ impl BufferSearchBar {
impl EventEmitter<Event> for BufferSearchBar {}
impl EventEmitter<workspace::ToolbarItemEvent> for BufferSearchBar {}
impl Render for BufferSearchBar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
if self.dismissed {
return div();
}
@@ -279,7 +279,7 @@ pub enum ViewEvent {
impl EventEmitter<ViewEvent> for ProjectSearchView {}
impl Render for ProjectSearchView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
if self.has_matches() {
div()
.flex_1()
@@ -1548,7 +1548,7 @@ impl ProjectSearchBar {
}
impl Render for ProjectSearchBar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let Some(search) = self.active_project_search.clone() else {
return div();
};
@@ -1,6 +1,5 @@
use gpui::{
- div, hsla, prelude::*, px, rems, AnyElement, Div, ElementId, Hsla, SharedString, Stateful,
- WindowContext,
+ div, hsla, prelude::*, px, rems, AnyElement, Div, ElementId, Hsla, SharedString, WindowContext,
};
use itertools::Itertools;
use smallvec::SmallVec;
@@ -74,9 +73,7 @@ impl ParentElement for StoryContainer {
}
impl RenderOnce for StoryContainer {
- type Output = Stateful<Div>;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
div()
.size_full()
.flex()
@@ -294,9 +291,7 @@ impl StoryItem {
}
impl RenderOnce for StoryItem {
- type Output = Div;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
div()
.my_2()
.flex()
@@ -358,9 +353,7 @@ impl StorySection {
}
impl RenderOnce for StorySection {
- type Output = Div;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
let children: SmallVec<[AnyElement; 2]> = SmallVec::from_iter(Itertools::intersperse_with(
self.children.into_iter(),
|| Story::divider().into_any_element(),
@@ -1,6 +1,6 @@
use editor::Editor;
use gpui::{
- div, white, Element, KeyBinding, ParentElement, Render, Styled, View, ViewContext,
+ div, white, IntoElement, KeyBinding, ParentElement, Render, Styled, View, ViewContext,
VisualContext, WindowContext,
};
@@ -22,7 +22,7 @@ impl AutoHeightEditorStory {
}
impl Render for AutoHeightEditorStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
.size_full()
.bg(white())
@@ -5,7 +5,7 @@ use ui::prelude::*;
pub struct CursorStory;
impl Render for CursorStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
let all_cursors: [(&str, Box<dyn Fn(Stateful<Div>) -> Stateful<Div>>); 19] = [
(
"cursor_default",
@@ -56,7 +56,7 @@ impl FocusStory {
}
impl Render for FocusStory {
- fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
let theme = cx.theme();
let color_1 = theme.status().created;
let color_2 = theme.status().modified;
@@ -14,7 +14,7 @@ impl KitchenSinkStory {
}
impl Render for KitchenSinkStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let component_stories = ComponentStory::iter()
.map(|selector| selector.story(cx))
.collect::<Vec<_>>();
@@ -6,7 +6,7 @@ use ui::prelude::*;
pub struct OverflowScrollStory;
impl Render for OverflowScrollStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title("Overflow Scroll"))
.child(Story::label("`overflow_x_scroll`"))
@@ -200,7 +200,7 @@ impl PickerStory {
}
impl Render for PickerStory {
- fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
div()
.bg(cx.theme().styles.colors.background)
.size_full()
@@ -11,7 +11,7 @@ impl ScrollStory {
}
impl Render for ScrollStory {
- fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
let theme = cx.theme();
let color_1 = theme.status().created;
let color_2 = theme.status().modified;
@@ -1,6 +1,6 @@
use gpui::{
- div, green, red, Element, HighlightStyle, InteractiveText, IntoElement, ParentElement, Render,
- Styled, StyledText, View, VisualContext, WindowContext,
+ div, green, red, HighlightStyle, InteractiveText, IntoElement, ParentElement, Render, Styled,
+ StyledText, View, VisualContext, WindowContext,
};
use indoc::indoc;
use story::*;
@@ -14,7 +14,7 @@ impl TextStory {
}
impl Render for TextStory {
- fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
StoryContainer::new("Text Story", "crates/storybook2/src/stories/text.rs")
.children(
vec![
@@ -6,7 +6,7 @@ use ui::prelude::*;
pub struct ViewportUnitsStory;
impl Render for ViewportUnitsStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container().child(
div()
.flex()
@@ -7,7 +7,7 @@ use ui::prelude::*;
pub struct ZIndexStory;
impl Render for ZIndexStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container().child(Story::title("z-index")).child(
div()
.flex()
@@ -80,9 +80,7 @@ struct ZIndexExample {
}
impl RenderOnce for ZIndexExample {
- type Output = Div;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
div()
.relative()
.size_full()
@@ -113,7 +113,7 @@ impl StoryWrapper {
}
impl Render for StoryWrapper {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
.flex()
.flex_col()
@@ -3,9 +3,9 @@ use std::{path::PathBuf, sync::Arc};
use crate::TerminalView;
use db::kvp::KEY_VALUE_STORE;
use gpui::{
- actions, div, serde_json, AppContext, AsyncWindowContext, Element, Entity, EventEmitter,
- ExternalPaths, FocusHandle, FocusableView, IntoElement, ParentElement, Pixels, Render, Styled,
- Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
+ actions, div, serde_json, AppContext, AsyncWindowContext, Entity, EventEmitter, ExternalPaths,
+ FocusHandle, FocusableView, IntoElement, ParentElement, Pixels, Render, Styled, Subscription,
+ Task, View, ViewContext, VisualContext, WeakView, WindowContext,
};
use project::Fs;
use serde::{Deserialize, Serialize};
@@ -329,7 +329,7 @@ impl TerminalPanel {
impl EventEmitter<PanelEvent> for TerminalPanel {}
impl Render for TerminalPanel {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
div().size_full().child(self.pane.clone())
}
}
@@ -617,7 +617,7 @@ impl TerminalView {
}
impl Render for TerminalView {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let terminal_handle = self.terminal.clone();
let focused = self.focus_handle.is_focused(cx);
@@ -7,7 +7,7 @@ use crate::{default_color_scales, ColorScaleStep};
pub struct ColorsStory;
impl Render for ColorsStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let color_scales = default_color_scales();
Story::container().child(Story::title("Colors")).child(
@@ -1,4 +1,4 @@
-use gpui::{div, img, px, Element, ParentElement, Render, Styled, ViewContext};
+use gpui::{div, img, px, IntoElement, ParentElement, Render, Styled, ViewContext};
use story::Story;
use crate::{ActiveTheme, PlayerColors};
@@ -6,7 +6,7 @@ use crate::{ActiveTheme, PlayerColors};
pub struct PlayerStory;
impl Render for PlayerStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container().child(
div()
.flex()
@@ -69,7 +69,7 @@ impl FocusableView for ThemeSelector {
}
impl Render for ThemeSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack().w(rems(34.)).child(self.picker.clone())
}
}
@@ -1,5 +1,5 @@
use crate::prelude::*;
-use gpui::{img, Div, Hsla, ImageSource, Img, IntoElement, Styled};
+use gpui::{img, Hsla, ImageSource, Img, IntoElement, Styled};
#[derive(Debug, Default, PartialEq, Clone)]
pub enum Shape {
@@ -16,9 +16,7 @@ pub struct Avatar {
}
impl RenderOnce for Avatar {
- type Output = Div;
-
- fn render(mut self, cx: &mut WindowContext) -> Self::Output {
+ fn render(mut self, cx: &mut WindowContext) -> impl IntoElement {
if self.image.style().corner_radii.top_left.is_none() {
self = self.shape(Shape::Circle);
}
@@ -136,9 +136,8 @@ impl ButtonCommon for Button {
}
impl RenderOnce for Button {
- type Output = ButtonLike;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ #[allow(refining_impl_trait)]
+ fn render(self, _cx: &mut WindowContext) -> ButtonLike {
let is_disabled = self.base.disabled;
let is_selected = self.base.selected;
@@ -63,9 +63,7 @@ impl Selectable for ButtonIcon {
}
impl RenderOnce for ButtonIcon {
- type Output = IconElement;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
let icon = self
.selected_icon
.filter(|_| self.selected)
@@ -1,5 +1,5 @@
use gpui::{relative, DefiniteLength, MouseButton};
-use gpui::{rems, transparent_black, AnyElement, AnyView, ClickEvent, Div, Hsla, Rems, Stateful};
+use gpui::{rems, transparent_black, AnyElement, AnyView, ClickEvent, Hsla, Rems};
use smallvec::SmallVec;
use crate::prelude::*;
@@ -363,9 +363,7 @@ impl ParentElement for ButtonLike {
}
impl RenderOnce for ButtonLike {
- type Output = Stateful<Div>;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
self.base
.h_flex()
.id(self.id.clone())
@@ -106,9 +106,7 @@ impl VisibleOnHover for IconButton {
}
impl RenderOnce for IconButton {
- type Output = ButtonLike;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
let is_disabled = self.base.disabled;
let is_selected = self.base.selected;
@@ -99,9 +99,7 @@ impl ButtonCommon for ToggleButton {
}
impl RenderOnce for ToggleButton {
- type Output = ButtonLike;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
let is_disabled = self.base.disabled;
let is_selected = self.base.selected;
@@ -1,4 +1,4 @@
-use gpui::{div, prelude::*, Div, Element, ElementId, IntoElement, Styled, WindowContext};
+use gpui::{div, prelude::*, Element, ElementId, IntoElement, Styled, WindowContext};
use crate::prelude::*;
use crate::{Color, Icon, IconElement, Selection};
@@ -19,9 +19,7 @@ pub struct Checkbox {
}
impl RenderOnce for Checkbox {
- type Output = gpui::Stateful<Div>;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let group_id = format!("checkbox_group_{:?}", self.id);
let icon = match self.checked {
@@ -232,7 +232,7 @@ impl ContextMenuItem {
}
impl Render for ContextMenu {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
div().elevation_2(cx).flex().flex_row().child(
v_stack()
.min_w(px(200.))
@@ -28,9 +28,7 @@ impl Disclosure {
}
impl RenderOnce for Disclosure {
- type Output = IconButton;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
IconButton::new(
self.id,
match self.is_open {
@@ -1,4 +1,4 @@
-use gpui::{Div, Hsla, IntoElement};
+use gpui::{Hsla, IntoElement};
use crate::prelude::*;
@@ -31,9 +31,7 @@ pub struct Divider {
}
impl RenderOnce for Divider {
- type Output = Div;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
div()
.map(|this| match self.direction {
DividerDirection::Horizontal => {
@@ -1,4 +1,4 @@
-use gpui::{rems, svg, IntoElement, Rems, Svg};
+use gpui::{rems, svg, IntoElement, Rems};
use strum::EnumIter;
use crate::prelude::*;
@@ -200,9 +200,7 @@ pub struct IconElement {
}
impl RenderOnce for IconElement {
- type Output = Svg;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
svg()
.size(self.size.rems())
.flex_none()
@@ -1,4 +1,4 @@
-use gpui::{Div, Position};
+use gpui::Position;
use crate::prelude::*;
@@ -45,9 +45,7 @@ impl Indicator {
}
impl RenderOnce for Indicator {
- type Output = Div;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
div()
.flex_none()
.map(|this| match self.style {
@@ -1,5 +1,5 @@
use crate::{h_stack, prelude::*, Icon, IconElement, IconSize};
-use gpui::{relative, rems, Action, Div, FocusHandle, IntoElement, Keystroke};
+use gpui::{relative, rems, Action, FocusHandle, IntoElement, Keystroke};
#[derive(IntoElement, Clone)]
pub struct KeyBinding {
@@ -11,9 +11,7 @@ pub struct KeyBinding {
}
impl RenderOnce for KeyBinding {
- type Output = Div;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
h_stack()
.flex_none()
.gap_2()
@@ -87,9 +85,7 @@ pub struct Key {
}
impl RenderOnce for Key {
- type Output = Div;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let single_char = self.key.len() == 1;
div()
@@ -121,9 +117,7 @@ pub struct KeyIcon {
}
impl RenderOnce for KeyIcon {
- type Output = Div;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
div()
.w(rems(14. / 16.))
.child(IconElement::new(self.icon).size(IconSize::Small))
@@ -46,9 +46,7 @@ impl LabelCommon for HighlightedLabel {
}
impl RenderOnce for HighlightedLabel {
- type Output = LabelLike;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let highlight_color = cx.theme().colors().text_accent;
let mut highlight_indices = self.highlight_indices.iter().copied().peekable();
@@ -40,9 +40,7 @@ impl LabelCommon for Label {
}
impl RenderOnce for Label {
- type Output = LabelLike;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
self.base.child(self.label)
}
}
@@ -1,4 +1,4 @@
-use gpui::{relative, AnyElement, Div, Styled};
+use gpui::{relative, AnyElement, Styled};
use smallvec::SmallVec;
use crate::prelude::*;
@@ -76,9 +76,7 @@ impl ParentElement for LabelLike {
}
impl RenderOnce for LabelLike {
- type Output = Div;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
div()
.when(self.strikethrough, |this| {
this.relative().child(
@@ -1,4 +1,4 @@
-use gpui::{AnyElement, Div};
+use gpui::AnyElement;
use smallvec::SmallVec;
use crate::{prelude::*, v_stack, Label, ListHeader};
@@ -46,9 +46,7 @@ impl ParentElement for List {
}
impl RenderOnce for List {
- type Output = Div;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
v_stack().w_full().py_1().children(self.header).map(|this| {
match (self.children.is_empty(), self.toggle) {
(false, _) => this.children(self.children),
@@ -1,6 +1,5 @@
-use gpui::{AnyElement, ClickEvent, Div, Stateful};
-
use crate::{h_stack, prelude::*, Disclosure, Label};
+use gpui::{AnyElement, ClickEvent};
#[derive(IntoElement)]
pub struct ListHeader {
@@ -76,9 +75,7 @@ impl Selectable for ListHeader {
}
impl RenderOnce for ListHeader {
- type Output = Stateful<Div>;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
h_stack()
.id(self.label.clone())
.w_full()
@@ -1,6 +1,4 @@
-use gpui::{
- px, AnyElement, AnyView, ClickEvent, Div, MouseButton, MouseDownEvent, Pixels, Stateful,
-};
+use gpui::{px, AnyElement, AnyView, ClickEvent, MouseButton, MouseDownEvent, Pixels};
use smallvec::SmallVec;
use crate::{prelude::*, Disclosure};
@@ -147,9 +145,7 @@ impl ParentElement for ListItem {
}
impl RenderOnce for ListItem {
- type Output = Stateful<Div>;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
h_stack()
.id(self.id)
.w_full()
@@ -1,14 +1,10 @@
-use gpui::Div;
-
use crate::prelude::*;
#[derive(IntoElement)]
pub struct ListSeparator;
impl RenderOnce for ListSeparator {
- type Output = Div;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
div()
.h_px()
.w_full()
@@ -1,5 +1,3 @@
-use gpui::Div;
-
use crate::prelude::*;
use crate::{h_stack, Icon, IconElement, IconSize, Label};
@@ -26,9 +24,7 @@ impl ListSubHeader {
}
impl RenderOnce for ListSubHeader {
- type Output = Div;
-
- fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
h_stack().flex_1().w_full().relative().py_1().child(
div()
.h_6()
@@ -1,5 +1,5 @@
use gpui::{
- div, AnyElement, Div, Element, ElementId, IntoElement, ParentElement, RenderOnce, Styled,
+ div, AnyElement, Element, ElementId, IntoElement, ParentElement, RenderOnce, Styled,
WindowContext,
};
use smallvec::SmallVec;
@@ -41,9 +41,7 @@ pub struct Popover {
}
impl RenderOnce for Popover {
- type Output = Div;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
div()
.flex()
.gap_1()
@@ -153,7 +153,7 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
}
let mut element = overlay.child(menu.clone()).into_any();
- menu_layout_id = Some(element.layout(cx));
+ menu_layout_id = Some(element.request_layout(cx));
element
});
@@ -164,7 +164,7 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
let child_layout_id = child_element
.as_mut()
- .map(|child_element| child_element.layout(cx));
+ .map(|child_element| child_element.request_layout(cx));
let layout_id = cx.request_layout(
&gpui::Style::default(),
@@ -81,7 +81,7 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
overlay = overlay.position(*position.borrow());
let mut element = overlay.child(menu.clone()).into_any();
- menu_layout_id = Some(element.layout(cx));
+ menu_layout_id = Some(element.request_layout(cx));
element
});
@@ -92,7 +92,7 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
let child_layout_id = child_element
.as_mut()
- .map(|child_element| child_element.layout(cx));
+ .map(|child_element| child_element.request_layout(cx));
let layout_id = cx.request_layout(
&gpui::Style::default(),
@@ -7,7 +7,7 @@ use crate::Avatar;
pub struct AvatarStory;
impl Render for AvatarStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Avatar>())
.child(Story::label("Default"))
@@ -7,7 +7,7 @@ use crate::{Button, ButtonStyle};
pub struct ButtonStory;
impl Render for ButtonStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Button>())
.child(Story::label("Default"))
@@ -7,7 +7,7 @@ use crate::{h_stack, Checkbox};
pub struct CheckboxStory;
impl Render for CheckboxStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Checkbox>())
.child(Story::label("Default"))
@@ -20,7 +20,7 @@ fn build_menu(cx: &mut WindowContext, header: impl Into<SharedString>) -> View<C
pub struct ContextMenuStory;
impl Render for ContextMenuStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.on_action(|_: &PrintCurrentDate, _| {
println!("printing unix time!");
@@ -7,7 +7,7 @@ use crate::Disclosure;
pub struct DisclosureStory;
impl Render for DisclosureStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Disclosure>())
.child(Story::label("Toggled"))
@@ -8,7 +8,7 @@ use crate::{Icon, IconElement};
pub struct IconStory;
impl Render for IconStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
let icons = Icon::iter();
Story::container()
@@ -7,7 +7,7 @@ use crate::{Icon, IconButton};
pub struct IconButtonStory;
impl Render for IconButtonStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
let default_button = StoryItem::new(
"Default",
IconButton::new("default_icon_button", Icon::Hash),
@@ -13,7 +13,7 @@ pub fn binding(key: &str) -> gpui::KeyBinding {
}
impl Render for KeybindingStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
let all_modifier_permutations = ["ctrl", "alt", "cmd", "shift"].into_iter().permutations(2);
Story::container()
@@ -5,7 +5,7 @@ use story::Story;
pub struct LabelStory;
impl Render for LabelStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Label>())
.child(Story::label("Default"))
@@ -7,7 +7,7 @@ use crate::{List, ListItem};
pub struct ListStory;
impl Render for ListStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<List>())
.child(Story::label("Default"))
@@ -7,7 +7,7 @@ use crate::{Icon, ListHeader};
pub struct ListHeaderStory;
impl Render for ListHeaderStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<ListHeader>())
.child(Story::label("Default"))
@@ -7,7 +7,7 @@ use crate::{Icon, ListItem};
pub struct ListItemStory;
impl Render for ListItemStory {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.bg(cx.theme().colors().background)
.child(Story::title_for::<ListItem>())
@@ -9,7 +9,7 @@ use crate::{Indicator, Tab};
pub struct TabStory;
impl Render for TabStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container()
.child(Story::title_for::<Tab>())
.child(Story::label("Default"))
@@ -6,7 +6,7 @@ use crate::{prelude::*, Tab, TabBar, TabPosition};
pub struct TabBarStory;
impl Render for TabBarStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
let tab_count = 20;
let selected_tab_index = 3;
@@ -6,7 +6,7 @@ use crate::{prelude::*, ToggleButton};
pub struct ToggleButtonStory;
impl Render for ToggleButtonStory {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
StoryContainer::new(
"Toggle Button",
"crates/ui2/src/components/stories/toggle_button.rs",
@@ -93,9 +93,8 @@ impl ParentElement for Tab {
}
impl RenderOnce for Tab {
- type Output = Stateful<Div>;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ #[allow(refining_impl_trait)]
+ fn render(self, cx: &mut WindowContext) -> Stateful<Div> {
let (text_color, tab_bg, _tab_hover_bg, _tab_active_bg) = match self.selected {
false => (
cx.theme().colors().text_muted,
@@ -1,4 +1,4 @@
-use gpui::{AnyElement, ScrollHandle, Stateful};
+use gpui::{AnyElement, ScrollHandle};
use smallvec::SmallVec;
use crate::prelude::*;
@@ -89,9 +89,7 @@ impl ParentElement for TabBar {
}
impl RenderOnce for TabBar {
- type Output = Stateful<Div>;
-
- fn render(self, cx: &mut WindowContext) -> Self::Output {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
const HEIGHT_IN_REMS: f32 = 30. / 16.;
div()
@@ -68,7 +68,7 @@ impl Tooltip {
}
impl Render for Tooltip {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone();
overlay().child(
// padding to avoid mouse cursor
@@ -65,7 +65,7 @@ impl FocusableView for BranchList {
}
impl Render for BranchList {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack()
.w(rems(self.rem_width))
.child(self.picker.clone())
@@ -47,7 +47,7 @@ impl ModeIndicator {
}
impl Render for ModeIndicator {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
let Some(mode) = self.mode.as_ref() else {
return div().into_any();
};
@@ -64,7 +64,7 @@ impl BaseKeymapSelector {
}
impl Render for BaseKeymapSelector {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
self.picker.clone()
}
}
@@ -58,7 +58,7 @@ pub struct WelcomePage {
}
impl Render for WelcomePage {
- fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
h_stack().full().track_focus(&self.focus_handle).child(
v_stack()
.w_96()
@@ -510,7 +510,7 @@ impl Dock {
}
impl Render for Dock {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
if let Some(entry) = self.visible_entry() {
let size = entry.panel.size(cx);
@@ -597,7 +597,7 @@ impl PanelButtons {
}
impl Render for PanelButtons {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
// todo!()
let dock = self.dock.read(cx);
let active_index = dock.active_panel_index;
@@ -719,7 +719,7 @@ pub mod test {
}
impl Render for TestPanel {
- fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
}
}
@@ -760,7 +760,7 @@ pub mod test {
use super::{Item, ItemEvent};
use crate::{ItemId, ItemNavHistory, Pane, Workspace, WorkspaceId};
use gpui::{
- AnyElement, AppContext, Context as _, Element, EntityId, EventEmitter, FocusableView,
+ AnyElement, AppContext, Context as _, EntityId, EventEmitter, FocusableView,
InteractiveElement, IntoElement, Model, Render, SharedString, Task, View, ViewContext,
VisualContext, WeakView,
};
@@ -910,7 +910,7 @@ pub mod test {
}
impl Render for TestItem {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
gpui::div().track_focus(&self.focus_handle)
}
}
@@ -104,7 +104,7 @@ impl ModalLayer {
}
impl Render for ModalLayer {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let Some(active_modal) = &self.active_modal else {
return div();
};
@@ -219,7 +219,7 @@ pub mod simple_message_notification {
}
impl Render for MessageNotification {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack()
.elevation_3(cx)
.p_4()
@@ -1867,7 +1867,7 @@ impl FocusableView for Pane {
}
impl Render for Pane {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_stack()
.key_context("Pane")
.track_focus(&self.focus_handle)
@@ -2746,7 +2746,7 @@ mod tests {
}
impl Render for DraggedTab {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone();
let item = &self.pane.read(cx).items[self.ix];
let label = item.tab_content(Some(self.detail), false, cx);
@@ -66,7 +66,7 @@ impl FocusableView for SharedScreen {
}
}
impl Render for SharedScreen {
- fn render(&mut self, _: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, _: &mut ViewContext<Self>) -> impl IntoElement {
div().track_focus(&self.focus).size_full().children(
self.frame
.as_ref()
@@ -33,7 +33,7 @@ pub struct StatusBar {
}
impl Render for StatusBar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
div()
.py_0p5()
.px_1()
@@ -93,7 +93,7 @@ impl Toolbar {
}
impl Render for Toolbar {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
if !self.has_any_visible_items() {
return div();
}
@@ -3487,7 +3487,7 @@ impl FocusableView for Workspace {
struct DraggedDock(DockPosition);
impl Render for Workspace {
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let mut context = KeyContext::default();
context.add("Workspace");
@@ -4305,7 +4305,7 @@ impl Element for DisconnectedOverlay {
"Your connection to the remote project has been lost.",
))
.into_any();
- (overlay.layout(cx), overlay)
+ (overlay.request_layout(cx), overlay)
}
fn paint(&mut self, bounds: Bounds<Pixels>, overlay: &mut Self::State, cx: &mut WindowContext) {
@@ -0,0 +1,442 @@
+use gpui::{
+ div, img, prelude::*, px, rems, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
+ SharedString, Stateful, View, ViewContext, WindowContext,
+};
+use theme::ActiveFabricTheme;
+use ui::{
+ popover_menu, Button, ButtonCommon, ButtonStyle, Clickable, Color, LabelSize, PopoverMenu,
+ Tooltip,
+};
+
+#[derive(Clone, Copy, Debug)]
+pub struct PeerId(pub u32);
+
+#[derive(Clone, Copy, Debug)]
+pub struct ProjectId(u64);
+
+pub trait TitlebarDelegate: 'static + Sized {
+ fn toggle_following(&mut self, peer_index: PeerId, cx: &mut ViewContext<Self>);
+}
+
+impl TitlebarDelegate for () {
+ fn toggle_following(&mut self, peer: PeerId, _cx: &mut ViewContext<Self>) {
+ log::info!("toggle following {:?}", peer);
+ }
+}
+
+#[derive(IntoElement)]
+pub struct Titlebar<D: TitlebarDelegate = ()> {
+ pub delegate: View<D>,
+ pub full_screen: bool,
+ pub project_host: Option<ProjectHost<D>>,
+ pub projects: Projects<D>,
+ pub branches: Option<Branches>,
+ pub collaborators: Vec<FacePile>,
+}
+
+#[derive(IntoElement)]
+pub struct ProjectHost<D: TitlebarDelegate> {
+ pub delegate: View<D>,
+ pub id: PeerId,
+ pub login: SharedString,
+ pub peer_index: u32,
+}
+
+#[derive(IntoElement)]
+pub struct Projects<D: TitlebarDelegate> {
+ pub delegate: View<D>,
+ pub current: SharedString,
+ pub recent: Vec<Project>,
+}
+
+#[derive(Clone)]
+pub struct Project {
+ pub name: SharedString,
+ pub id: ProjectId,
+}
+
+pub struct ProjectsMenu<D> {
+ delegate: View<D>,
+ focus: FocusHandle,
+ recent: Vec<Project>,
+}
+
+pub struct Branches {
+ pub current: SharedString,
+}
+
+#[derive(IntoElement, Default)]
+pub struct FacePile {
+ pub faces: Vec<Avatar>,
+}
+
+#[derive(IntoElement)]
+pub struct Avatar {
+ pub image_uri: SharedString,
+ pub audio_status: AudioStatus,
+ pub available: Option<bool>,
+ pub shape: AvatarShape,
+}
+
+pub enum AvatarShape {
+ Square,
+ Circle,
+}
+
+impl<D: TitlebarDelegate> RenderOnce for Titlebar<D> {
+ type Output = Stateful<Div>;
+
+ fn render(self, cx: &mut ui::prelude::WindowContext) -> Self::Output {
+ div()
+ .flex()
+ .flex_col()
+ .id("titlebar")
+ .justify_between()
+ .w_full()
+ .h(rems(1.75))
+ // Set a non-scaling min-height here to ensure the titlebar is
+ // always at least the height of the traffic lights.
+ .min_h(px(32.))
+ .pl_2()
+ .when(self.full_screen, |this| {
+ // Use pixels here instead of a rem-based size because the macOS traffic
+ // lights are a static size, and don't scale with the rest of the UI.
+ this.pl(px(80.))
+ })
+ .bg(cx.theme().denim.default.background)
+ .on_click(|event, cx| {
+ if event.up.click_count == 2 {
+ cx.zoom_window();
+ }
+ })
+ // left side
+ .child(
+ div()
+ .flex()
+ .flex_row()
+ .gap_1()
+ .children(self.project_host)
+ .child(self.projects), // .children(self.render_project_branch(cx))
+ // .children(self.render_collaborators(cx)),
+ )
+ // right side
+ // .child(
+ // div()
+ // .flex()
+ // .flex_row()
+ // .gap_1()
+ // .pr_1()
+ // .when_some(room, |this, room| {
+ // let room = room.read(cx);
+ // let project = self.project.read(cx);
+ // let is_local = project.is_local();
+ // let is_shared = is_local && project.is_shared();
+ // let is_muted = room.is_muted(cx);
+ // let is_deafened = room.is_deafened().unwrap_or(false);
+ // let is_screen_sharing = room.is_screen_sharing();
+
+ // this.when(is_local, |this| {
+ // this.child(
+ // Button::new(
+ // "toggle_sharing",
+ // if is_shared { "Unshare" } else { "Share" },
+ // )
+ // .style(ButtonStyle::Subtle)
+ // .label_size(LabelSize::Small)
+ // .on_click(cx.listener(
+ // move |this, _, cx| {
+ // if is_shared {
+ // this.unshare_project(&Default::default(), cx);
+ // } else {
+ // this.share_project(&Default::default(), cx);
+ // }
+ // },
+ // )),
+ // )
+ // })
+ // .child(
+ // IconButton::new("leave-call", ui::Icon::Exit)
+ // .style(ButtonStyle::Subtle)
+ // .icon_size(IconSize::Small)
+ // .on_click(move |_, cx| {
+ // ActiveCall::global(cx)
+ // .update(cx, |call, cx| call.hang_up(cx))
+ // .detach_and_log_err(cx);
+ // }),
+ // )
+ // .child(
+ // IconButton::new(
+ // "mute-microphone",
+ // if is_muted {
+ // ui::Icon::MicMute
+ // } else {
+ // ui::Icon::Mic
+ // },
+ // )
+ // .style(ButtonStyle::Subtle)
+ // .icon_size(IconSize::Small)
+ // .selected(is_muted)
+ // .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
+ // )
+ // .child(
+ // IconButton::new(
+ // "mute-sound",
+ // if is_deafened {
+ // ui::Icon::AudioOff
+ // } else {
+ // ui::Icon::AudioOn
+ // },
+ // )
+ // .style(ButtonStyle::Subtle)
+ // .icon_size(IconSize::Small)
+ // .selected(is_deafened)
+ // .tooltip(move |cx| {
+ // Tooltip::with_meta("Deafen Audio", None, "Mic will be muted", cx)
+ // })
+ // .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
+ // )
+ // .child(
+ // IconButton::new("screen-share", ui::Icon::Screen)
+ // .style(ButtonStyle::Subtle)
+ // .icon_size(IconSize::Small)
+ // .selected(is_screen_sharing)
+ // .on_click(move |_, cx| {
+ // crate::toggle_screen_sharing(&Default::default(), cx)
+ // }),
+ // )
+ // })
+ // .map(|el| {
+ // let status = self.client.status();
+ // let status = &*status.borrow();
+ // if matches!(status, client::Status::Connected { .. }) {
+ // el.child(self.render_user_menu_button(cx))
+ // } else {
+ // el.children(self.render_connection_status(status, cx))
+ // .child(self.render_sign_in_button(cx))
+ // .child(self.render_user_menu_button(cx))
+ // }
+ // }),
+ // )
+ }
+}
+
+impl<D: TitlebarDelegate> RenderOnce for ProjectHost<D> {
+ type Output = Button;
+
+ fn render(self, _: &mut WindowContext) -> Self::Output {
+ let delegate = self.delegate;
+ Button::new("project-host", self.login)
+ .color(Color::Player(self.peer_index))
+ .style(ButtonStyle::Subtle)
+ .label_size(LabelSize::Small)
+ .tooltip(move |cx| Tooltip::text("Toggle following", cx))
+ .on_click(move |_, cx| {
+ let host_id = self.id;
+ delegate.update(cx, |this, cx| this.toggle_following(host_id, cx))
+ })
+ }
+}
+
+impl<D: 'static> EventEmitter<DismissEvent> for ProjectsMenu<D> {}
+
+impl<D: TitlebarDelegate> Render for ProjectsMenu<D> {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
+ todo!()
+ }
+}
+
+impl<D: TitlebarDelegate> FocusableView for ProjectsMenu<D> {
+ fn focus_handle(&self, _cx: &gpui::AppContext) -> gpui::FocusHandle {
+ self.focus.clone()
+ }
+}
+
+impl<D: TitlebarDelegate> RenderOnce for Projects<D> {
+ type Output = PopoverMenu<ProjectsMenu<D>>;
+
+ fn render(self, _cx: &mut WindowContext) -> Self::Output {
+ let delegate = self.delegate;
+ let recent_projects = self.recent;
+
+ popover_menu("recent-projects")
+ .trigger(
+ Button::new("trigger", self.current)
+ .style(ButtonStyle::Subtle)
+ .label_size(LabelSize::Small)
+ .tooltip(move |cx| Tooltip::text("Recent Projects", cx)),
+ )
+ .menu(move |cx| {
+ if recent_projects.is_empty() {
+ None
+ } else {
+ Some(cx.new_view(|cx| ProjectsMenu {
+ delegate: delegate.clone(),
+ focus: cx.focus_handle(),
+ recent: recent_projects.clone(),
+ }))
+ }
+ })
+ }
+}
+
+impl RenderOnce for FacePile {
+ type Output = Div;
+
+ fn render(self, _: &mut WindowContext) -> Self::Output {
+ let face_count = self.faces.len();
+ div()
+ .p_1()
+ .flex()
+ .items_center()
+ .children(self.faces.into_iter().enumerate().map(|(ix, avatar)| {
+ let last_child = ix == face_count - 1;
+ div()
+ .z_index((face_count - ix) as u8)
+ .when(!last_child, |div| div.neg_mr_1())
+ .child(avatar)
+ }))
+ }
+}
+
+impl RenderOnce for Avatar {
+ type Output = Div;
+
+ fn render(self, cx: &mut WindowContext) -> Self::Output {
+ div()
+ .map(|this| match self.shape {
+ AvatarShape::Square => this.rounded_md(),
+ AvatarShape::Circle => this.rounded_full(),
+ })
+ .map(|this| match self.audio_status {
+ AudioStatus::None => this,
+ AudioStatus::Muted => this.border_color(cx.theme().muted),
+ AudioStatus::Speaking => this.border_color(cx.theme().speaking),
+ })
+ .size(cx.rem_size() + px(2.))
+ .child(
+ img(self.image_uri)
+ .size(cx.rem_size())
+ .bg(cx.theme().cotton.disabled.background),
+ )
+ .children(self.available.map(|is_free| {
+ // Non-integer sizes result in non-round indicators.
+ let indicator_size = (cx.rem_size() * 0.4).round();
+
+ div()
+ .absolute()
+ .z_index(1)
+ .bg(if is_free {
+ cx.theme().positive.default.background
+ } else {
+ cx.theme().negative.default.background
+ })
+ .size(indicator_size)
+ .rounded(indicator_size)
+ .bottom_0()
+ .right_0()
+ }))
+ }
+}
+
+pub enum AudioStatus {
+ None,
+ Muted,
+ Speaking,
+}
+
+// impl Titlebar {
+// pub fn render_project_host(&self, cx: &mut ViewContext<Self>) -> Option<impl Element> {
+// let host = self.project.read(cx).host()?;
+// let host = self.user_store.read(cx).get_cached_user(host.user_id)?;
+// let participant_index = self
+// .user_store
+// .read(cx)
+// .participant_indices()
+// .get(&host.id)?;
+// Some(
+// div().border().border_color(gpui::red()).child(
+// Button::new("project_owner_trigger", host.github_login.clone())
+// .color(Color::Player(participant_index.0))
+// .style(ButtonStyle::Subtle)
+// .label_size(LabelSize::Small)
+// .tooltip(move |cx| Tooltip::text("Toggle following", cx)),
+// ),
+// )
+// }
+
+// pub fn render_project_branch(&self, cx: &mut ViewContext<Self>) -> Option<impl Element> {
+// let entry = {
+// let mut names_and_branches =
+// self.project.read(cx).visible_worktrees(cx).map(|worktree| {
+// let worktree = worktree.read(cx);
+// worktree.root_git_entry()
+// });
+
+// names_and_branches.next().flatten()
+// };
+// let workspace = self.workspace.upgrade()?;
+// let branch_name = entry
+// .as_ref()
+// .and_then(RepositoryEntry::branch)
+// .map(|branch| util::truncate_and_trailoff(&branch, MAX_BRANCH_NAME_LENGTH))?;
+// Some(
+// popover_menu("project_branch_trigger")
+// .trigger(
+// Button::new("project_branch_trigger", branch_name)
+// .color(Color::Muted)
+// .style(ButtonStyle::Subtle)
+// .label_size(LabelSize::Small)
+// .tooltip(move |cx| {
+// Tooltip::with_meta(
+// "Recent Branches",
+// Some(&ToggleVcsMenu),
+// "Local branches only",
+// cx,
+// )
+// }),
+// )
+// .menu(move |cx| Self::render_vcs_popover(workspace.clone(), cx)),
+// )
+// }
+
+// fn render_collaborator(
+// &self,
+// user: &Arc<User>,
+// peer_id: PeerId,
+// is_present: bool,
+// is_speaking: bool,
+// is_muted: bool,
+// room: &Room,
+// project_id: Option<u64>,
+// current_user: &Arc<User>,
+// ) -> Option<FacePile> {
+// let followers = project_id.map_or(&[] as &[_], |id| room.followers_for(peer_id, id));
+
+// let pile = FacePile::default()
+// .child(
+// Avatar::new(user.avatar_uri.clone())
+// .grayscale(!is_present)
+// .border_color(if is_speaking {
+// gpui::blue()
+// } else if is_muted {
+// gpui::red()
+// } else {
+// Hsla::default()
+// }),
+// )
+// .children(followers.iter().filter_map(|follower_peer_id| {
+// let follower = room
+// .remote_participants()
+// .values()
+// .find_map(|p| (p.peer_id == *follower_peer_id).then_some(&p.user))
+// .or_else(|| {
+// (self.client.peer_id() == Some(*follower_peer_id)).then_some(current_user)
+// })?
+// .clone();
+
+// Some(Avatar::new(follower.avatar_uri.clone()))
+// }));
+
+// Some(pile)
+// }
+// }