More compilation fixes

Kirill Bulatov created

Change summary

crates/terminal2/src/terminal_settings.rs     |  12 -
crates/terminal_view2/src/terminal_element.rs | 196 +++++++++++---------
crates/terminal_view2/src/terminal_panel.rs   | 153 ++++++++-------
crates/terminal_view2/src/terminal_view.rs    |  45 +++-
crates/workspace2/src/pane.rs                 |  24 +-
crates/workspace2/src/workspace2.rs           |  19 +
6 files changed, 244 insertions(+), 205 deletions(-)

Detailed changes

crates/terminal2/src/terminal_settings.rs 🔗

@@ -1,4 +1,4 @@
-use gpui::{AppContext, FontFeatures};
+use gpui::{AppContext, FontFeatures, Pixels};
 use schemars::JsonSchema;
 use serde_derive::{Deserialize, Serialize};
 use std::{collections::HashMap, path::PathBuf};
@@ -15,7 +15,7 @@ pub enum TerminalDockPosition {
 pub struct TerminalSettings {
     pub shell: Shell,
     pub working_directory: WorkingDirectory,
-    font_size: Option<f32>,
+    pub font_size: Option<Pixels>,
     pub font_family: Option<String>,
     pub line_height: TerminalLineHeight,
     pub font_features: Option<FontFeatures>,
@@ -90,14 +90,6 @@ pub struct TerminalSettingsContent {
     pub detect_venv: Option<VenvSettings>,
 }
 
-impl TerminalSettings {
-    // todo!("move to terminal element")
-    // pub fn font_size(&self, cx: &AppContext) -> Option<f32> {
-    //     self.font_size
-    //         .map(|size| theme2::adjusted_font_size(size, cx))
-    // }
-}
-
 impl settings::Settings for TerminalSettings {
     const KEY: Option<&'static str> = Some("terminal");
 

crates/terminal_view2/src/terminal_element.rs 🔗

@@ -1,11 +1,13 @@
 use editor::{Cursor, HighlightedRange, HighlightedRangeLine};
 use gpui::{
-    serde_json::json, AnyElement, Bounds, HighlightStyle, Hsla, Line, ModelContext, MouseButton,
-    Pixels, Point, TextStyle, ViewContext, WeakModel, WindowContext,
+    AnyElement, AppContext, Bounds, Component, Element, HighlightStyle, Hsla, LayoutId, Line,
+    ModelContext, MouseButton, Pixels, Point, TextStyle, Underline, ViewContext, WeakModel,
+    WindowContext,
 };
 use itertools::Itertools;
 use language::CursorShape;
 use ordered_float::OrderedFloat;
+use settings::Settings;
 use terminal::{
     alacritty_terminal::{
         ansi::{Color as AnsiColor, Color::Named, CursorShape as AlacCursorShape, NamedColor},
@@ -21,10 +23,9 @@ use terminal::{
     TerminalSize,
 };
 use theme::ThemeSettings;
-use util::ResultExt;
 
+use std::mem;
 use std::{fmt::Debug, ops::RangeInclusive};
-use std::{mem, ops::Range};
 
 use crate::TerminalView;
 
@@ -143,7 +144,7 @@ impl LayoutRect {
         cx.paint_quad(
             Bounds::new(position, size),
             Default::default(),
-            Some(self.color),
+            self.color,
             Default::default(),
             Default::default(),
         );
@@ -282,10 +283,10 @@ impl TerminalElement {
         text_fragment: &Line,
     ) -> Option<(Vector2F, f32)> {
         if cursor_point.line() < size.total_lines() as i32 {
-            let cursor_width = if text_fragment.width() == 0. {
+            let cursor_width = if text_fragment.width == 0. {
                 size.cell_width()
             } else {
-                text_fragment.width()
+                text_fragment.width
             };
 
             //Cursor should always surround as much of the text as possible,
@@ -339,7 +340,7 @@ impl TerminalElement {
 
         let font_id = font_cache
             .select_font(text_style.font_family_id, &properties)
-            .unwrap_or(text_style.font_id);
+            .unwrap_or(8text_style.font_id);
 
         let mut result = RunStyle {
             color: fg,
@@ -369,7 +370,7 @@ impl TerminalElement {
     ) -> impl Fn(E, &mut TerminalView, &mut EventContext<TerminalView>) {
         move |event, _: &mut TerminalView, cx| {
             cx.focus_parent();
-            if let Some(conn_handle) = connection.upgrade(cx) {
+            if let Some(conn_handle) = connection.upgrade() {
                 conn_handle.update(cx, |terminal, cx| {
                     f(terminal, origin, event, cx);
 
@@ -382,7 +383,7 @@ impl TerminalElement {
     fn attach_mouse_handlers(
         &self,
         origin: Point<Pixels>,
-        visible_bounds: Bounds,
+        visible_bounds: Bounds<Pixels>,
         mode: TermMode,
         cx: &mut ViewContext<TerminalView>,
     ) {
@@ -397,7 +398,7 @@ impl TerminalElement {
                 let terminal_view = cx.handle();
                 cx.focus(&terminal_view);
                 v.context_menu.update(cx, |menu, _cx| menu.delay_cancel());
-                if let Some(conn_handle) = connection.upgrade(cx) {
+                if let Some(conn_handle) = connection.upgrade() {
                     conn_handle.update(cx, |terminal, cx| {
                         terminal.mouse_down(&event, origin);
 
@@ -412,7 +413,7 @@ impl TerminalElement {
                 }
 
                 if cx.is_self_focused() {
-                    if let Some(conn_handle) = connection.upgrade(cx) {
+                    if let Some(conn_handle) = connection.upgrade() {
                         conn_handle.update(cx, |terminal, cx| {
                             terminal.mouse_drag(event, origin);
                             cx.notify();
@@ -435,7 +436,7 @@ impl TerminalElement {
             .on_click(
                 MouseButton::Right,
                 move |event, view: &mut TerminalView, cx| {
-                    let mouse_mode = if let Some(conn_handle) = connection.upgrade(cx) {
+                    let mouse_mode = if let Some(conn_handle) = connection.upgrade() {
                         conn_handle.update(cx, |terminal, _cx| terminal.mouse_mode(event.shift))
                     } else {
                         // If we can't get the model handle, probably can't deploy the context menu
@@ -448,7 +449,7 @@ impl TerminalElement {
             )
             .on_move(move |event, _: &mut TerminalView, cx| {
                 if cx.is_self_focused() {
-                    if let Some(conn_handle) = connection.upgrade(cx) {
+                    if let Some(conn_handle) = connection.upgrade() {
                         conn_handle.update(cx, |terminal, cx| {
                             terminal.mouse_move(&event, origin);
                             cx.notify();
@@ -457,7 +458,7 @@ impl TerminalElement {
                 }
             })
             .on_scroll(move |event, _: &mut TerminalView, cx| {
-                if let Some(conn_handle) = connection.upgrade(cx) {
+                if let Some(conn_handle) = connection.upgrade() {
                     conn_handle.update(cx, |terminal, cx| {
                         terminal.scroll_wheel(event, origin);
                         cx.notify();
@@ -516,17 +517,16 @@ impl TerminalElement {
 }
 
 impl Element<TerminalView> for TerminalElement {
-    type LayoutState = LayoutState;
-    type PaintState = ();
+    type ElementState = LayoutState;
 
     fn layout(
         &mut self,
-        constraint: gpui::SizeConstraint,
-        view: &mut TerminalView,
+        view_state: &mut TerminalView,
+        element_state: &mut Self::ElementState,
         cx: &mut ViewContext<TerminalView>,
-    ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
-        let settings = settings::get::<ThemeSettings>(cx);
-        let terminal_settings = settings::get::<TerminalSettings>(cx);
+    ) -> LayoutId {
+        let settings = ThemeSettings::get_global(cx);
+        let terminal_settings = TerminalSettings::get_global(cx);
 
         //Setup layout information
         let terminal_theme = settings.theme.terminal.clone(); //TODO: Try to minimize this clone.
@@ -534,9 +534,7 @@ impl Element<TerminalView> for TerminalElement {
         let tooltip_style = settings.theme.tooltip.clone();
 
         let font_cache = cx.font_cache();
-        let font_size = terminal_settings
-            .font_size(cx)
-            .unwrap_or(settings.buffer_font_size(cx));
+        let font_size = font_size(&terminal_settings, cx).unwrap_or(settings.buffer_font_size(cx));
         let font_family_name = terminal_settings
             .font_family
             .as_ref()
@@ -575,14 +573,14 @@ impl Element<TerminalView> for TerminalElement {
             TerminalSize::new(line_height, cell_width, size)
         };
 
-        let search_matches = if let Some(terminal_model) = self.terminal.upgrade(cx) {
+        let search_matches = if let Some(terminal_model) = self.terminal.upgrade() {
             terminal_model.read(cx).matches.clone()
         } else {
             Default::default()
         };
 
         let background_color = terminal_theme.background;
-        let terminal_handle = self.terminal.upgrade(cx).unwrap();
+        let terminal_handle = self.terminal.upgrade().unwrap();
 
         let last_hovered_word = terminal_handle.update(cx, |terminal, cx| {
             terminal.set_size(dimensions);
@@ -614,7 +612,7 @@ impl Element<TerminalView> for TerminalElement {
 
             tooltip.layout(
                 SizeConstraint::new(Vector2F::zero(), cx.window_size()),
-                view,
+                view_state,
                 cx,
             );
             tooltip
@@ -709,7 +707,7 @@ impl Element<TerminalView> for TerminalElement {
         //Done!
         (
             constraint.max,
-            LayoutState {
+            Self::ElementState {
                 cells,
                 cursor,
                 background_color,
@@ -726,26 +724,25 @@ impl Element<TerminalView> for TerminalElement {
 
     fn paint(
         &mut self,
-        bounds: Bounds,
-        visible_bounds: Bounds,
-        layout: &mut Self::LayoutState,
-        view: &mut TerminalView,
+        bounds: Bounds<Pixels>,
+        view_state: &mut TerminalView,
+        element_state: &mut Self::ElementState,
         cx: &mut ViewContext<TerminalView>,
-    ) -> Self::PaintState {
+    ) {
         let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
 
         //Setup element stuff
         let clip_bounds = Some(visible_bounds);
 
         cx.paint_layer(clip_bounds, |cx| {
-            let origin = bounds.origin() + vec2f(layout.gutter, 0.);
+            let origin = bounds.origin() + vec2f(element_state.gutter, 0.);
 
             // Elements are ephemeral, only at paint time do we know what could be clicked by a mouse
-            self.attach_mouse_handlers(origin, visible_bounds, layout.mode, cx);
+            self.attach_mouse_handlers(origin, visible_bounds, element_state.mode, cx);
 
             cx.scene().push_cursor_region(gpui::CursorRegion {
                 bounds,
-                style: if layout.hyperlink_tooltip.is_some() {
+                style: if element_state.hyperlink_tooltip.is_some() {
                     CursorStyle::AlacPointingHand
                 } else {
                     CursorStyle::IBeam
@@ -755,31 +752,34 @@ impl Element<TerminalView> for TerminalElement {
             cx.paint_layer(clip_bounds, |cx| {
                 //Start with a background color
                 cx.scene().push_quad(Quad {
-                    bounds: RectF::new(bounds.origin(), bounds.size()),
-                    background: Some(layout.background_color),
+                    bounds,
+                    background: Some(element_state.background_color),
                     border: Default::default(),
                     corner_radii: Default::default(),
                 });
 
-                for rect in &layout.rects {
-                    rect.paint(origin, layout, view, cx);
+                for rect in &element_state.rects {
+                    rect.paint(origin, element_state, view_state, cx);
                 }
             });
 
             //Draw Highlighted Backgrounds
             cx.paint_layer(clip_bounds, |cx| {
-                for (relative_highlighted_range, color) in layout.relative_highlighted_ranges.iter()
+                for (relative_highlighted_range, color) in
+                    element_state.relative_highlighted_ranges.iter()
                 {
-                    if let Some((start_y, highlighted_range_lines)) =
-                        to_highlighted_range_lines(relative_highlighted_range, layout, origin)
-                    {
+                    if let Some((start_y, highlighted_range_lines)) = to_highlighted_range_lines(
+                        relative_highlighted_range,
+                        element_state,
+                        origin,
+                    ) {
                         let hr = HighlightedRange {
                             start_y, //Need to change this
-                            line_height: layout.size.line_height,
+                            line_height: element_state.size.line_height,
                             lines: highlighted_range_lines,
                             color: color.clone(),
                             //Copied from editor. TODO: move to theme or something
-                            corner_radius: 0.15 * layout.size.line_height,
+                            corner_radius: 0.15 * element_state.size.line_height,
                         };
                         hr.paint(bounds, cx);
                     }
@@ -788,63 +788,83 @@ impl Element<TerminalView> for TerminalElement {
 
             //Draw the text cells
             cx.paint_layer(clip_bounds, |cx| {
-                for cell in &layout.cells {
-                    cell.paint(origin, layout, visible_bounds, view, cx);
+                for cell in &element_state.cells {
+                    cell.paint(origin, element_state, visible_bounds, view_state, cx);
                 }
             });
 
             //Draw cursor
             if self.cursor_visible {
-                if let Some(cursor) = &layout.cursor {
+                if let Some(cursor) = &element_state.cursor {
                     cx.paint_layer(clip_bounds, |cx| {
                         cursor.paint(origin, cx);
                     })
                 }
             }
 
-            if let Some(element) = &mut layout.hyperlink_tooltip {
-                element.paint(origin, visible_bounds, view, cx)
+            if let Some(element) = &mut element_state.hyperlink_tooltip {
+                element.paint(origin, visible_bounds, view_state, cx)
             }
         });
     }
 
-    fn metadata(&self) -> Option<&dyn std::any::Any> {
-        None
+    fn id(&self) -> Option<gpui::ElementId> {
+        todo!()
     }
 
-    fn debug(
-        &self,
-        _: Bounds,
-        _: &Self::LayoutState,
-        _: &Self::PaintState,
-        _: &TerminalView,
-        _: &gpui::ViewContext<TerminalView>,
-    ) -> gpui::serde_json::Value {
-        json!({
-            "type": "TerminalElement",
-        })
+    fn initialize(
+        &mut self,
+        view_state: &mut TerminalView,
+        element_state: Option<Self::ElementState>,
+        cx: &mut ViewContext<TerminalView>,
+    ) -> Self::ElementState {
+        todo!()
     }
 
-    fn rect_for_text_range(
-        &self,
-        _: Range<usize>,
-        bounds: Bounds,
-        _: Bounds,
-        layout: &Self::LayoutState,
-        _: &Self::PaintState,
-        _: &TerminalView,
-        _: &gpui::ViewContext<TerminalView>,
-    ) -> Option<RectF> {
-        // Use the same origin that's passed to `Cursor::paint` in the paint
-        // method bove.
-        let mut origin = bounds.origin() + vec2f(layout.size.cell_width, 0.);
-
-        // TODO - Why is it necessary to move downward one line to get correct
-        // positioning? I would think that we'd want the same rect that is
-        // painted for the cursor.
-        origin += vec2f(0., layout.size.line_height);
-
-        Some(layout.cursor.as_ref()?.bounding_rect(origin))
+    // todo!() remove?
+    // fn metadata(&self) -> Option<&dyn std::any::Any> {
+    //     None
+    // }
+
+    // fn debug(
+    //     &self,
+    //     _: Bounds<Pixels>,
+    //     _: &Self::ElementState,
+    //     _: &Self::PaintState,
+    //     _: &TerminalView,
+    //     _: &gpui::ViewContext<TerminalView>,
+    // ) -> gpui::serde_json::Value {
+    //     json!({
+    //         "type": "TerminalElement",
+    //     })
+    // }
+
+    // fn rect_for_text_range(
+    //     &self,
+    //     _: Range<usize>,
+    //     bounds: Bounds<Pixels>,
+    //     _: Bounds<Pixels>,
+    //     layout: &Self::ElementState,
+    //     _: &Self::PaintState,
+    //     _: &TerminalView,
+    //     _: &gpui::ViewContext<TerminalView>,
+    // ) -> Option<Bounds<Pixels>> {
+    //     // Use the same origin that's passed to `Cursor::paint` in the paint
+    //     // method bove.
+    //     let mut origin = bounds.origin() + vec2f(layout.size.cell_width, 0.);
+
+    //     // TODO - Why is it necessary to move downward one line to get correct
+    //     // positioning? I would think that we'd want the same rect that is
+    //     // painted for the cursor.
+    //     origin += vec2f(0., layout.size.line_height);
+
+    //     Some(layout.cursor.as_ref()?.bounding_rect(origin))
+    // }
+}
+
+impl Component<TerminalView> for TerminalElement {
+    fn render(self) -> AnyElement<TerminalView> {
+        todo!()
     }
 }
 
@@ -933,3 +953,9 @@ fn to_highlighted_range_lines(
 
     Some((start_y, highlighted_range_lines))
 }
+
+fn font_size(terminal_settings: &TerminalSettings, cx: &mut AppContext) -> Option<Pixels> {
+    terminal_settings
+        .font_size
+        .map(|size| theme::adjusted_font_size(size, cx))
+}

crates/terminal_view2/src/terminal_panel.rs 🔗

@@ -3,27 +3,34 @@ use std::{path::PathBuf, sync::Arc};
 use crate::TerminalView;
 use db::kvp::KEY_VALUE_STORE;
 use gpui::{
-    actions, anyhow::Result, elements::*, serde_json, Action, AppContext, AsyncAppContext, Entity,
-    Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
+    actions, serde_json, Action, AppContext, AsyncAppContext, Entity, EventEmitter, Render,
+    Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
 };
 use project::Fs;
 use serde::{Deserialize, Serialize};
-use settings::SettingsStore;
+use settings::{Settings, SettingsStore};
 use terminal::terminal_settings::{TerminalDockPosition, TerminalSettings};
 use util::{ResultExt, TryFutureExt};
 use workspace::{
-    dock::{DockPosition, Panel},
+    dock::{DockPosition, Panel, PanelEvent},
     item::Item,
-    pane, DraggedItem, Pane, Workspace,
+    pane, Pane, Workspace,
 };
 
+use anyhow::Result;
+
 const TERMINAL_PANEL_KEY: &'static str = "TerminalPanel";
 
-actions!(terminal_panel, [ToggleFocus]);
+actions!(ToggleFocus);
 
 pub fn init(cx: &mut AppContext) {
-    cx.add_action(TerminalPanel::new_terminal);
-    cx.add_action(TerminalPanel::open_terminal);
+    cx.observe_new_views(
+        |workspace: &mut Workspace, _: &mut ViewContext<Workspace>| {
+            workspace.register_action(TerminalPanel::new_terminal);
+            workspace.register_action(TerminalPanel::open_terminal);
+        },
+    )
+    .detach();
 }
 
 #[derive(Debug)]
@@ -36,9 +43,9 @@ pub enum Event {
 }
 
 pub struct TerminalPanel {
-    pane: ViewHandle<Pane>,
+    pane: View<Pane>,
     fs: Arc<dyn Fs>,
-    workspace: WeakViewHandle<Workspace>,
+    workspace: WeakView<Workspace>,
     width: Option<f32>,
     height: Option<f32>,
     pending_serialization: Task<Option<()>>,
@@ -48,12 +55,11 @@ pub struct TerminalPanel {
 impl TerminalPanel {
     fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
         let weak_self = cx.weak_handle();
-        let pane = cx.add_view(|cx| {
-            let window = cx.window();
+        let pane = cx.build_view(|cx| {
+            let window = cx.window_handle();
             let mut pane = Pane::new(
                 workspace.weak_handle(),
                 workspace.project().clone(),
-                workspace.app_state().background_actions,
                 Default::default(),
                 cx,
             );
@@ -78,7 +84,7 @@ impl TerminalPanel {
                         move |_, cx| {
                             let this = this.clone();
                             cx.window_context().defer(move |cx| {
-                                if let Some(this) = this.upgrade(cx) {
+                                if let Some(this) = this.upgrade() {
                                     this.update(cx, |this, cx| {
                                         this.add_terminal(None, cx);
                                     });
@@ -104,7 +110,7 @@ impl TerminalPanel {
                     ))
                     .into_any()
             });
-            let buffer_search_bar = cx.add_view(search::BufferSearchBar::new);
+            let buffer_search_bar = cx.build_view(search::BufferSearchBar::new);
             pane.toolbar()
                 .update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx));
             pane
@@ -123,7 +129,7 @@ impl TerminalPanel {
             _subscriptions: subscriptions,
         };
         let mut old_dock_position = this.position(cx);
-        cx.observe_global::<SettingsStore, _>(move |this, cx| {
+        cx.observe_global::<SettingsStore>(move |this, cx| {
             let new_dock_position = this.position(cx);
             if new_dock_position != old_dock_position {
                 old_dock_position = new_dock_position;
@@ -134,13 +140,10 @@ impl TerminalPanel {
         this
     }
 
-    pub fn load(
-        workspace: WeakViewHandle<Workspace>,
-        cx: AsyncAppContext,
-    ) -> Task<Result<ViewHandle<Self>>> {
+    pub fn load(workspace: WeakView<Workspace>, cx: AsyncAppContext) -> Task<Result<View<Self>>> {
         cx.spawn(|mut cx| async move {
             let serialized_panel = if let Some(panel) = cx
-                .background()
+                .background_executor()
                 .spawn(async move { KEY_VALUE_STORE.read_kvp(TERMINAL_PANEL_KEY) })
                 .await
                 .log_err()
@@ -151,7 +154,7 @@ impl TerminalPanel {
                 None
             };
             let (panel, pane, items) = workspace.update(&mut cx, |workspace, cx| {
-                let panel = cx.add_view(|cx| TerminalPanel::new(workspace, cx));
+                let panel = cx.build_view(|cx| TerminalPanel::new(workspace, cx));
                 let items = if let Some(serialized_panel) = serialized_panel.as_ref() {
                     panel.update(cx, |panel, cx| {
                         cx.notify();
@@ -189,7 +192,7 @@ impl TerminalPanel {
                 let mut active_ix = None;
                 for item in items {
                     if let Some(item) = item.log_err() {
-                        let item_id = item.id();
+                        let item_id = item.entity_id().as_u64();
                         pane.add_item(Box::new(item), false, false, None, cx);
                         if Some(item_id) == active_item_id {
                             active_ix = Some(pane.items_len() - 1);
@@ -208,7 +211,7 @@ impl TerminalPanel {
 
     fn handle_pane_event(
         &mut self,
-        _pane: ViewHandle<Pane>,
+        _pane: View<Pane>,
         event: &pane::Event,
         cx: &mut ViewContext<Self>,
     ) {
@@ -221,7 +224,7 @@ impl TerminalPanel {
             pane::Event::Focus => cx.emit(Event::Focus),
 
             pane::Event::AddItem { item } => {
-                if let Some(workspace) = self.workspace.upgrade(cx) {
+                if let Some(workspace) = self.workspace.upgrade() {
                     let pane = self.pane.clone();
                     workspace.update(cx, |workspace, cx| item.added_to_pane(workspace, pane, cx))
                 }
@@ -261,24 +264,23 @@ impl TerminalPanel {
     fn add_terminal(&mut self, working_directory: Option<PathBuf>, cx: &mut ViewContext<Self>) {
         let workspace = self.workspace.clone();
         cx.spawn(|this, mut cx| async move {
-            let pane = this.read_with(&cx, |this, _| this.pane.clone())?;
+            let pane = this.update(&mut cx, |this, _| this.pane.clone())?;
             workspace.update(&mut cx, |workspace, cx| {
                 let working_directory = if let Some(working_directory) = working_directory {
                     Some(working_directory)
                 } else {
-                    let working_directory_strategy = settings::get::<TerminalSettings>(cx)
-                        .working_directory
-                        .clone();
+                    let working_directory_strategy =
+                        TerminalSettings::get_global(cx).working_directory.clone();
                     crate::get_working_directory(workspace, cx, working_directory_strategy)
                 };
 
-                let window = cx.window();
+                let window = cx.window_handle();
                 if let Some(terminal) = workspace.project().update(cx, |project, cx| {
                     project
                         .create_terminal(working_directory, window, cx)
                         .log_err()
                 }) {
-                    let terminal = Box::new(cx.add_view(|cx| {
+                    let terminal = Box::new(cx.build_view(|cx| {
                         TerminalView::new(
                             terminal,
                             workspace.weak_handle(),
@@ -287,7 +289,7 @@ impl TerminalPanel {
                         )
                     }));
                     pane.update(cx, |pane, cx| {
-                        let focus = pane.has_focus();
+                        let focus = pane.has_focus(cx);
                         pane.add_item(terminal, true, focus, None, cx);
                     });
                 }
@@ -303,12 +305,16 @@ impl TerminalPanel {
             .pane
             .read(cx)
             .items()
-            .map(|item| item.id())
+            .map(|item| item.id().as_u64())
             .collect::<Vec<_>>();
-        let active_item_id = self.pane.read(cx).active_item().map(|item| item.id());
+        let active_item_id = self
+            .pane
+            .read(cx)
+            .active_item()
+            .map(|item| item.id().as_u64());
         let height = self.height;
         let width = self.width;
-        self.pending_serialization = cx.background().spawn(
+        self.pending_serialization = cx.background_executor().spawn(
             async move {
                 KEY_VALUE_STORE
                     .write_kvp(
@@ -328,29 +334,25 @@ impl TerminalPanel {
     }
 }
 
-impl Entity for TerminalPanel {
-    type Event = Event;
-}
-
-impl View for TerminalPanel {
-    fn ui_name() -> &'static str {
-        "TerminalPanel"
-    }
+impl EventEmitter<Event> for TerminalPanel {}
+impl EventEmitter<PanelEvent> for TerminalPanel {}
 
+impl Render for TerminalPanel {
     fn render(&mut self, cx: &mut ViewContext<Self>) -> gpui::AnyElement<Self> {
         ChildView::new(&self.pane, cx).into_any()
     }
 
-    fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
-        if cx.is_self_focused() {
-            cx.focus(&self.pane);
-        }
-    }
+    // todo!()
+    // fn focus_in(&mut self, _: gpui::AnyView, cx: &mut ViewContext<Self>) {
+    //     if cx.is_self_focused() {
+    //         cx.focus(&self.pane);
+    //     }
+    // }
 }
 
 impl Panel for TerminalPanel {
     fn position(&self, cx: &WindowContext) -> DockPosition {
-        match settings::get::<TerminalSettings>(cx).dock {
+        match TerminalSettings::get_global(cx).dock {
             TerminalDockPosition::Left => DockPosition::Left,
             TerminalDockPosition::Bottom => DockPosition::Bottom,
             TerminalDockPosition::Right => DockPosition::Right,
@@ -373,7 +375,7 @@ impl Panel for TerminalPanel {
     }
 
     fn size(&self, cx: &WindowContext) -> f32 {
-        let settings = settings::get::<TerminalSettings>(cx);
+        let settings = TerminalSettings::get_global(cx);
         match self.position(cx) {
             DockPosition::Left | DockPosition::Right => {
                 self.width.unwrap_or_else(|| settings.default_width)
@@ -391,14 +393,6 @@ impl Panel for TerminalPanel {
         cx.notify();
     }
 
-    fn should_zoom_in_on_event(event: &Event) -> bool {
-        matches!(event, Event::ZoomIn)
-    }
-
-    fn should_zoom_out_on_event(event: &Event) -> bool {
-        matches!(event, Event::ZoomOut)
-    }
-
     fn is_zoomed(&self, cx: &WindowContext) -> bool {
         self.pane.read(cx).is_zoomed()
     }
@@ -430,31 +424,44 @@ impl Panel for TerminalPanel {
         }
     }
 
-    fn should_change_position_on_event(event: &Self::Event) -> bool {
-        matches!(event, Event::DockPositionChanged)
+    fn has_focus(&self, cx: &WindowContext) -> bool {
+        self.pane.read(cx).has_focus(cx)
     }
 
-    fn should_activate_on_event(_: &Self::Event) -> bool {
-        false
+    fn persistent_name(&self) -> &'static str {
+        todo!()
     }
 
-    fn should_close_on_event(event: &Event) -> bool {
-        matches!(event, Event::Close)
-    }
+    // todo!() is it needed?
+    // fn should_change_position_on_event(event: &Self::Event) -> bool {
+    //     matches!(event, Event::DockPositionChanged)
+    // }
 
-    fn has_focus(&self, cx: &WindowContext) -> bool {
-        self.pane.read(cx).has_focus()
-    }
+    // fn should_activate_on_event(_: &Self::Event) -> bool {
+    //     false
+    // }
 
-    fn is_focus_event(event: &Self::Event) -> bool {
-        matches!(event, Event::Focus)
-    }
+    // fn should_close_on_event(event: &Event) -> bool {
+    //     matches!(event, Event::Close)
+    // }
+
+    // fn is_focus_event(event: &Self::Event) -> bool {
+    //     matches!(event, Event::Focus)
+    // }
+
+    // fn should_zoom_in_on_event(event: &Event) -> bool {
+    //     matches!(event, Event::ZoomIn)
+    // }
+
+    // fn should_zoom_out_on_event(event: &Event) -> bool {
+    //     matches!(event, Event::ZoomOut)
+    // }
 }
 
 #[derive(Serialize, Deserialize)]
 struct SerializedTerminalPanel {
-    items: Vec<usize>,
-    active_item_id: Option<usize>,
+    items: Vec<u64>,
+    active_item_id: Option<u64>,
     width: Option<f32>,
     height: Option<f32>,
 }

crates/terminal_view2/src/terminal_view.rs 🔗

@@ -10,10 +10,11 @@ use anyhow::Context;
 use dirs::home_dir;
 use editor::{scroll::autoscroll::Autoscroll, Editor};
 use gpui::{
-    actions, div, img, red, register_action, AnyElement, AppContext, Component, Div, EventEmitter,
-    FocusEvent, FocusHandle, Focusable, FocusableKeyDispatch, InputHandler, KeyDownEvent,
-    Keystroke, Model, ParentElement, Pixels, Render, StatefulInteractivity, StatelessInteractive,
-    Styled, Task, View, ViewContext, VisualContext, WeakView,
+    actions, div, img, red, register_action, AnyElement, AppContext, Component, DispatchPhase, Div,
+    EventEmitter, FocusEvent, FocusHandle, Focusable, FocusableKeyDispatch, InputHandler,
+    KeyDownEvent, Keystroke, Model, ParentElement, Pixels, Render, SharedString,
+    StatefulInteractivity, StatelessInteractive, Styled, Task, View, ViewContext, VisualContext,
+    WeakView,
 };
 use language::Bias;
 use project::{search::SearchQuery, LocalWorktree, Project};
@@ -21,7 +22,6 @@ use serde::Deserialize;
 use settings::Settings;
 use smol::Timer;
 use std::{
-    borrow::Cow,
     ops::RangeInclusive,
     path::{Path, PathBuf},
     sync::Arc,
@@ -40,7 +40,7 @@ use workspace::{
     item::{BreadcrumbText, Item, ItemEvent},
     notifications::NotifyResultExt,
     register_deserializable_item,
-    searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle},
+    searchable::{SearchEvent, SearchOptions, SearchableItem},
     NewCenterTerminal, Pane, ToolbarItemLocation, Workspace, WorkspaceId,
 };
 
@@ -51,11 +51,11 @@ const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
 pub struct ScrollTerminal(pub i32);
 
 #[register_action]
-#[derive(Clone, Default, Deserialize, PartialEq)]
+#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
 pub struct SendText(String);
 
 #[register_action]
-#[derive(Clone, Default, Deserialize, PartialEq)]
+#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
 pub struct SendKeystroke(String);
 
 actions!(Clear, Copy, Paste, ShowCharacterPalette, SearchTest);
@@ -260,7 +260,7 @@ impl TerminalView {
             has_bell: false,
             focus_handle: cx.focus_handle(),
             // todo!()
-            // context_menu: cx.add_view(|cx| ContextMenu::new(view_id, cx)),
+            // context_menu: cx.build_view(|cx| ContextMenu::new(view_id, cx)),
             blink_state: true,
             blinking_on: false,
             blinking_paused: false,
@@ -493,7 +493,12 @@ pub fn regex_search_for_query(query: &project::search::SearchQuery) -> Option<Re
 }
 
 impl TerminalView {
-    fn key_down(&mut self, event: &KeyDownEvent, cx: &mut ViewContext<Self>) -> bool {
+    fn key_down(
+        &mut self,
+        event: &KeyDownEvent,
+        _dispatch_phase: DispatchPhase,
+        cx: &mut ViewContext<Self>,
+    ) {
         self.clear_bel(cx);
         self.pause_cursor_blinking(cx);
 
@@ -502,7 +507,7 @@ impl TerminalView {
                 &event.keystroke,
                 TerminalSettings::get_global(cx).option_as_meta,
             )
-        })
+        });
     }
 
     fn focus_in(&mut self, event: &FocusEvent, cx: &mut ViewContext<Self>) {
@@ -652,7 +657,10 @@ impl InputHandler for TerminalView {
         todo!()
     }
 
-    fn selected_text_range(&self, cx: &AppContext) -> Option<std::ops::Range<usize>> {
+    fn selected_text_range(
+        &mut self,
+        cx: &mut ViewContext<Self>,
+    ) -> Option<std::ops::Range<usize>> {
         if self
             .terminal
             .read(cx)
@@ -706,7 +714,7 @@ impl InputHandler for TerminalView {
 }
 
 impl Item for TerminalView {
-    fn tab_tooltip_text(&self, cx: &AppContext) -> Option<Cow<str>> {
+    fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
         Some(self.terminal().read(cx).title().into())
     }
 
@@ -727,7 +735,7 @@ impl Item for TerminalView {
         &self,
         _workspace_id: WorkspaceId,
         _cx: &mut ViewContext<Self>,
-    ) -> Option<Self> {
+    ) -> Option<View<Self>> {
         //From what I can tell, there's no  way to tell the current working
         //Directory of the terminal from outside the shell. There might be
         //solutions to this, but they are non-trivial and require more IPC
@@ -789,7 +797,7 @@ impl Item for TerminalView {
             //     cx.read(|cx| {
             //         let strategy = TerminalSettings::get_global(cx).working_directory.clone();
             //         workspace
-            //             .upgrade(cx)
+            //             .upgrade()
             //             .map(|workspace| {
             //                 get_working_directory(workspace.read(cx), cx, strategy)
             //             })
@@ -817,6 +825,10 @@ impl Item for TerminalView {
         //     .detach();
         self.workspace_id = workspace.database_id();
     }
+
+    fn focus_handle(&self) -> FocusHandle {
+        self.focus_handle.clone()
+    }
 }
 
 impl SearchableItem for TerminalView {
@@ -1098,7 +1110,8 @@ mod tests {
         let project = Project::test(params.fs.clone(), [], cx).await;
         let workspace = cx
             .add_window(|cx| Workspace::test_new(project.clone(), cx))
-            .root_view(cx);
+            .root_view(cx)
+            .unwrap();
 
         (project, workspace)
     }

crates/workspace2/src/pane.rs 🔗

@@ -179,7 +179,7 @@ pub struct Pane {
     workspace: WeakView<Workspace>,
     project: Model<Project>,
     //     can_drop: Rc<dyn Fn(&DragAndDrop<Workspace>, &WindowContext) -> bool>,
-    //     can_split: bool,
+    can_split: bool,
     //     render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>>,
 }
 
@@ -347,7 +347,7 @@ impl Pane {
             workspace,
             project,
             // can_drop: Rc::new(|_, _| true),
-            // can_split: true,
+            can_split: true,
             // render_tab_bar_buttons: Rc::new(move |pane, cx| {
             //     Flex::row()
             //         // New menu
@@ -427,17 +427,17 @@ impl Pane {
     //         self.can_drop = Rc::new(can_drop);
     //     }
 
-    //     pub fn set_can_split(&mut self, can_split: bool, cx: &mut ViewContext<Self>) {
-    //         self.can_split = can_split;
-    //         cx.notify();
-    //     }
+    pub fn set_can_split(&mut self, can_split: bool, cx: &mut ViewContext<Self>) {
+        self.can_split = can_split;
+        cx.notify();
+    }
 
-    //     pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut ViewContext<Self>) {
-    //         self.toolbar.update(cx, |toolbar, cx| {
-    //             toolbar.set_can_navigate(can_navigate, cx);
-    //         });
-    //         cx.notify();
-    //     }
+    pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut ViewContext<Self>) {
+        self.toolbar.update(cx, |toolbar, cx| {
+            toolbar.set_can_navigate(can_navigate, cx);
+        });
+        cx.notify();
+    }
 
     //     pub fn set_render_tab_bar_buttons<F>(&mut self, cx: &mut ViewContext<Self>, render: F)
     //     where

crates/workspace2/src/workspace2.rs 🔗

@@ -36,11 +36,12 @@ use futures::{
     Future, FutureExt, StreamExt,
 };
 use gpui::{
-    actions, div, point, prelude::*, size, Action, AnyModel, AnyView, AnyWeakView, AppContext,
+    actions, div, point, register_action, size, Action, AnyModel, AnyView, AnyWeakView, AppContext,
     AsyncAppContext, AsyncWindowContext, Bounds, Div, Entity, EntityId, EventEmitter, FocusHandle,
-    FocusableView, GlobalPixels, KeyContext, Model, ModelContext, ParentComponent, Point, Render,
-    Size, Styled, Subscription, Task, View, ViewContext, WeakView, WindowBounds, WindowContext,
-    WindowHandle, WindowOptions,
+    FocusableView, GlobalPixels, KeyContext, Model, ModelContext, ParentElement, Point, Render,
+    Size, StatefulInteractive, StatelessInteractive, StatelessInteractivity, Styled, Subscription,
+    Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle,
+    WindowOptions,
 };
 use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
 use itertools::Itertools;
@@ -193,10 +194,11 @@ impl Clone for Toast {
     }
 }
 
-// #[derive(Clone, Deserialize, PartialEq)]
-// pub struct OpenTerminal {
-//     pub working_directory: PathBuf,
-// }
+#[register_action]
+#[derive(Debug, Default, Clone, Deserialize, PartialEq)]
+pub struct OpenTerminal {
+    pub working_directory: PathBuf,
+}
 
 // impl_actions!(
 //     workspace,
@@ -206,7 +208,6 @@ impl Clone for Toast {
 //         SwapPaneInDirection,
 //         NewFileInDirection,
 //         Toast,
-//         OpenTerminal,
 //         SaveAll,
 //         Save,
 //         CloseAllItemsAndPanes,