mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
Merge pull request #2263 from zed-industries/language-status-bar
Language status bar
This commit is contained in:
commit
30a08467b0
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1259,6 +1259,7 @@ dependencies = [
|
||||
"collections",
|
||||
"context_menu",
|
||||
"editor",
|
||||
"feedback",
|
||||
"futures 0.3.25",
|
||||
"fuzzy",
|
||||
"gpui",
|
||||
|
3
assets/icons/speech_bubble_12.svg
Normal file
3
assets/icons/speech_bubble_12.svg
Normal 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 |
@ -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" }
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
87
crates/language_selector/src/active_buffer_language.rs
Normal file
87
crates/language_selector/src/active_buffer_language.rs
Normal 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();
|
||||
}
|
||||
}
|
@ -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]);
|
||||
|
@ -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>,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user