Add `EditorPane` component and wire up in the workspace

Marshall Bowers created

Change summary

crates/ui2/src/components.rs             |   2 
crates/ui2/src/components/editor_pane.rs |  55 +++++++++
crates/ui2/src/components/workspace.rs   |  25 +--
crates/ui2/src/static_data.rs            | 150 +++++++++++++++++++++++++
4 files changed, 215 insertions(+), 17 deletions(-)

Detailed changes

crates/ui2/src/components.rs 🔗

@@ -1,6 +1,7 @@
 mod assistant_panel;
 mod breadcrumb;
 mod buffer;
+mod editor_pane;
 mod icon_button;
 mod list;
 mod panel;
@@ -16,6 +17,7 @@ mod workspace;
 pub use assistant_panel::*;
 pub use breadcrumb::*;
 pub use buffer::*;
+pub use editor_pane::*;
 pub use icon_button::*;
 pub use list::*;
 pub use panel::*;

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

@@ -0,0 +1,55 @@
+use std::path::PathBuf;
+
+use crate::prelude::*;
+use crate::{v_stack, Breadcrumb, Buffer, Icon, IconButton, Symbol, Tab, TabBar, Toolbar};
+
+pub struct Editor<S: 'static + Send + Sync + Clone> {
+    pub tabs: Vec<Tab<S>>,
+    pub path: PathBuf,
+    pub symbols: Vec<Symbol>,
+    pub buffer: Buffer<S>,
+}
+
+#[derive(Element)]
+pub struct EditorPane<S: 'static + Send + Sync + Clone> {
+    editor: Editor<S>,
+}
+
+impl<S: 'static + Send + Sync + Clone> EditorPane<S> {
+    pub fn new(editor: Editor<S>) -> Self {
+        Self { editor }
+    }
+
+    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
+        struct LeftItemsPayload {
+            path: PathBuf,
+            symbols: Vec<Symbol>,
+        }
+
+        v_stack()
+            .w_full()
+            .h_full()
+            .flex_1()
+            .child(TabBar::new(self.editor.tabs.clone()))
+            .child(Toolbar::new(
+                |_, payload| {
+                    let payload = payload.downcast_ref::<LeftItemsPayload>().unwrap();
+
+                    vec![Breadcrumb::new(payload.path.clone(), payload.symbols.clone()).into_any()]
+                },
+                Box::new(LeftItemsPayload {
+                    path: self.editor.path.clone(),
+                    symbols: self.editor.symbols.clone(),
+                }),
+                |_, _| {
+                    vec![
+                        IconButton::new(Icon::InlayHint).into_any(),
+                        IconButton::new(Icon::MagnifyingGlass).into_any(),
+                        IconButton::new(Icon::MagicWand).into_any(),
+                    ]
+                },
+                Box::new(()),
+            ))
+            .child(self.editor.buffer.clone())
+    }
+}

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

@@ -6,8 +6,8 @@ use gpui3::{relative, rems, Size};
 
 use crate::prelude::*;
 use crate::{
-    theme, v_stack, Pane, PaneGroup, Panel, PanelAllowedSides, PanelSide, ProjectPanel,
-    SplitDirection, StatusBar, Terminal,
+    hello_world_rust_editor_with_status_example, theme, v_stack, EditorPane, Pane, PaneGroup,
+    Panel, PanelAllowedSides, PanelSide, ProjectPanel, SplitDirection, StatusBar, Terminal,
 };
 
 #[derive(Element)]
@@ -48,12 +48,10 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
                             |_, payload| {
                                 let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
 
-                                vec![
-                                    Terminal::new().into_any(), // EditorPane::new(hello_world_rust_editor_with_status_example(
-                                                                //     &theme,
-                                                                // ))
-                                                                // .into_any()
-                                ]
+                                vec![EditorPane::new(hello_world_rust_editor_with_status_example(
+                                    &theme,
+                                ))
+                                .into_any()]
                             },
                             Box::new(theme.clone()),
                         ),
@@ -79,13 +77,10 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
                         |_, payload| {
                             let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
 
-                            vec![
-                                Terminal::new().into_any(),
-                                //     EditorPane::new(hello_world_rust_editor_with_status_example(
-                                //     &theme,
-                                // ))
-                                // .into_any()
-                            ]
+                            vec![EditorPane::new(hello_world_rust_editor_with_status_example(
+                                &theme,
+                            ))
+                            .into_any()]
                         },
                         Box::new(theme.clone()),
                     )],

crates/ui2/src/static_data.rs 🔗

@@ -1,8 +1,105 @@
+use std::path::PathBuf;
+use std::str::FromStr;
+
 use crate::{
-    Buffer, BufferRow, BufferRows, GitStatus, HighlightColor, HighlightedLine, HighlightedText,
-    Icon, Label, LabelColor, ListEntry, ListItem, Theme, ToggleState,
+    Buffer, BufferRow, BufferRows, Editor, FileSystemStatus, GitStatus, HighlightColor,
+    HighlightedLine, HighlightedText, Icon, Label, LabelColor, ListEntry, ListItem, Symbol, Tab,
+    Theme, ToggleState,
 };
 
