Merge pull request #2263 from zed-industries/language-status-bar

Language status bar
This commit is contained in:
Mikayla Maki 2023-03-10 16:26:42 -08:00 committed by GitHub
commit 30a08467b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 183 additions and 35 deletions

1
Cargo.lock generated
View File

@ -1259,6 +1259,7 @@ dependencies = [
"collections",
"context_menu",
"editor",
"feedback",
"futures 0.3.25",
"fuzzy",
"gpui",

View File

@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.6667 0.400196H1.33346C0.819658 0.400196 0.399658 0.820196 0.399658 1.3326V10.6658C0.399658 11.181 0.816998 11.5982 1.33206 11.5982C1.58966 11.5982 1.82206 11.4932 1.99146 11.3238L4.51706 8.79684H10.6639C11.1763 8.79684 11.5963 8.37544 11.5963 7.86304V1.3298C11.5963 0.815996 11.1749 0.395996 10.6625 0.395996L10.6667 0.400196ZM2.2667 2.2664H6.00008V3.1988H2.26628V2.265L2.2667 2.2664ZM7.8667 6.93316H2.2667V5.99936H7.8667V6.93176V6.93316ZM9.7329 5.06556H2.26488V4.13176H9.73164V5.06416L9.7329 5.06556Z" fill="#282C34"/>
</svg>

After

Width:  |  Height:  |  Size: 636 B

View File

@ -29,6 +29,7 @@ clock = { path = "../clock" }
collections = { path = "../collections" }
context_menu = { path = "../context_menu" }
editor = { path = "../editor" }
feedback = { path = "../feedback" }
fuzzy = { path = "../fuzzy" }
gpui = { path = "../gpui" }
menu = { path = "../menu" }

View File

@ -304,12 +304,22 @@ impl CollabTitlebarItem {
label: "Sign out".into(),
action: Box::new(SignOut),
},
ContextMenuItem::Item {
label: "Give Feedback".into(),
action: Box::new(feedback::feedback_editor::GiveFeedback),
},
]
} else {
vec![ContextMenuItem::Item {
label: "Sign in".into(),
action: Box::new(Authenticate),
}]
vec![
ContextMenuItem::Item {
label: "Sign in".into(),
action: Box::new(Authenticate),
},
ContextMenuItem::Item {
label: "Give Feedback".into(),
action: Box::new(feedback::feedback_editor::GiveFeedback),
},
]
};
user_menu.show(

View File

@ -1082,18 +1082,21 @@ impl MultiBuffer {
let mut cursor = snapshot.excerpts.cursor::<usize>();
cursor.seek(&position, Bias::Right, &());
cursor.item().map(|excerpt| {
(
excerpt.id.clone(),
self.buffers
.borrow()
.get(&excerpt.buffer_id)
.unwrap()
.buffer
.clone(),
excerpt.range.context.clone(),
)
})
cursor
.item()
.or_else(|| snapshot.excerpts.last())
.map(|excerpt| {
(
excerpt.id.clone(),
self.buffers
.borrow()
.get(&excerpt.buffer_id)
.unwrap()
.buffer
.clone(),
excerpt.range.context.clone(),
)
})
}
// If point is at the end of the buffer, the last excerpt is returned

View File

@ -1,34 +1,59 @@
use gpui::{
elements::{MouseEventHandler, ParentElement, Stack, Text},
CursorStyle, Element, ElementBox, Entity, MouseButton, RenderContext, View, ViewContext,
};
use gpui::{elements::*, CursorStyle, Entity, MouseButton, RenderContext, View, ViewContext};
use settings::Settings;
use workspace::{item::ItemHandle, StatusItemView};
use crate::feedback_editor::GiveFeedback;
use crate::feedback_editor::{FeedbackEditor, GiveFeedback};
pub struct DeployFeedbackButton;
pub struct DeployFeedbackButton {
active: bool,
}
impl Entity for DeployFeedbackButton {
type Event = ();
}
impl DeployFeedbackButton {
pub fn new() -> Self {
DeployFeedbackButton { active: false }
}
}
impl View for DeployFeedbackButton {
fn ui_name() -> &'static str {
"DeployFeedbackButton"
}
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox {
let active = self.active;
Stack::new()
.with_child(
MouseEventHandler::<Self>::new(0, cx, |state, cx| {
let theme = &cx.global::<Settings>().theme;
let theme = &theme.workspace.status_bar.feedback;
let style = &theme
.workspace
.status_bar
.sidebar_buttons
.item
.style_for(state, active);
Text::new("Give Feedback", theme.style_for(state, true).clone()).boxed()
Svg::new("icons/speech_bubble_12.svg")
.with_color(style.icon_color)
.constrained()
.with_width(style.icon_size)
.aligned()
.constrained()
.with_width(style.icon_size)
.with_height(style.icon_size)
.contained()
.with_style(style.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, cx| cx.dispatch_action(GiveFeedback))
.on_click(MouseButton::Left, move |_, cx| {
if !active {
cx.dispatch_action(GiveFeedback)
}
})
.boxed(),
)
.boxed()
@ -36,5 +61,15 @@ impl View for DeployFeedbackButton {
}
impl StatusItemView for DeployFeedbackButton {
fn set_active_pane_item(&mut self, _: Option<&dyn ItemHandle>, _: &mut ViewContext<Self>) {}
fn set_active_pane_item(&mut self, item: Option<&dyn ItemHandle>, cx: &mut ViewContext<Self>) {
if let Some(item) = item {
if let Some(_) = item.downcast::<FeedbackEditor>() {
self.active = true;
cx.notify();
return;
}
}
self.active = false;
cx.notify();
}
}

View File

@ -0,0 +1,87 @@
use editor::Editor;
use gpui::{
elements::*, CursorStyle, Entity, MouseButton, RenderContext, Subscription, View, ViewContext,
ViewHandle,
};
use settings::Settings;
use std::sync::Arc;
use workspace::{item::ItemHandle, StatusItemView};
pub struct ActiveBufferLanguage {
active_language: Option<Arc<str>>,
_observe_active_editor: Option<Subscription>,
}
impl Default for ActiveBufferLanguage {
fn default() -> Self {
Self::new()
}
}
impl ActiveBufferLanguage {
pub fn new() -> Self {
Self {
active_language: None,
_observe_active_editor: None,
}
}
fn update_language(&mut self, editor: ViewHandle<Editor>, cx: &mut ViewContext<Self>) {
self.active_language.take();
let editor = editor.read(cx);
if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
if let Some(language) = buffer.read(cx).language() {
self.active_language = Some(language.name());
}
}
cx.notify();
}
}
impl Entity for ActiveBufferLanguage {
type Event = ();
}
impl View for ActiveBufferLanguage {
fn ui_name() -> &'static str {
"ActiveBufferLanguage"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
if let Some(active_language) = self.active_language.as_ref() {
MouseEventHandler::<Self>::new(0, cx, |state, cx| {
let theme = &cx.global::<Settings>().theme.workspace.status_bar;
let style = theme.active_language.style_for(state, false);
Label::new(active_language.to_string(), style.text.clone())
.contained()
.with_style(style.container)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, cx| cx.dispatch_action(crate::Toggle))
.boxed()
} else {
Empty::new().boxed()
}
}
}
impl StatusItemView for ActiveBufferLanguage {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
cx: &mut ViewContext<Self>,
) {
if let Some(editor) = active_pane_item.and_then(|item| item.act_as::<Editor>(cx)) {
self._observe_active_editor = Some(cx.observe(&editor, Self::update_language));
self.update_language(editor, cx);
} else {
self.active_language = None;
self._observe_active_editor = None;
}
cx.notify();
}
}

View File

@ -1,5 +1,6 @@
use std::sync::Arc;
mod active_buffer_language;
pub use active_buffer_language::ActiveBufferLanguage;
use editor::Editor;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
@ -10,6 +11,7 @@ use language::{Buffer, LanguageRegistry};
use picker::{Picker, PickerDelegate};
use project::Project;
use settings::Settings;
use std::sync::Arc;
use workspace::{AppState, Workspace};
actions!(language_selector, [Toggle]);

View File

@ -292,10 +292,10 @@ pub struct StatusBar {
pub height: f32,
pub item_spacing: f32,
pub cursor_position: TextStyle,
pub active_language: Interactive<ContainedText>,
pub auto_update_progress_message: TextStyle,
pub auto_update_done_message: TextStyle,
pub lsp_status: Interactive<StatusBarLspStatus>,
pub feedback: Interactive<TextStyle>,
pub sidebar_buttons: StatusBarSidebarButtons,
pub diagnostic_summary: Interactive<StatusBarDiagnosticSummary>,
pub diagnostic_message: Interactive<ContainedText>,

View File

@ -141,6 +141,7 @@ pub fn menus() -> Vec<Menu<'static>> {
MenuItem::action("View Dependency Licenses", crate::OpenLicenses),
MenuItem::action("Show Welcome", workspace::Welcome),
MenuItem::separator(),
MenuItem::action("Give us feedback", feedback::feedback_editor::GiveFeedback),
MenuItem::action(
"Copy System Specs Into Clipboard",
feedback::CopySystemSpecsIntoClipboard,

View File

@ -340,14 +340,16 @@ pub fn initialize_workspace(
cx.add_view(|cx| diagnostics::items::DiagnosticIndicator::new(workspace.project(), cx));
let activity_indicator =
activity_indicator::ActivityIndicator::new(workspace, app_state.languages.clone(), cx);
let cursor_position = cx.add_view(|_| editor::items::CursorPosition::new());
let active_buffer_language = cx.add_view(|_| language_selector::ActiveBufferLanguage::new());
let feedback_button =
cx.add_view(|_| feedback::deploy_feedback_button::DeployFeedbackButton {});
cx.add_view(|_| feedback::deploy_feedback_button::DeployFeedbackButton::new());
let cursor_position = cx.add_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);
status_bar.add_right_item(cursor_position, cx);
status_bar.add_right_item(feedback_button, cx);
status_bar.add_right_item(active_buffer_language, cx);
status_bar.add_right_item(cursor_position, cx);
});
auto_update::notify_of_any_new_update(cx.weak_handle(), cx);

View File

@ -25,6 +25,13 @@ export default function statusBar(colorScheme: ColorScheme) {
},
border: border(layer, { top: true, overlay: true }),
cursorPosition: text(layer, "sans", "variant"),
activeLanguage: {
padding: { left: 6, right: 6 },
...text(layer, "sans", "variant"),
hover: {
...text(layer, "sans", "on")
}
},
autoUpdateProgressMessage: text(layer, "sans", "variant"),
autoUpdateDoneMessage: text(layer, "sans", "variant"),
lspStatus: {
@ -44,10 +51,6 @@ export default function statusBar(colorScheme: ColorScheme) {
...text(layer, "sans"),
hover: text(layer, "sans", "hovered"),
},
feedback: {
...text(layer, "sans", "variant"),
hover: text(layer, "sans", "hovered"),
},
diagnosticSummary: {
height: 20,
iconWidth: 16,