Merge followup mess

Conrad Irwin created

Change summary

crates/auto_update2/src/update_notification.rs |  4 +-
crates/command_palette2/src/command_palette.rs |  5 +-
crates/diagnostics2/src/diagnostics.rs         | 14 ++++---
crates/diagnostics2/src/items.rs               |  6 +-
crates/diagnostics2/src/toolbar_controls.rs    |  4 +-
crates/editor2/src/editor.rs                   |  1 
crates/file_finder2/src/file_finder.rs         |  7 +--
crates/go_to_line2/src/go_to_line.rs           |  3 -
crates/gpui2/src/elements/text.rs              | 29 ++++++++++++--
crates/gpui2/src/window.rs                     | 16 ++++----
crates/project_panel2/src/project_panel.rs     |  1 
crates/terminal_view2/src/terminal_view.rs     |  2 
crates/ui2/src/components/button.rs            |  2 
crates/ui2/src/components/context_menu.rs      | 26 ++++---------
crates/ui2/src/components/icon_button.rs       |  5 ++
crates/ui2/src/components/keybinding.rs        | 21 +---------
crates/ui2/src/components/list.rs              | 39 ++++++++++---------
crates/workspace2/src/notifications.rs         |  2 
18 files changed, 90 insertions(+), 97 deletions(-)

Detailed changes

crates/auto_update2/src/update_notification.rs 🔗

@@ -1,4 +1,4 @@
-use gpui::{div, Div, EventEmitter, ParentComponent, Render, SemanticVersion, ViewContext};
+use gpui::{div, Div, EventEmitter, ParentElement, Render, SemanticVersion, ViewContext};
 use menu::Cancel;
 use workspace::notifications::NotificationEvent;
 