+pub fn static_tabs_example<S: 'static + Send + Sync + Clone>() -> Vec<Tab<S>> {
+    vec![
+        Tab::new()
+            .title("wip.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false)
+            .fs_status(FileSystemStatus::Deleted),
+        Tab::new()
+            .title("Cargo.toml".to_string())
+            .icon(Icon::FileToml)
+            .current(false)
+            .git_status(GitStatus::Modified),
+        Tab::new()
+            .title("Channels Panel".to_string())
+            .icon(Icon::Hash)
+            .current(false),
+        Tab::new()
+            .title("channels_panel.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(true)
+            .git_status(GitStatus::Modified),
+        Tab::new()
+            .title("workspace.rs".to_string())
+            .current(false)
+            .icon(Icon::FileRust)
+            .git_status(GitStatus::Modified),
+        Tab::new()
+            .title("icon_button.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false),
+        Tab::new()
+            .title("storybook.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false)
+            .git_status(GitStatus::Created),
+        Tab::new()
+            .title("theme.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false),
+        Tab::new()
+            .title("theme_registry.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false),
+        Tab::new()
+            .title("styleable_helpers.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false),
+    ]
+}
+
+pub fn static_tabs_1<S: 'static + Send + Sync + Clone>() -> Vec<Tab<S>> {
+    vec![
+        Tab::new()
+            .title("project_panel.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false)
+            .fs_status(FileSystemStatus::Deleted),
+        Tab::new()
+            .title("tab_bar.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false)
+            .git_status(GitStatus::Modified),
+        Tab::new()
+            .title("workspace.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false),
+        Tab::new()
+            .title("tab.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(true)
+            .git_status(GitStatus::Modified),
+    ]
+}
+
+pub fn static_tabs_2<S: 'static + Send + Sync + Clone>() -> Vec<Tab<S>> {
+    vec![
+        Tab::new()
+            .title("tab_bar.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(false)
+            .fs_status(FileSystemStatus::Deleted),
+        Tab::new()
+            .title("static_data.rs".to_string())
+            .icon(Icon::FileRust)
+            .current(true)
+            .git_status(GitStatus::Modified),
+    ]
+}
+
+pub fn static_tabs_3<S: 'static + Send + Sync + Clone>() -> Vec<Tab<S>> {
+    vec![Tab::new().git_status(GitStatus::Created).current(true)]
+}
+
 pub fn static_project_panel_project_items<S: 'static + Send + Sync + Clone>() -> Vec<ListItem<S>> {
     vec![
         ListEntry::new(Label::new("zed"))
@@ -147,10 +244,39 @@ pub fn static_project_panel_single_items<S: 'static + Send + Sync + Clone>() ->
     .collect()
 }
 
+pub fn empty_editor_example<S: 'static + Send + Sync + Clone>() -> Editor<S> {
+    Editor {
+        tabs: static_tabs_example(),
+        path: PathBuf::from_str("crates/ui/src/static_data.rs").unwrap(),
+        symbols: vec![],
+        buffer: empty_buffer_example(),
+    }
+}
+
 pub fn empty_buffer_example<S: 'static + Send + Sync + Clone>() -> Buffer<S> {
     Buffer::new().set_rows(Some(BufferRows::default()))
 }
 
+pub fn hello_world_rust_editor_example<S: 'static + Send + Sync + Clone>(
+    theme: &Theme,
+) -> Editor<S> {
+    Editor {
+        tabs: static_tabs_example(),
+        path: PathBuf::from_str("crates/ui/src/static_data.rs").unwrap(),
+        symbols: vec![Symbol(vec![
+            HighlightedText {
+                text: "fn ".to_string(),
+                color: HighlightColor::Keyword.hsla(&theme),
+            },
+            HighlightedText {
+                text: "main".to_string(),
+                color: HighlightColor::Function.hsla(&theme),
+            },
+        ])],
+        buffer: hello_world_rust_buffer_example(theme),
+    }
+}
+
 pub fn hello_world_rust_buffer_example<S: 'static + Send + Sync + Clone>(
     theme: &Theme,
 ) -> Buffer<S> {
@@ -271,6 +397,26 @@ pub fn hello_world_rust_buffer_rows(theme: &Theme) -> Vec<BufferRow> {
     ]
 }
 
+pub fn hello_world_rust_editor_with_status_example<S: 'static + Send + Sync + Clone>(
+    theme: &Theme,
+) -> Editor<S> {
+    Editor {
+        tabs: static_tabs_example(),
+        path: PathBuf::from_str("crates/ui/src/static_data.rs").unwrap(),
+        symbols: vec![Symbol(vec![
+            HighlightedText {
+                text: "fn ".to_string(),
+                color: HighlightColor::Keyword.hsla(&theme),
+            },
+            HighlightedText {
+                text: "main".to_string(),
+                color: HighlightColor::Function.hsla(&theme),
+            },
+        ])],
+        buffer: hello_world_rust_buffer_with_status_example(theme),
+    }
+}
+
 pub fn hello_world_rust_buffer_with_status_example<S: 'static + Send + Sync + Clone>(
     theme: &Theme,
 ) -> Buffer<S> {