Cargo.lock 🔗
@@ -4804,6 +4804,7 @@ dependencies = [
"project2",
"settings2",
"theme2",
+ "ui2",
"util",
"workspace2",
]
Conrad Irwin created
Cargo.lock | 1
crates/editor2/src/editor.rs | 16
crates/language_selector2/Cargo.toml | 3
crates/language_selector2/src/active_buffer_language.rs | 58 +--
crates/language_selector2/src/language_selector.rs | 138 +++++++---
crates/workspace2/src/workspace2.rs | 5
crates/zed2/src/main.rs | 2
crates/zed2/src/zed2.rs | 6
8 files changed, 131 insertions(+), 98 deletions(-)
@@ -4804,6 +4804,7 @@ dependencies = [
"project2",
"settings2",
"theme2",
+ "ui2",
"util",
"workspace2",
]
@@ -1920,14 +1920,14 @@ impl Editor {
// self.buffer.read(cx).read(cx).file_at(point).cloned()
// }
- // pub fn active_excerpt(
- // &self,
- // cx: &AppContext,
- // ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
- // self.buffer
- // .read(cx)
- // .excerpt_containing(self.selections.newest_anchor().head(), cx)
- // }
+ pub fn active_excerpt(
+ &self,
+ cx: &AppContext,
+ ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
+ self.buffer
+ .read(cx)
+ .excerpt_containing(self.selections.newest_anchor().head(), cx)
+ }
// pub fn style(&self, cx: &AppContext) -> EditorStyle {
// build_style(
@@ -9,13 +9,14 @@ path = "src/language_selector.rs"
doctest = false
[dependencies]
-editor2 = { package = "editor2", path = "../editor2" }
+editor = { package = "editor2", path = "../editor2" }
fuzzy = { package = "fuzzy2", path = "../fuzzy2" }
language = { package = "language2", path = "../language2" }
gpui = { package = "gpui2", path = "../gpui2" }
picker = { package = "picker2", path = "../picker2" }
project = { package = "project2", path = "../project2" }
theme = { package = "theme2", path = "../theme2" }
+ui = { package = "ui2", path = "../ui2" }
settings = { package = "settings2", path = "../settings2" }
util = { path = "../util" }
workspace = { package = "workspace2", path = "../workspace2" }
@@ -1,15 +1,16 @@
use editor::Editor;
use gpui::{
- elements::*,
- platform::{CursorStyle, MouseButton},
- Entity, Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
+ div, Div, IntoElement, ParentElement, Render, Subscription, View, ViewContext, WeakView,
};
use std::sync::Arc;
+use ui::{Button, ButtonCommon, Clickable, Tooltip};
use workspace::{item::ItemHandle, StatusItemView, Workspace};
+use crate::LanguageSelector;
+
pub struct ActiveBufferLanguage {
active_language: Option<Option<Arc<str>>>,
- workspace: WeakViewHandle<Workspace>,
+ workspace: WeakView<Workspace>,
_observe_active_editor: Option<Subscription>,
}
@@ -22,7 +23,7 @@ impl ActiveBufferLanguage {
}
}
- fn update_language(&mut self, editor: ViewHandle<Editor>, cx: &mut ViewContext<Self>) {
+ fn update_language(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
self.active_language = Some(None);
let editor = editor.read(cx);
@@ -36,44 +37,29 @@ impl ActiveBufferLanguage {
}
}
-impl Entity for ActiveBufferLanguage {
- type Event = ();
-}
-
-impl View for ActiveBufferLanguage {
- fn ui_name() -> &'static str {
- "ActiveBufferLanguage"
- }
+impl Render for ActiveBufferLanguage {
+ type Element = Div;
- fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
- if let Some(active_language) = self.active_language.as_ref() {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Div {
+ div().when_some(self.active_language.as_ref(), |el, active_language| {
let active_language_text = if let Some(active_language_text) = active_language {
active_language_text.to_string()
} else {
"Unknown".to_string()
};
- let theme = theme::current(cx).clone();
- MouseEventHandler::new::<Self, _>(0, cx, |state, cx| {
- let theme = &theme::current(cx).workspace.status_bar;
- let style = theme.active_language.style_for(state);
- Label::new(active_language_text, style.text.clone())
- .contained()
- .with_style(style.container)
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_click(MouseButton::Left, |_, this, cx| {
- if let Some(workspace) = this.workspace.upgrade(cx) {
- workspace.update(cx, |workspace, cx| {
- crate::toggle(workspace, &Default::default(), cx)
- });
- }
- })
- .with_tooltip::<Self>(0, "Select Language", None, theme.tooltip.clone(), cx)
- .into_any()
- } else {
- Empty::new().into_any()
- }
+ el.child(
+ Button::new("change-language", active_language_text)
+ .on_click(cx.listener(|this, _, cx| {
+ if let Some(workspace) = this.workspace.upgrade() {
+ workspace.update(cx, |workspace, cx| {
+ LanguageSelector::toggle(workspace, cx)
+ });
+ }
+ }))
+ .tooltip(|cx| Tooltip::text("Select Language", cx)),
+ )
+ })
}
}
@@ -4,50 +4,88 @@ pub use active_buffer_language::ActiveBufferLanguage;
use anyhow::anyhow;
use editor::Editor;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
-use gpui::{actions, elements::*, AppContext, ModelHandle, MouseState, ViewContext};
+use gpui::{
+ actions, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
+ Model, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
+};
use language::{Buffer, LanguageRegistry};
-use picker::{Picker, PickerDelegate, PickerEvent};
+use picker::{Picker, PickerDelegate};
use project::Project;
use std::sync::Arc;
+use ui::{v_stack, HighlightedLabel, ListItem, Selectable};
use util::ResultExt;
use workspace::Workspace;
actions!(Toggle);
pub fn init(cx: &mut AppContext) {
- cx.observe_new_views(LanguagePicker::register).detach();
+ cx.observe_new_views(LanguageSelector::register).detach();
}
-pub fn init(cx: &mut AppContext) {
- Picker::<LanguageSelectorDelegate>::init(cx);
- cx.add_action(toggle);
+pub struct LanguageSelector {
+ picker: View<Picker<LanguageSelectorDelegate>>,
}
-pub fn toggle(
- workspace: &mut Workspace,
- _: &Toggle,
- cx: &mut ViewContext<Workspace>,
-) -> Option<()> {
- let (_, buffer, _) = workspace
- .active_item(cx)?
- .act_as::<Editor>(cx)?
- .read(cx)
- .active_excerpt(cx)?;
- workspace.toggle_modal(cx, |workspace, cx| {
+impl LanguageSelector {
+ fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
+ dbg!("regsiter");
+ workspace.register_action(move |workspace, _: &Toggle, cx| {
+ Self::toggle(workspace, cx);
+ });
+ }
+
+ fn toggle(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> Option<()> {
let registry = workspace.app_state().languages.clone();
- cx.add_view(|cx| {
- Picker::new(
- LanguageSelectorDelegate::new(buffer, workspace.project().clone(), registry),
- cx,
- )
- })
- });
- Some(())
+ let (_, buffer, _) = workspace
+ .active_item(cx)?
+ .act_as::<Editor>(cx)?
+ .read(cx)
+ .active_excerpt(cx)?;
+ let project = workspace.project().clone();
+
+ workspace.toggle_modal(cx, move |cx| {
+ LanguageSelector::new(buffer, project, registry, cx)
+ });
+ Some(())
+ }
+
+ fn new(
+ buffer: Model<Buffer>,
+ project: Model<Project>,
+ language_registry: Arc<LanguageRegistry>,
+ cx: &mut ViewContext<Self>,
+ ) -> Self {
+ let delegate = LanguageSelectorDelegate::new(
+ cx.view().downgrade(),
+ buffer,
+ project,
+ language_registry,
+ );
+
+ let picker = cx.build_view(|cx| Picker::new(delegate, cx));
+ Self { picker }
+ }
}
+impl Render for LanguageSelector {
+ type Element = Div;
+
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
+ v_stack().min_w_96().child(self.picker.clone())
+ }
+}
+
+impl FocusableView for LanguageSelector {
+ fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+ self.picker.focus_handle(cx)
+ }
+}
+impl EventEmitter<DismissEvent> for LanguageSelector {}
+
pub struct LanguageSelectorDelegate {
- buffer: ModelHandle<Buffer>,
- project: ModelHandle<Project>,
+ language_selector: WeakView<LanguageSelector>,
+ buffer: Model<Buffer>,
+ project: Model<Project>,
language_registry: Arc<LanguageRegistry>,
candidates: Vec<StringMatchCandidate>,
matches: Vec<StringMatch>,
@@ -56,8 +94,9 @@ pub struct LanguageSelectorDelegate {
impl LanguageSelectorDelegate {
fn new(
- buffer: ModelHandle<Buffer>,
- project: ModelHandle<Project>,
+ language_selector: WeakView<LanguageSelector>,
+ buffer: Model<Buffer>,
+ project: Model<Project>,
language_registry: Arc<LanguageRegistry>,
) -> Self {
let candidates = language_registry
@@ -78,6 +117,7 @@ impl LanguageSelectorDelegate {
matches.sort_unstable_by(|mat1, mat2| mat1.string.cmp(&mat2.string));
Self {
+ language_selector,
buffer,
project,
language_registry,
@@ -89,6 +129,8 @@ impl LanguageSelectorDelegate {
}
impl PickerDelegate for LanguageSelectorDelegate {
+ type ListItem = ListItem;
+
fn placeholder_text(&self) -> Arc<str> {
"Select a language...".into()
}
@@ -106,23 +148,25 @@ impl PickerDelegate for LanguageSelectorDelegate {
cx.spawn(|_, mut cx| async move {
let language = language.await?;
let project = project
- .upgrade(&cx)
+ .upgrade()
.ok_or_else(|| anyhow!("project was dropped"))?;
let buffer = buffer
- .upgrade(&cx)
+ .upgrade()
.ok_or_else(|| anyhow!("buffer was dropped"))?;
project.update(&mut cx, |project, cx| {
project.set_language_for_buffer(&buffer, language, cx);
- });
- anyhow::Ok(())
+ })
})
.detach_and_log_err(cx);
}
-
- cx.emit(PickerEvent::Dismiss);
+ self.dismissed(cx);
}
- fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
+ fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ self.language_selector
+ .update(cx, |_, cx| cx.emit(DismissEvent))
+ .log_err();
+ }
fn selected_index(&self) -> usize {
self.selected_index
@@ -137,7 +181,7 @@ impl PickerDelegate for LanguageSelectorDelegate {
query: String,
cx: &mut ViewContext<Picker<Self>>,
) -> gpui::Task<()> {
- let background = cx.background().clone();
+ let background = cx.background_executor().clone();
let candidates = self.candidates.clone();
cx.spawn(|this, mut cx| async move {
let matches = if query.is_empty() {
@@ -164,7 +208,7 @@ impl PickerDelegate for LanguageSelectorDelegate {
};
this.update(&mut cx, |this, cx| {
- let delegate = this.delegate_mut();
+ let delegate = &mut this.delegate;
delegate.matches = matches;
delegate.selected_index = delegate
.selected_index
@@ -178,23 +222,21 @@ impl PickerDelegate for LanguageSelectorDelegate {
fn render_match(
&self,
ix: usize,
- mouse_state: &mut MouseState,
selected: bool,
- cx: &AppContext,
- ) -> AnyElement<Picker<Self>> {
- let theme = theme::current(cx);
+ cx: &mut ViewContext<Picker<Self>>,
+ ) -> Option<Self::ListItem> {
let mat = &self.matches[ix];
- let style = theme.picker.item.in_state(selected).style_for(mouse_state);
let buffer_language_name = self.buffer.read(cx).language().map(|l| l.name());
let mut label = mat.string.clone();
if buffer_language_name.as_deref() == Some(mat.string.as_str()) {
label.push_str(" (current)");
}
- Label::new(label, style.label.clone())
- .with_highlights(mat.positions.clone())
- .contained()
- .with_style(style.container)
- .into_any()
+ Some(
+ ListItem::new(ix)
+ .inset(true)
+ .selected(selected)
+ .child(HighlightedLabel::new(label, mat.positions.clone())),
+ )
}
}
@@ -2164,7 +2164,10 @@ impl Workspace {
cx: &mut ViewContext<Self>,
) {
match event {
- pane::Event::AddItem { item } => item.added_to_pane(self, pane, cx),
+ pane::Event::AddItem { item } => {
+ self.handle_pane_focused(pane.clone(), cx);
+ item.added_to_pane(self, pane, cx);
+ }
pane::Event::Split(direction) => {
self.split_and_clone(pane, *direction, cx);
}
@@ -216,7 +216,7 @@ fn main() {
terminal_view::init(cx);
// journal2::init(app_state.clone(), cx);
- // language_selector::init(cx);
+ language_selector::init(cx);
theme_selector::init(cx);
// activity_indicator::init(cx);
// language_tools::init(cx);
@@ -142,8 +142,8 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
cx.build_view(|cx| diagnostics::items::DiagnosticIndicator::new(workspace, cx));
let activity_indicator =
activity_indicator::ActivityIndicator::new(workspace, app_state.languages.clone(), cx);
- let active_buffer_language =
- cx.add_view(|_| language_selector::ActiveBufferLanguage::new(workspace));
+ let active_buffer_language =
+ cx.build_view(|_| language_selector::ActiveBufferLanguage::new(workspace));
// let vim_mode_indicator = cx.add_view(|cx| vim::ModeIndicator::new(cx));
// let feedback_button = cx.add_view(|_| {
// feedback::deploy_feedback_button::DeployFeedbackButton::new(workspace)
@@ -155,7 +155,7 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
// status_bar.add_right_item(feedback_button, cx);
// status_bar.add_right_item(copilot, cx);
- status_bar.add_right_item(active_buffer_language, 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);
});