WIP: Render dummy chat messages to test `List`

Antonio Scandurra and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

gpui/src/elements.rs         | 47 +++++++++++++++++++++++++------------
zed/src/chat_panel.rs        | 37 +++++++++++++++++++++++++----
zed/src/workspace.rs         | 17 +++++--------
zed/src/workspace/sidebar.rs |  4 +-
4 files changed, 73 insertions(+), 32 deletions(-)

Detailed changes

gpui/src/elements.rs 🔗

@@ -155,25 +155,42 @@ impl<T: Element> AnyElement for Lifecycle<T> {
     }
 
     fn paint(&mut self, origin: Vector2F, cx: &mut PaintContext) {
-        *self = if let Lifecycle::PostLayout {
-            mut element,
-            constraint,
-            size,
-            mut layout,
-        } = mem::take(self)
-        {
-            let bounds = RectF::new(origin, size);
-            let paint = element.paint(bounds, &mut layout, cx);
+        *self = match mem::take(self) {
+            Lifecycle::PostLayout {
+                mut element,
+                constraint,
+                size,
+                mut layout,
+            } => {
+                let bounds = RectF::new(origin, size);
+                let paint = element.paint(bounds, &mut layout, cx);
+                Lifecycle::PostPaint {
+                    element,
+                    constraint,
+                    bounds,
+                    layout,
+                    paint,
+                }
+            }
             Lifecycle::PostPaint {
-                element,
+                mut element,
                 constraint,
                 bounds,
-                layout,
-                paint,
+                mut layout,
+                ..
+            } => {
+                let bounds = RectF::new(origin, bounds.size());
+                let paint = element.paint(bounds, &mut layout, cx);
+                Lifecycle::PostPaint {
+                    element,
+                    constraint,
+                    bounds,
+                    layout,
+                    paint,
+                }
             }
-        } else {
-            panic!("invalid element lifecycle state");
-        };
+            _ => panic!("invalid element lifecycle state"),
+        }
     }
 
     fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {

zed/src/chat_panel.rs 🔗

@@ -1,14 +1,41 @@
+use crate::Settings;
+
 use super::channel::{Channel, ChannelList};
-use gpui::{elements::*, Entity, ModelHandle, View};
+use gpui::{elements::*, Entity, ModelHandle, RenderContext, View, ViewContext};
+use postage::watch;
 
 pub struct ChatPanel {
-    channel_list: ModelHandle<ChannelList>,
-    active_channel: Option<ModelHandle<Channel>>,
+    // channel_list: ModelHandle<ChannelList>,
+    // active_channel: Option<ModelHandle<Channel>>,
     messages: ListState,
 }
 
 pub enum Event {}
 
+impl ChatPanel {
+    pub fn new(settings: watch::Receiver<Settings>) -> Self {
+        let settings = settings.borrow();
+        let mut messages = Vec::new();
+        for i in 0..1000 {
+            messages.push(
+                Container::new(
+                    Label::new(
+                        format!("This is message {}", i),
+                        settings.ui_font_family,
+                        settings.ui_font_size,
+                    )
+                    .with_style(&settings.theme.selector.label)
+                    .boxed(),
+                )
+                .boxed(),
+            );
+        }
+        Self {
+            messages: ListState::new(messages),
+        }
+    }
+}
+
 impl Entity for ChatPanel {
     type Event = Event;
 }
@@ -18,7 +45,7 @@ impl View for ChatPanel {
         "ChatPanel"
     }
 
-    fn render(&self, cx: &gpui::RenderContext<'_, Self>) -> gpui::ElementBox {
-        todo!()
+    fn render(&self, cx: &RenderContext<Self>) -> gpui::ElementBox {
+        List::new(self.messages.clone()).boxed()
     }
 }

zed/src/workspace.rs 🔗

@@ -3,6 +3,7 @@ pub mod pane_group;
 pub mod sidebar;
 
 use crate::{
+    chat_panel::ChatPanel,
     editor::{Buffer, Editor},
     fs::Fs,
     language::LanguageRegistry,
@@ -28,7 +29,7 @@ use log::error;
 pub use pane::*;
 pub use pane_group::*;
 use postage::watch;
-use sidebar::{Side, Sidebar};
+use sidebar::{Side, Sidebar, ToggleSidebarItem};
 use smol::prelude::*;
 use std::{
     collections::{hash_map::Entry, HashMap, HashSet},
@@ -44,7 +45,6 @@ action!(ShareWorktree);
 action!(JoinWorktree, Arc<AppState>);
 action!(Save);
 action!(DebugElements);
-action!(ToggleSidebarItem, (Side, usize));
 
 pub fn init(cx: &mut MutableAppContext) {
     cx.add_global_action(open);
@@ -372,7 +372,8 @@ impl Workspace {
         let mut right_sidebar = Sidebar::new(Side::Right);
         right_sidebar.add_item(
             "icons/comment-16.svg",
-            cx.add_view(|_| ProjectBrowser).into(),
+            cx.add_view(|_| ChatPanel::new(app_state.settings.clone()))
+                .into(),
         );
         right_sidebar.add_item("icons/user-16.svg", cx.add_view(|_| ProjectBrowser).into());
 
@@ -752,16 +753,12 @@ impl Workspace {
         }
     }
 
-    pub fn toggle_sidebar_item(
-        &mut self,
-        ToggleSidebarItem((side, item_ix)): &ToggleSidebarItem,
-        cx: &mut ViewContext<Self>,
-    ) {
-        let sidebar = match side {
+    pub fn toggle_sidebar_item(&mut self, action: &ToggleSidebarItem, cx: &mut ViewContext<Self>) {
+        let sidebar = match action.0.side {
             Side::Left => &mut self.left_sidebar,
             Side::Right => &mut self.right_sidebar,
         };
-        sidebar.toggle_item(*item_ix);
+        sidebar.toggle_item(action.0.item_index);
         cx.notify();
     }
 

zed/src/workspace/sidebar.rs 🔗

@@ -28,8 +28,8 @@ action!(ToggleSidebarItem, ToggleArg);
 
 #[derive(Clone)]
 pub struct ToggleArg {
-    side: Side,
-    item_index: usize,
+    pub side: Side,
+    pub item_index: usize,
 }
 
 impl Sidebar {