diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index 43b3294471fc9932df259d9f3271485c5b0d7a89..6a9ecd89516bcd0fe00866125925d327b73d43cb 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -8,9 +8,9 @@ use anyhow::{anyhow, Context, Result}; use collections::HashSet; use futures::future::try_join_all; use gpui::{ - div, point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, EventEmitter, - FocusHandle, Model, ParentElement, Pixels, SharedString, Styled, Subscription, Task, View, - ViewContext, VisualContext, WeakView, WindowContext, + div, point, AnyElement, AppContext, AsyncAppContext, Div, Entity, EntityId, EventEmitter, + FocusHandle, IntoElement, Model, ParentElement, Pixels, Render, SharedString, Styled, + Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use language::{ proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, CharKind, OffsetRangeExt, @@ -20,6 +20,7 @@ use project::{search::SearchQuery, FormatTrigger, Item as _, Project, ProjectPat use rpc::proto::{self, update_view, PeerId}; use settings::Settings; use smallvec::SmallVec; +use std::fmt::Write; use std::{ borrow::Cow, cmp::{self, Ordering}, @@ -31,8 +32,11 @@ use std::{ use text::Selection; use theme::{ActiveTheme, Theme}; use ui::{Color, Label}; -use util::{paths::PathExt, ResultExt, TryFutureExt}; -use workspace::item::{BreadcrumbText, FollowEvent, FollowableEvents, FollowableItemHandle}; +use util::{paths::PathExt, paths::FILE_ROW_COLUMN_DELIMITER, ResultExt, TryFutureExt}; +use workspace::{ + item::{BreadcrumbText, FollowEvent, FollowableEvents, FollowableItemHandle}, + StatusItemView, +}; use workspace::{ item::{FollowableItem, Item, ItemEvent, ItemHandle, ProjectItem}, searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle}, @@ -1119,86 +1123,78 @@ pub struct CursorPosition { _observe_active_editor: Option, } -// impl Default for CursorPosition { -// fn default() -> Self { -// Self::new() -// } -// } +impl Default for CursorPosition { + fn default() -> Self { + Self::new() + } +} -// impl CursorPosition { -// pub fn new() -> Self { -// Self { -// position: None, -// selected_count: 0, -// _observe_active_editor: None, -// } -// } - -// fn update_position(&mut self, editor: View, cx: &mut ViewContext) { -// let editor = editor.read(cx); -// let buffer = editor.buffer().read(cx).snapshot(cx); - -// self.selected_count = 0; -// let mut last_selection: Option> = None; -// for selection in editor.selections.all::(cx) { -// self.selected_count += selection.end - selection.start; -// if last_selection -// .as_ref() -// .map_or(true, |last_selection| selection.id > last_selection.id) -// { -// last_selection = Some(selection); -// } -// } -// self.position = last_selection.map(|s| s.head().to_point(&buffer)); +impl CursorPosition { + pub fn new() -> Self { + Self { + position: None, + selected_count: 0, + _observe_active_editor: None, + } + } -// cx.notify(); -// } -// } + fn update_position(&mut self, editor: View, cx: &mut ViewContext) { + let editor = editor.read(cx); + let buffer = editor.buffer().read(cx).snapshot(cx); -// impl Entity for CursorPosition { -// type Event = (); -// } + self.selected_count = 0; + let mut last_selection: Option> = None; + for selection in editor.selections.all::(cx) { + self.selected_count += selection.end - selection.start; + if last_selection + .as_ref() + .map_or(true, |last_selection| selection.id > last_selection.id) + { + last_selection = Some(selection); + } + } + self.position = last_selection.map(|s| s.head().to_point(&buffer)); -// impl View for CursorPosition { -// fn ui_name() -> &'static str { -// "CursorPosition" -// } - -// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { -// if let Some(position) = self.position { -// let theme = &theme::current(cx).workspace.status_bar; -// let mut text = format!( -// "{}{FILE_ROW_COLUMN_DELIMITER}{}", -// position.row + 1, -// position.column + 1 -// ); -// if self.selected_count > 0 { -// write!(text, " ({} selected)", self.selected_count).unwrap(); -// } -// Label::new(text, theme.cursor_position.clone()).into_any() -// } else { -// Empty::new().into_any() -// } -// } -// } + cx.notify(); + } +} -// impl StatusItemView for CursorPosition { -// fn set_active_pane_item( -// &mut self, -// active_pane_item: Option<&dyn ItemHandle>, -// cx: &mut ViewContext, -// ) { -// if let Some(editor) = active_pane_item.and_then(|item| item.act_as::(cx)) { -// self._observe_active_editor = Some(cx.observe(&editor, Self::update_position)); -// self.update_position(editor, cx); -// } else { -// self.position = None; -// self._observe_active_editor = None; -// } +impl Render for CursorPosition { + type Element = Div; + + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + div().when_some(self.position, |el, position| { + let mut text = format!( + "{}{FILE_ROW_COLUMN_DELIMITER}{}", + position.row + 1, + position.column + 1 + ); + if self.selected_count > 0 { + write!(text, " ({} selected)", self.selected_count).unwrap(); + } -// cx.notify(); -// } -// } + el.child(Label::new(text)) + }) + } +} + +impl StatusItemView for CursorPosition { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn ItemHandle>, + cx: &mut ViewContext, + ) { + if let Some(editor) = active_pane_item.and_then(|item| item.act_as::(cx)) { + self._observe_active_editor = Some(cx.observe(&editor, Self::update_position)); + self.update_position(editor, cx); + } else { + self.position = None; + self._observe_active_editor = None; + } + + cx.notify(); + } +} fn path_for_buffer<'a>( buffer: &Model, diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index f31b0ae753c2a759a776857658c925eb34787dee..08fe56808a6365b689ba1f0b263c2b60499b097b 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -240,6 +240,10 @@ impl Element for AnyView { } fn paint(self, _: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + debug_assert!( + state.is_some(), + "state is None. Did you include an AnyView twice in the tree?" + ); (self.paint)(&self, state.take().unwrap(), cx) } } diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index 397859648b18c9c05c72187223e5551935072c40..8e448ae062dd1a2d02579a67dcfa500e62c6c774 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -52,22 +52,13 @@ impl Render for StatusBar { h_stack() .gap_4() .child( - h_stack() - .gap_1() - .child( - // TODO: Line / column numbers - div() - .border() - .border_color(gpui::red()) - .child(Button::new("status_line_column_numbers", "15:22")), - ) - .child( - // TODO: Language picker - div() - .border() - .border_color(gpui::red()) - .child(Button::new("status_buffer_language", "Rust")), - ), + h_stack().gap_1().child( + // TODO: Language picker + div() + .border() + .border_color(gpui::red()) + .child(Button::new("status_buffer_language", "Rust")), + ), ) .child( h_stack() @@ -133,7 +124,7 @@ impl StatusBar { h_stack() .items_center() .gap_2() - .children(self.right_items.iter().map(|item| item.to_any())) + .children(self.right_items.iter().rev().map(|item| item.to_any())) } } diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index 07b75bf8d47c4fee48e90136d4c984953b029139..080f19e60dc4ff3ecd2682d2e76d58a52a84c5e2 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -147,7 +147,7 @@ pub fn initialize_workspace(app_state: Arc, cx: &mut AppContext) { // let feedback_button = cx.add_view(|_| { // feedback::deploy_feedback_button::DeployFeedbackButton::new(workspace) // }); - // let cursor_position = cx.add_view(|_| editor::items::CursorPosition::new()); + let cursor_position = cx.build_view(|_| editor::items::CursorPosition::new()); workspace.status_bar().update(cx, |status_bar, cx| { status_bar.add_left_item(diagnostic_summary, cx); status_bar.add_left_item(activity_indicator, cx); @@ -156,7 +156,7 @@ pub fn initialize_workspace(app_state: Arc, cx: &mut AppContext) { // status_bar.add_right_item(copilot, cx); // status_bar.add_right_item(active_buffer_language, cx); // status_bar.add_right_item(vim_mode_indicator, cx); - // status_bar.add_right_item(cursor_position, cx); + status_bar.add_right_item(cursor_position, cx); }); auto_update::notify_of_any_new_update(cx);