@@ -8,7 +8,7 @@ pub struct UpdateNotification {
 
 impl EventEmitter<NotificationEvent> for UpdateNotification {}
 
-impl Render for UpdateNotification {
+impl Render<Self> for UpdateNotification {
     type Element = Div<Self>;
 
     fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> Self::Element {

crates/command_palette2/src/command_palette.rs 🔗

@@ -1,9 +1,8 @@
 use collections::{CommandPaletteFilter, HashMap};
 use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::{
-    actions, actions, div, prelude::*, prelude::*, Action, AppContext, Component, Dismiss, Div,
-    EventEmitter, FocusHandle, FocusableView, Keystroke, ManagedView, Manager, ParentComponent,
-    ParentElement, Render, Render, Styled, View, ViewContext, VisualContext, WeakView,
+    actions, div, prelude::*, Action, AppContext, Div, EventEmitter, FocusHandle, FocusableView,
+    Keystroke, Manager, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
 };
 use picker::{Picker, PickerDelegate};
 use std::{

crates/diagnostics2/src/diagnostics.rs 🔗

@@ -14,8 +14,8 @@ use editor::{
 use futures::future::try_join_all;
 use gpui::{
     actions, div, AnyElement, AnyView, AppContext, Component, Context, Div, EventEmitter,
-    FocusEvent, FocusHandle, Focusable, FocusableComponent, FocusableView, InteractiveComponent,
-    Model, ParentComponent, Render, SharedString, Styled, Subscription, Task, View, ViewContext,
+    FocusEvent, FocusHandle, Focusable, FocusableElement, FocusableView, InteractiveElement, Model,
+    ParentElement, Render, RenderOnce, SharedString, Styled, Subscription, Task, View, ViewContext,
     VisualContext, WeakView,
 };
 use language::{
@@ -90,7 +90,7 @@ struct DiagnosticGroupState {
 
 impl EventEmitter<ItemEvent> for ProjectDiagnosticsEditor {}
 
-impl Render for ProjectDiagnosticsEditor {
+impl Render<Self> for ProjectDiagnosticsEditor {
     type Element = Focusable<Self, Div<Self>>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
@@ -792,13 +792,15 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
             .when_some(diagnostic.code.as_ref(), |stack, code| {
                 stack.child(Label::new(code.clone()))
             })
-            .render()
+            .render_into_any()
     })
 }
 
 pub(crate) fn render_summary<T: 'static>(summary: &DiagnosticSummary) -> AnyElement<T> {
     if summary.error_count == 0 && summary.warning_count == 0 {
-        Label::new("No problems").render()
+        let label = Label::new("No problems");
+        label.render_into_any()
+        //.render()
     } else {
         h_stack()
             .bg(gpui::red())
@@ -806,7 +808,7 @@ pub(crate) fn render_summary<T: 'static>(summary: &DiagnosticSummary) -> AnyElem
             .child(Label::new(summary.error_count.to_string()))
             .child(IconElement::new(Icon::ExclamationTriangle))
             .child(Label::new(summary.warning_count.to_string()))
-            .render()
+            .render_into_any()
     }
 }
 

crates/diagnostics2/src/items.rs 🔗

@@ -1,8 +1,8 @@
 use collections::HashSet;
 use editor::{Editor, GoToDiagnostic};
 use gpui::{
-    rems, Div, EventEmitter, InteractiveComponent, ParentComponent, Render, Stateful,
-    StatefulInteractiveComponent, Styled, Subscription, View, ViewContext, WeakView,
+    rems, Div, EventEmitter, InteractiveElement, ParentElement, Render, Stateful,
+    StatefulInteractiveElement, Styled, Subscription, View, ViewContext, WeakView,
 };
 use language::Diagnostic;
 use lsp::LanguageServerId;
@@ -21,7 +21,7 @@ pub struct DiagnosticIndicator {
     _observe_active_editor: Option<Subscription>,
 }
 
-impl Render for DiagnosticIndicator {
+impl Render<Self> for DiagnosticIndicator {
     type Element = Stateful<Self, Div<Self>>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {

crates/diagnostics2/src/toolbar_controls.rs 🔗

@@ -1,5 +1,5 @@
 use crate::ProjectDiagnosticsEditor;
-use gpui::{div, Div, EventEmitter, ParentComponent, Render, ViewContext, WeakView};
+use gpui::{div, Div, EventEmitter, ParentElement, Render, ViewContext, WeakView};
 use ui::{Icon, IconButton, Tooltip};
 use workspace::{item::ItemHandle, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
 
@@ -7,7 +7,7 @@ pub struct ToolbarControls {
     editor: Option<WeakView<ProjectDiagnosticsEditor>>,
 }
 
-impl Render for ToolbarControls {
+impl Render<Self> for ToolbarControls {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {

crates/file_finder2/src/file_finder.rs 🔗

@@ -2,10 +2,9 @@ use collections::HashMap;
 use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
 use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
 use gpui::{
-    actions, div, AppContext, Component, Dismiss, Div, EventEmitter, FocusHandle, FocusableView,
-    InteractiveComponent, InteractiveElement, ManagedView, Manager, Model, ParentComponent,
-    ParentElement, Render, RenderOnce, Styled, Styled, Task, View, ViewContext, VisualContext,
-    WeakView,
+    actions, div, AppContext, Div, EventEmitter, FocusHandle, FocusableView, InteractiveElement,
+    Manager, Model, ParentElement, Render, RenderOnce, Styled, Task, View, ViewContext,
+    VisualContext, WeakView,
 };
 use picker::{Picker, PickerDelegate};
 use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};

crates/go_to_line2/src/go_to_line.rs 🔗

@@ -1,8 +1,7 @@
 use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor};
 use gpui::{
     actions, div, prelude::*, AppContext, Div, EventEmitter, FocusHandle, FocusableView, Manager,
-    ParentComponent, Render, SharedString, Styled, Subscription, View, ViewContext, VisualContext,
-    WindowContext,
+    Render, SharedString, Styled, Subscription, View, ViewContext, VisualContext, WindowContext,
 };
 use text::{Bias, Point};
 use theme::ActiveTheme;

crates/gpui2/src/elements/text.rs 🔗

@@ -256,19 +256,35 @@ impl TextState {
 
         let layout_id = cx.request_measured_layout(Default::default(), rem_size, {
             let element_state = self.clone();
-            move |known_dimensions, _| {
+
+            move |known_dimensions, available_space| {
+                let wrap_width = known_dimensions.width.or(match available_space.width {
+                    crate::AvailableSpace::Definite(x) => Some(x),
+                    _ => None,
+                });
+
+                if let Some(text_state) = element_state.0.lock().as_ref() {
+                    if text_state.size.is_some()
+                        && (wrap_width.is_none() || wrap_width == text_state.wrap_width)
+                    {
+                        return text_state.size.unwrap();
+                    }
+                }
+
                 let Some(lines) = text_system
                     .shape_text(
                         &text,
                         font_size,
                         &runs[..],
-                        known_dimensions.width, // Wrap if we know the width.
+                        wrap_width, // Wrap if we know the width.
                     )
                     .log_err()
                 else {
                     element_state.lock().replace(TextStateInner {
                         lines: Default::default(),
                         line_height,
+                        wrap_width,
+                        size: Some(Size::default()),
                     });
                     return Size::default();
                 };
@@ -280,9 +296,12 @@ impl TextState {
                     size.width = size.width.max(line_size.width);
                 }
 
-                element_state
-                    .lock()
-                    .replace(TextStateInner { lines, line_height });
+                element_state.lock().replace(TextStateInner {
+                    lines,
+                    line_height,
+                    wrap_width,
+                    size: Some(size),
+                });
 
                 size
             }

crates/gpui2/src/window.rs 🔗

@@ -2,14 +2,14 @@ use crate::{
     key_dispatch::DispatchActionListener, px, size, Action, AnyDrag, AnyView, AppContext,
     AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
     DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId,
-    EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData,
-    InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model, ModelContext,
-    Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path,
-    Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
-    PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams,
-    RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, SubscriberSet,
-    Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext,
-    WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
+    EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla,
+    ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model,
+    ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent,
+    MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler,
+    PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,
+    RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size,
+    Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View,
+    VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
 };
 use anyhow::{anyhow, Context as _, Result};
 use collections::HashMap;

crates/project_panel2/src/project_panel.rs 🔗

@@ -247,7 +247,6 @@ impl ProjectPanel {
             let mut old_dock_position = this.position(cx);
             ProjectPanelSettings::register(cx);
             cx.observe_global::<SettingsStore>(move |this, cx| {
-                dbg!("OLA!");
                 let new_dock_position = this.position(cx);
                 if new_dock_position != old_dock_position {
                     old_dock_position = new_dock_position;

crates/ui2/src/components/button.rs 🔗

@@ -1,7 +1,7 @@
 use std::sync::Arc;
 
 use gpui::{
-    div, DefiniteLength, Div, Hsla, MouseButton, RenderOnce, Stateful, StatefulInteractiveElement,
+    DefiniteLength, Div, Hsla, MouseButton, RenderOnce, Stateful, StatefulInteractiveElement,
     WindowContext,
 };
 

crates/ui2/src/components/context_menu.rs 🔗

@@ -1,18 +1,12 @@
 use std::cell::RefCell;
 use std::rc::Rc;
 
-use crate::prelude::*;
-use crate::{v_stack, Label, List, ListEntry, ListItem, ListSeparator, ListSubHeader};
+use crate::{prelude::*, v_stack, List, ListItem};
+use crate::{ListEntry, ListSeparator, ListSubHeader};
 use gpui::{
-<<<<<<< HEAD
-    overlay, px, Action, AnchorCorner, AnyElement, Bounds, Dismiss, DispatchPhase, Div,
-    FocusHandle, LayoutId, ManagedView, MouseButton, MouseDownEvent, Pixels, Point, Render,
-    RenderOnce, View,
-=======
     overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, DispatchPhase, Div,
     EventEmitter, FocusHandle, FocusableView, LayoutId, ManagedView, Manager, MouseButton,
-    MouseDownEvent, Pixels, Point, Render, View, VisualContext, WeakView,
->>>>>>> main
+    MouseDownEvent, Pixels, Point, Render, RenderOnce, View, VisualContext, WeakView,
 };
 
 pub enum ContextMenuItem<V> {
@@ -30,15 +24,15 @@ pub struct ContextMenu<V> {
     handle: WeakView<V>,
 }
 
-impl<V: Render> FocusableView for ContextMenu<V> {
+impl<V: 'static> FocusableView for ContextMenu<V> {
     fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
         self.focus_handle.clone()
     }
 }
 
-impl<V: Render> EventEmitter<Manager> for ContextMenu<V> {}
+impl<V: 'static> EventEmitter<Manager> for ContextMenu<V> {}
 
-impl<V: Render> ContextMenu<V> {
+impl<V: 'static> ContextMenu<V> {
     pub fn build(
         cx: &mut ViewContext<V>,
         f: impl FnOnce(Self, &mut ViewContext<Self>) -> Self,
@@ -92,11 +86,7 @@ impl<V: Render> ContextMenu<V> {
     }
 }
 
-<<<<<<< HEAD
-impl Render<Self> for ContextMenu {
-=======
-impl<V: Render> Render for ContextMenu<V> {
->>>>>>> main
+impl<V: 'static> Render<Self> for ContextMenu<V> {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
@@ -324,7 +314,7 @@ mod stories {
 
     actions!(PrintCurrentDate, PrintBestFood);
 
-    fn build_menu<V: Render>(
+    fn build_menu<V: Render<V>>(
         cx: &mut ViewContext<V>,
         header: impl Into<SharedString>,
     ) -> View<ContextMenu<V>> {

crates/ui2/src/components/icon_button.rs 🔗

@@ -58,7 +58,10 @@ impl<V: 'static> Component<V> for IconButton<V> {
             .p_1()
             .bg(bg_color)
             .cursor_pointer()
-            .hover(|style| style.bg(bg_hover_color))
+            // Nate: Trying to figure out the right places we want to show a
+            // hover state here. I think it is a bit heavy to have it on every
+            // place we use an icon button.
+            // .hover(|style| style.bg(bg_hover_color))
             .active(|style| style.bg(bg_active_color))
             .child(IconElement::new(self.icon).color(icon_color));
 

crates/ui2/src/components/keybinding.rs 🔗

@@ -1,6 +1,5 @@
 use crate::prelude::*;
 use gpui::{Action, Div, RenderOnce};
-use strum::EnumIter;
 
 #[derive(RenderOnce, Clone)]
 pub struct KeyBinding {
@@ -72,22 +71,6 @@ impl Key {
     }
 }
 
-// NOTE: The order the modifier keys appear in this enum impacts the order in
-// which they are rendered in the UI.
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)]
-pub enum ModifierKey {
-    Control,
-    Alt,
-    Command,
-    Shift,
-}
-
-actions!(NoAction);
-
-pub fn binding(key: &str) -> gpui::KeyBinding {
-    gpui::KeyBinding::new(key, NoAction {}, None)
-}
-
 #[cfg(feature = "stories")]
 pub use stories::*;
 
@@ -95,7 +78,7 @@ pub use stories::*;
 mod stories {
     use super::*;
     pub use crate::KeyBinding;
-    use crate::{binding, Story};
+    use crate::Story;
     use gpui::{actions, Div, Render};
     use itertools::Itertools;
     pub struct KeybindingStory;
@@ -106,7 +89,7 @@ mod stories {
         gpui::KeyBinding::new(key, NoAction {}, None)
     }
 
-    impl Render for KeybindingStory {
+    impl Render<Self> for KeybindingStory {
         type Element = Div<Self>;
 
         fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {

crates/ui2/src/components/list.rs 🔗

@@ -1,4 +1,4 @@
-use gpui::{div, Action, Div, RenderOnce};
+use gpui::{div, Div, RenderOnce, Stateful, StatefulInteractiveElement};
 use std::rc::Rc;
 
 use crate::settings::user_settings;
@@ -232,7 +232,7 @@ pub enum ListEntrySize {
     Medium,
 }
 
-#[derive(RenderOnce, Clone)]
+#[derive(Clone)]
 pub enum ListItem<V: 'static> {
     Entry(ListEntry<V>),
     Separator(ListSeparator),
@@ -257,19 +257,7 @@ impl<V: 'static> From<ListSubHeader> for ListItem<V> {
     }
 }
 
-impl<V: 'static> Component<V> for ListItem<V> {
-    type Rendered = Div<V>;
-
-    fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> Self::Rendered {
-        match self {
-            ListItem::Entry(entry) => div().child(entry.render(ix, cx)),
-            ListItem::Separator(separator) => div().child(separator.render(view, cx)),
-            ListItem::Header(header) => div().child(header.render(view, cx)),
-        }
-    }
-}
-
-impl ListItem {
+impl<V: 'static> ListItem<V> {
     pub fn new(label: Label) -> Self {
         Self::Entry(ListEntry::new(label))
     }
@@ -281,6 +269,14 @@ impl ListItem {
             None
         }
     }
+
+    fn render(self, view: &mut V, ix: usize, cx: &mut ViewContext<V>) -> Div<V> {
+        match self {
+            ListItem::Entry(entry) => div().child(entry.render(ix, cx)),
+            ListItem::Separator(separator) => div().child(separator.render(view, cx)),
+            ListItem::Header(header) => div().child(header.render(view, cx)),
+        }
+    }
 }
 
 // #[derive(RenderOnce)]
@@ -458,7 +454,7 @@ impl<V: 'static> Component<V> for ListSeparator {
 
 #[derive(RenderOnce)]
 pub struct List<V: 'static> {
-    items: Vec<ListItem>,
+    items: Vec<ListItem<V>>,
     /// Message to display when the list is empty
     /// Defaults to "No items"
     empty_message: SharedString,
@@ -471,7 +467,12 @@ impl<V: 'static> Component<V> for List<V> {
 
     fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> Self::Rendered {
         let list_content = match (self.items.is_empty(), self.toggle) {
-            (false, _) => div().children(self.items),
+            (false, _) => div().children(
+                self.items
+                    .into_iter()
+                    .enumerate()
+                    .map(|(ix, item)| item.render(view, ix, cx)),
+            ),
             (true, Toggle::Toggled(false)) => div(),
             (true, _) => {
                 div().child(Label::new(self.empty_message.clone()).color(TextColor::Muted))
@@ -487,7 +488,7 @@ impl<V: 'static> Component<V> for List<V> {
 }
 
 impl<V: 'static> List<V> {
-    pub fn new(items: Vec<ListItem>) -> Self {
+    pub fn new(items: Vec<ListItem<V>>) -> Self {
         Self {
             items,
             empty_message: "No items".into(),
@@ -511,7 +512,7 @@ impl<V: 'static> List<V> {
         self
     }
 
-    fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
+    fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
         let list_content = match (self.items.is_empty(), self.toggle) {
             (false, _) => div().children(
                 self.items

crates/workspace2/src/notifications.rs 🔗

@@ -15,7 +15,7 @@ pub enum NotificationEvent {
 
 pub trait Notification: EventEmitter<NotificationEvent> + Render<Self> {}
 
-impl<V: EventEmitter<NotificationEvent> + Render> Notification for V {}
+impl<V: EventEmitter<NotificationEvent> + Render<Self>> Notification for V {}
 
 pub trait NotificationHandle: Send {
     fn id(&self) -> EntityId;