Apply more fixes to the visual part
This commit is contained in:
parent
676a07270e
commit
75074c3297
5 changed files with 335 additions and 429 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -5008,6 +5008,7 @@ dependencies = [
|
||||||
"settings2",
|
"settings2",
|
||||||
"theme2",
|
"theme2",
|
||||||
"tree-sitter",
|
"tree-sitter",
|
||||||
|
"ui2",
|
||||||
"unindent",
|
"unindent",
|
||||||
"util",
|
"util",
|
||||||
"workspace2",
|
"workspace2",
|
||||||
|
|
|
@ -1652,14 +1652,11 @@ impl Editor {
|
||||||
Self::new(EditorMode::SingleLine, buffer, None, cx)
|
Self::new(EditorMode::SingleLine, buffer, None, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn multi_line(
|
pub fn multi_line(cx: &mut ViewContext<Self>) -> Self {
|
||||||
// field_editor_style: Option<Arc<GetFieldEditorTheme>>,
|
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
|
||||||
// cx: &mut ViewContext<Self>,
|
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||||
// ) -> Self {
|
Self::new(EditorMode::Full, buffer, None, cx)
|
||||||
// let buffer = cx.build_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
|
}
|
||||||
// let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
|
|
||||||
// Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
|
pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
|
||||||
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
|
let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
|
||||||
|
|
|
@ -17,6 +17,7 @@ language = { package = "language2", path = "../language2" }
|
||||||
project = { package = "project2", path = "../project2" }
|
project = { package = "project2", path = "../project2" }
|
||||||
workspace = { package = "workspace2", path = "../workspace2" }
|
workspace = { package = "workspace2", path = "../workspace2" }
|
||||||
gpui = { package = "gpui2", path = "../gpui2" }
|
gpui = { package = "gpui2", path = "../gpui2" }
|
||||||
|
ui = { package = "ui2", path = "../ui2" }
|
||||||
util = { path = "../util" }
|
util = { path = "../util" }
|
||||||
lsp = { package = "lsp2", path = "../lsp2" }
|
lsp = { package = "lsp2", path = "../lsp2" }
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
use collections::{HashMap, VecDeque};
|
use collections::{HashMap, VecDeque};
|
||||||
use editor::{Editor, MoveToEnd};
|
use editor::{Editor, EditorElement, EditorEvent, MoveToEnd};
|
||||||
use futures::{channel::mpsc, StreamExt};
|
use futures::{channel::mpsc, StreamExt};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, AnchorCorner, AnyElement, AppContext, Context, CursorStyle, Element, Empty, Entity,
|
actions, div, overlay, red, AnchorCorner, AnyElement, AppContext, Context, CursorStyle, Div,
|
||||||
Model, ModelContext, MouseButton, Overlay, OverlayFitMode, Subscription, View, ViewContext,
|
EventEmitter, FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ModelContext,
|
||||||
VisualContext, WeakModel,
|
MouseButton, OverlayFitMode, ParentElement, Render, Styled, Subscription, View, ViewContext,
|
||||||
|
VisualContext, WeakModel, WindowContext,
|
||||||
};
|
};
|
||||||
use language::{LanguageServerId, LanguageServerName};
|
use language::{LanguageServerId, LanguageServerName};
|
||||||
use lsp::IoKind;
|
use lsp::IoKind;
|
||||||
use project::{search::SearchQuery, Project};
|
use project::{search::SearchQuery, Project};
|
||||||
use std::{borrow::Cow, sync::Arc};
|
use std::{borrow::Cow, sync::Arc};
|
||||||
use theme::Theme;
|
use theme::{ActiveTheme, Theme};
|
||||||
|
use ui::{h_stack, v_stack, Label};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::{Item, ItemHandle},
|
item::{Item, ItemHandle},
|
||||||
searchable::{SearchableItem, SearchableItemHandle},
|
searchable::{SearchEvent, SearchableItem, SearchableItemHandle},
|
||||||
ToolbarItemLocation, ToolbarItemView, Workspace,
|
ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SEND_LINE: &str = "// Send:";
|
const SEND_LINE: &str = "// Send:";
|
||||||
|
@ -50,6 +52,7 @@ pub struct LspLogView {
|
||||||
current_server_id: Option<LanguageServerId>,
|
current_server_id: Option<LanguageServerId>,
|
||||||
is_showing_rpc_trace: bool,
|
is_showing_rpc_trace: bool,
|
||||||
project: Model<Project>,
|
project: Model<Project>,
|
||||||
|
focus_handle: FocusHandle,
|
||||||
_log_store_subscriptions: Vec<Subscription>,
|
_log_store_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,9 +113,9 @@ impl LogStore {
|
||||||
projects: HashMap::default(),
|
projects: HashMap::default(),
|
||||||
io_tx,
|
io_tx,
|
||||||
};
|
};
|
||||||
cx.spawn_weak(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
while let Some((project, server_id, io_kind, message)) = io_rx.next().await {
|
while let Some((project, server_id, io_kind, message)) = io_rx.next().await {
|
||||||
if let Some(this) = this.upgrade(&cx) {
|
if let Some(this) = this.upgrade() {
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
this.on_io(project, server_id, io_kind, &message, cx);
|
this.on_io(project, server_id, io_kind, &message, cx);
|
||||||
});
|
});
|
||||||
|
@ -120,7 +123,7 @@ impl LogStore {
|
||||||
}
|
}
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
})
|
})
|
||||||
.detach();
|
.detach_and_log_err(cx);
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +134,7 @@ impl LogStore {
|
||||||
ProjectState {
|
ProjectState {
|
||||||
servers: HashMap::default(),
|
servers: HashMap::default(),
|
||||||
_subscriptions: [
|
_subscriptions: [
|
||||||
cx.observe_release(&project, move |this, _, _| {
|
cx.observe_release(project, move |this, _, _| {
|
||||||
this.projects.remove(&weak_project);
|
this.projects.remove(&weak_project);
|
||||||
}),
|
}),
|
||||||
cx.subscribe(project, |this, project, event, cx| match event {
|
cx.subscribe(project, |this, project, event, cx| match event {
|
||||||
|
@ -185,14 +188,13 @@ impl LogStore {
|
||||||
.ok();
|
.ok();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
let this = cx.weak_handle();
|
let this = cx.handle().downgrade();
|
||||||
let weak_project = project.downgrade();
|
let weak_project = project.downgrade();
|
||||||
server_state._lsp_logs_subscription = server.map(|server| {
|
server_state._lsp_logs_subscription = server.map(|server| {
|
||||||
let server_id = server.server_id();
|
let server_id = server.server_id();
|
||||||
server.on_notification::<lsp::notification::LogMessage, _>({
|
server.on_notification::<lsp::notification::LogMessage, _>({
|
||||||
move |params, mut cx| {
|
move |params, mut cx| {
|
||||||
if let Some((project, this)) = weak_project.upgrade().zip(this.upgrade(&mut cx))
|
if let Some((project, this)) = weak_project.upgrade().zip(this.upgrade()) {
|
||||||
{
|
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
this.add_language_server_log(&project, server_id, ¶ms.message, cx);
|
this.add_language_server_log(&project, server_id, ¶ms.message, cx);
|
||||||
});
|
});
|
||||||
|
@ -413,14 +415,25 @@ impl LspLogView {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let (editor, editor_subscription) = Self::editor_for_logs(String::new(), cx);
|
let (editor, editor_subscription) = Self::editor_for_logs(String::new(), cx);
|
||||||
|
|
||||||
|
let focus_handle = cx.focus_handle();
|
||||||
|
let focus_subscription = cx.on_focus(&focus_handle, |log_view, cx| {
|
||||||
|
cx.focus_view(&log_view.editor);
|
||||||
|
});
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
|
focus_handle,
|
||||||
editor,
|
editor,
|
||||||
editor_subscription,
|
editor_subscription,
|
||||||
project,
|
project,
|
||||||
log_store,
|
log_store,
|
||||||
current_server_id: None,
|
current_server_id: None,
|
||||||
is_showing_rpc_trace: false,
|
is_showing_rpc_trace: false,
|
||||||
_log_store_subscriptions: vec![model_changes_subscription, events_subscriptions],
|
_log_store_subscriptions: vec![
|
||||||
|
model_changes_subscription,
|
||||||
|
events_subscriptions,
|
||||||
|
focus_subscription,
|
||||||
|
],
|
||||||
};
|
};
|
||||||
if let Some(server_id) = server_id {
|
if let Some(server_id) = server_id {
|
||||||
this.show_logs_for_server(server_id, cx);
|
this.show_logs_for_server(server_id, cx);
|
||||||
|
@ -433,13 +446,18 @@ impl LspLogView {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> (View<Editor>, Subscription) {
|
) -> (View<Editor>, Subscription) {
|
||||||
let editor = cx.build_view(|cx| {
|
let editor = cx.build_view(|cx| {
|
||||||
let mut editor = Editor::multi_line(None, cx);
|
let mut editor = Editor::multi_line(cx);
|
||||||
editor.set_text(log_contents, cx);
|
editor.set_text(log_contents, cx);
|
||||||
editor.move_to_end(&MoveToEnd, cx);
|
editor.move_to_end(&MoveToEnd, cx);
|
||||||
editor.set_read_only(true);
|
editor.set_read_only(true);
|
||||||
editor
|
editor
|
||||||
});
|
});
|
||||||
let editor_subscription = cx.subscribe(&editor, |_, _, event, cx| cx.emit(event.clone()));
|
let editor_subscription = cx.subscribe(
|
||||||
|
&editor,
|
||||||
|
|_, _, event: &EditorEvent, cx: &mut ViewContext<'_, LspLogView>| {
|
||||||
|
cx.emit(event.clone())
|
||||||
|
},
|
||||||
|
);
|
||||||
(editor, editor_subscription)
|
(editor, editor_subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +544,7 @@ impl LspLogView {
|
||||||
.as_singleton()
|
.as_singleton()
|
||||||
.expect("log buffer should be a singleton")
|
.expect("log buffer should be a singleton")
|
||||||
.update(cx, |_, cx| {
|
.update(cx, |_, cx| {
|
||||||
cx.spawn_weak({
|
cx.spawn({
|
||||||
let buffer = cx.handle();
|
let buffer = cx.handle();
|
||||||
|_, mut cx| async move {
|
|_, mut cx| async move {
|
||||||
let language = language.await.ok();
|
let language = language.await.ok();
|
||||||
|
@ -574,30 +592,34 @@ fn log_contents(lines: &VecDeque<String>) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for LspLogView {
|
impl Render for LspLogView {
|
||||||
fn ui_name() -> &'static str {
|
// todo!()
|
||||||
"LspLogView"
|
// fn ui_name() -> &'static str {
|
||||||
|
// "LspLogView"
|
||||||
|
// }
|
||||||
|
|
||||||
|
type Element = EditorElement;
|
||||||
|
|
||||||
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
|
self.editor.update(cx, |editor, cx| editor.render(cx))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
impl FocusableView for LspLogView {
|
||||||
ChildView::new(&self.editor, cx).into_any()
|
fn focus_handle(&self, _: &AppContext) -> FocusHandle {
|
||||||
}
|
self.focus_handle.clone()
|
||||||
|
|
||||||
fn focus_in(&mut self, _: gpui::AnyView, cx: &mut ViewContext<Self>) {
|
|
||||||
if cx.is_self_focused() {
|
|
||||||
cx.focus(&self.editor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item for LspLogView {
|
impl Item for LspLogView {
|
||||||
fn tab_content<V: 'static>(
|
type Event = EditorEvent;
|
||||||
&self,
|
|
||||||
_: Option<usize>,
|
fn to_item_events(event: &Self::Event, f: impl FnMut(workspace::item::ItemEvent)) {
|
||||||
style: &theme::Tab,
|
Editor::to_item_events(event, f)
|
||||||
_: &AppContext,
|
}
|
||||||
) -> AnyElement<V> {
|
|
||||||
Label::new("LSP Logs", style.label.clone()).into_any()
|
fn tab_content(&self, _: Option<usize>, _: bool, _: &WindowContext<'_>) -> AnyElement {
|
||||||
|
Label::new("LSP Logs").into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
||||||
|
@ -608,15 +630,6 @@ impl Item for LspLogView {
|
||||||
impl SearchableItem for LspLogView {
|
impl SearchableItem for LspLogView {
|
||||||
type Match = <Editor as SearchableItem>::Match;
|
type Match = <Editor as SearchableItem>::Match;
|
||||||
|
|
||||||
fn to_search_event(
|
|
||||||
&mut self,
|
|
||||||
event: &Self::Event,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) -> Option<workspace::searchable::SearchEvent> {
|
|
||||||
self.editor
|
|
||||||
.update(cx, |editor, cx| editor.to_search_event(event, cx))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
|
fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
self.editor.update(cx, |e, cx| e.clear_matches(cx))
|
self.editor.update(cx, |e, cx| e.clear_matches(cx))
|
||||||
}
|
}
|
||||||
|
@ -675,6 +688,8 @@ impl SearchableItem for LspLogView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EventEmitter<ToolbarItemEvent> for LspLogToolbarItemView {}
|
||||||
|
|
||||||
impl ToolbarItemView for LspLogToolbarItemView {
|
impl ToolbarItemView for LspLogToolbarItemView {
|
||||||
fn set_active_pane_item(
|
fn set_active_pane_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -688,9 +703,7 @@ impl ToolbarItemView for LspLogToolbarItemView {
|
||||||
self._log_view_subscription = Some(cx.observe(&log_view, |_, _, cx| {
|
self._log_view_subscription = Some(cx.observe(&log_view, |_, _, cx| {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}));
|
}));
|
||||||
return ToolbarItemLocation::PrimaryLeft {
|
return ToolbarItemLocation::PrimaryLeft;
|
||||||
flex: Some((1., false)),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.log_view = None;
|
self.log_view = None;
|
||||||
|
@ -699,15 +712,17 @@ impl ToolbarItemView for LspLogToolbarItemView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for LspLogToolbarItemView {
|
impl Render for LspLogToolbarItemView {
|
||||||
fn ui_name() -> &'static str {
|
type Element = Div;
|
||||||
"LspLogView"
|
// todo!()
|
||||||
}
|
// fn ui_name() -> &'static str {
|
||||||
|
// "LspLogView"
|
||||||
|
// }
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Div {
|
||||||
let theme = theme::current(cx).clone();
|
let theme = cx.theme().clone();
|
||||||
let Some(log_view) = self.log_view.as_ref() else {
|
let Some(log_view) = self.log_view.as_ref() else {
|
||||||
return Empty::new().into_any();
|
return div();
|
||||||
};
|
};
|
||||||
let (menu_rows, current_server_id) = log_view.update(cx, |log_view, cx| {
|
let (menu_rows, current_server_id) = log_view.update(cx, |log_view, cx| {
|
||||||
let menu_rows = log_view.menu_items(cx).unwrap_or_default();
|
let menu_rows = log_view.menu_items(cx).unwrap_or_default();
|
||||||
|
@ -726,19 +741,15 @@ impl View for LspLogToolbarItemView {
|
||||||
|
|
||||||
enum LspLogScroll {}
|
enum LspLogScroll {}
|
||||||
enum Menu {}
|
enum Menu {}
|
||||||
let lsp_menu = Stack::new()
|
let lsp_menu = h_stack()
|
||||||
.with_child(Self::render_language_server_menu_header(
|
.child(Self::render_language_server_menu_header(current_server, cx))
|
||||||
current_server,
|
.children(if self.menu_open {
|
||||||
&theme,
|
|
||||||
cx,
|
|
||||||
))
|
|
||||||
.with_children(if self.menu_open {
|
|
||||||
Some(
|
Some(
|
||||||
Overlay::new(
|
overlay()
|
||||||
MouseEventHandler::new::<Menu, _>(0, cx, move |_, cx| {
|
.child(
|
||||||
Flex::column()
|
v_stack()
|
||||||
.scrollable::<LspLogScroll>(0, None, cx)
|
.scrollable::<LspLogScroll>(0, None, cx)
|
||||||
.with_children(menu_rows.into_iter().map(|row| {
|
.children(menu_rows.into_iter().map(|row| {
|
||||||
Self::render_language_server_menu_item(
|
Self::render_language_server_menu_item(
|
||||||
row.server_id,
|
row.server_id,
|
||||||
row.server_name,
|
row.server_name,
|
||||||
|
@ -750,12 +761,6 @@ impl View for LspLogToolbarItemView {
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
.contained()
|
|
||||||
.with_style(theme.toolbar_dropdown_menu.container)
|
|
||||||
.constrained()
|
|
||||||
.with_width(400.)
|
|
||||||
.with_height(400.)
|
|
||||||
})
|
|
||||||
.on_down_out(MouseButton::Left, |_, this, cx| {
|
.on_down_out(MouseButton::Left, |_, this, cx| {
|
||||||
this.menu_open = false;
|
this.menu_open = false;
|
||||||
cx.notify()
|
cx.notify()
|
||||||
|
@ -765,36 +770,18 @@ impl View for LspLogToolbarItemView {
|
||||||
.with_fit_mode(OverlayFitMode::SwitchAnchor)
|
.with_fit_mode(OverlayFitMode::SwitchAnchor)
|
||||||
.with_anchor_corner(AnchorCorner::TopLeft)
|
.with_anchor_corner(AnchorCorner::TopLeft)
|
||||||
.with_z_index(999)
|
.with_z_index(999)
|
||||||
.aligned()
|
|
||||||
.bottom()
|
.bottom()
|
||||||
.left(),
|
.left(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
})
|
});
|
||||||
.aligned()
|
|
||||||
.left()
|
|
||||||
.clipped();
|
|
||||||
|
|
||||||
enum LspCleanupButton {}
|
enum LspCleanupButton {}
|
||||||
let log_cleanup_button =
|
let log_cleanup_button = div()
|
||||||
MouseEventHandler::new::<LspCleanupButton, _>(1, cx, |state, cx| {
|
.child(Label::new("Clear"))
|
||||||
let theme = theme::current(cx).clone();
|
.on_mouse_down(MouseButton::Left, move |_, cx| {
|
||||||
let style = theme
|
if let Some(log_view) = self.log_view.as_ref() {
|
||||||
.workspace
|
|
||||||
.toolbar
|
|
||||||
.toggleable_text_tool
|
|
||||||
.in_state(server_selected)
|
|
||||||
.style_for(state);
|
|
||||||
Label::new("Clear", style.text.clone())
|
|
||||||
.aligned()
|
|
||||||
.contained()
|
|
||||||
.with_style(style.container)
|
|
||||||
.constrained()
|
|
||||||
.with_height(theme.toolbar_dropdown_menu.row_height / 6.0 * 5.0)
|
|
||||||
})
|
|
||||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
|
||||||
if let Some(log_view) = this.log_view.as_ref() {
|
|
||||||
log_view.update(cx, |log_view, cx| {
|
log_view.update(cx, |log_view, cx| {
|
||||||
log_view.editor.update(cx, |editor, cx| {
|
log_view.editor.update(cx, |editor, cx| {
|
||||||
editor.set_read_only(false);
|
editor.set_read_only(false);
|
||||||
|
@ -804,17 +791,13 @@ impl View for LspLogToolbarItemView {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.cursor(CursorStyle::PointingHand);
|
||||||
.aligned()
|
|
||||||
.right();
|
|
||||||
|
|
||||||
Flex::row()
|
h_stack()
|
||||||
.with_child(lsp_menu)
|
.child(lsp_menu)
|
||||||
.with_child(log_cleanup_button)
|
.child(log_cleanup_button)
|
||||||
.contained()
|
.border_1()
|
||||||
.aligned()
|
.border_color(red())
|
||||||
.left()
|
|
||||||
.into_any_named("lsp log controls")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,11 +854,10 @@ impl LspLogToolbarItemView {
|
||||||
|
|
||||||
fn render_language_server_menu_header(
|
fn render_language_server_menu_header(
|
||||||
current_server: Option<LogMenuItem>,
|
current_server: Option<LogMenuItem>,
|
||||||
theme: &Arc<Theme>,
|
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> impl Element<Self> {
|
) -> Div {
|
||||||
|
let view = cx.view().clone();
|
||||||
enum ToggleMenu {}
|
enum ToggleMenu {}
|
||||||
MouseEventHandler::new::<ToggleMenu, _>(0, cx, move |state, _| {
|
|
||||||
let label: Cow<str> = current_server
|
let label: Cow<str> = current_server
|
||||||
.and_then(|row| {
|
.and_then(|row| {
|
||||||
Some(
|
Some(
|
||||||
|
@ -893,15 +875,16 @@ impl LspLogToolbarItemView {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| "No server selected".into());
|
.unwrap_or_else(|| "No server selected".into());
|
||||||
let style = theme.toolbar_dropdown_menu.header.style_for(state);
|
div()
|
||||||
Label::new(label, style.text.clone())
|
.child(Label::new(label))
|
||||||
.contained()
|
.cursor(CursorStyle::PointingHand)
|
||||||
.with_style(style.container)
|
.on_mouse_down(MouseButton::Left, move |_, cx| {
|
||||||
})
|
view.update(cx, |view, cx| {
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.on_click(MouseButton::Left, move |_, view, cx| {
|
|
||||||
view.toggle_menu(cx);
|
view.toggle_menu(cx);
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
.border_1()
|
||||||
|
.border_color(red())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_language_server_menu_item(
|
fn render_language_server_menu_item(
|
||||||
|
@ -913,57 +896,31 @@ impl LspLogToolbarItemView {
|
||||||
rpc_trace_selected: bool,
|
rpc_trace_selected: bool,
|
||||||
theme: &Arc<Theme>,
|
theme: &Arc<Theme>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> impl Element<Self> {
|
) -> Div {
|
||||||
enum ActivateLog {}
|
enum ActivateLog {}
|
||||||
enum ActivateRpcTrace {}
|
enum ActivateRpcTrace {}
|
||||||
enum LanguageServerCheckbox {}
|
enum LanguageServerCheckbox {}
|
||||||
|
|
||||||
Flex::column()
|
let view = cx.view().clone();
|
||||||
.with_child({
|
|
||||||
let style = &theme.toolbar_dropdown_menu.section_header;
|
v_stack()
|
||||||
Label::new(
|
.child(Label::new(format!("{} ({})", name.0, worktree_root_name)))
|
||||||
format!("{} ({})", name.0, worktree_root_name),
|
.child(
|
||||||
style.text.clone(),
|
div()
|
||||||
)
|
.child(Label::new(SERVER_LOGS))
|
||||||
.contained()
|
.cursor(CursorStyle::PointingHand)
|
||||||
.with_style(style.container)
|
.on_mouse_down(MouseButton::Left, move |_, cx| {
|
||||||
.constrained()
|
view.update(cx, |view, cx| {
|
||||||
.with_height(theme.toolbar_dropdown_menu.row_height)
|
|
||||||
})
|
|
||||||
.with_child(
|
|
||||||
MouseEventHandler::new::<ActivateLog, _>(id.0, cx, move |state, _| {
|
|
||||||
let style = theme
|
|
||||||
.toolbar_dropdown_menu
|
|
||||||
.item
|
|
||||||
.in_state(logs_selected)
|
|
||||||
.style_for(state);
|
|
||||||
Label::new(SERVER_LOGS, style.text.clone())
|
|
||||||
.contained()
|
|
||||||
.with_style(style.container)
|
|
||||||
.constrained()
|
|
||||||
.with_height(theme.toolbar_dropdown_menu.row_height)
|
|
||||||
})
|
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.on_click(MouseButton::Left, move |_, view, cx| {
|
|
||||||
view.show_logs_for_server(id, cx);
|
view.show_logs_for_server(id, cx);
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.with_child(
|
.child(
|
||||||
MouseEventHandler::new::<ActivateRpcTrace, _>(id.0, cx, move |state, cx| {
|
h_stack()
|
||||||
let style = theme
|
.child(Label::new(RPC_MESSAGES))
|
||||||
.toolbar_dropdown_menu
|
.child(
|
||||||
.item
|
|
||||||
.in_state(rpc_trace_selected)
|
|
||||||
.style_for(state);
|
|
||||||
Flex::row()
|
|
||||||
.with_child(
|
|
||||||
Label::new(RPC_MESSAGES, style.text.clone())
|
|
||||||
.constrained()
|
|
||||||
.with_height(theme.toolbar_dropdown_menu.row_height),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
ui::checkbox_with_label::<LanguageServerCheckbox, _, Self, _>(
|
ui::checkbox_with_label::<LanguageServerCheckbox, _, Self, _>(
|
||||||
Empty::new(),
|
div(),
|
||||||
&theme.welcome.checkbox,
|
&theme.welcome.checkbox,
|
||||||
rpc_trace_enabled,
|
rpc_trace_enabled,
|
||||||
id.0,
|
id.0,
|
||||||
|
@ -974,17 +931,17 @@ impl LspLogToolbarItemView {
|
||||||
)
|
)
|
||||||
.flex_float(),
|
.flex_float(),
|
||||||
)
|
)
|
||||||
.align_children_center()
|
.border_1()
|
||||||
.contained()
|
.border_color(red())
|
||||||
.with_style(style.container)
|
.cursor(CursorStyle::PointingHand)
|
||||||
.constrained()
|
.on_mouse_down(MouseButton::Left, move |_, cx| {
|
||||||
.with_height(theme.toolbar_dropdown_menu.row_height)
|
view.update(cx, |view, cx| {
|
||||||
})
|
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.on_click(MouseButton::Left, move |_, view, cx| {
|
|
||||||
view.show_rpc_trace_for_server(id, cx);
|
view.show_rpc_trace_for_server(id, cx);
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
.border_1()
|
||||||
|
.border_color(red())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,14 +953,7 @@ pub enum Event {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for LogStore {
|
impl EventEmitter<Event> for LogStore {}
|
||||||
type Event = Event;
|
impl EventEmitter<Event> for LspLogView {}
|
||||||
}
|
impl EventEmitter<EditorEvent> for LspLogView {}
|
||||||
|
impl EventEmitter<SearchEvent> for LspLogView {}
|
||||||
impl Entity for LspLogView {
|
|
||||||
type Event = editor::Event;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Entity for LspLogToolbarItemView {
|
|
||||||
type Event = ();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId};
|
use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, AnchorCorner, AppContext, CursorStyle, Div, Element, Empty, Entity, Focusable, Model,
|
actions, div, overlay, red, uniform_list, AnyElement, AppContext, CursorStyle, Div,
|
||||||
MouseButton, Overlay, OverlayFitMode, ParentElement, Render, TextStyle, UniformList,
|
EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model,
|
||||||
UniformListState, View, ViewContext, VisualContext, WeakView,
|
MouseButton, ParentElement, Render, Styled, TextStyle, UniformListState, View, ViewContext,
|
||||||
|
VisualContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use language::{Buffer, OwnedSyntaxLayerInfo, SyntaxLayerInfo};
|
use language::{Buffer, OwnedSyntaxLayerInfo, SyntaxLayerInfo};
|
||||||
use std::{mem, ops::Range, sync::Arc};
|
use settings::Settings;
|
||||||
use theme::{ActiveTheme, Theme, ThemeSettings};
|
use std::{mem, ops::Range};
|
||||||
|
use theme::{ActiveTheme, ThemeSettings};
|
||||||
use tree_sitter::{Node, TreeCursor};
|
use tree_sitter::{Node, TreeCursor};
|
||||||
|
use ui::{h_stack, Label};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::{Item, ItemHandle},
|
item::{Item, ItemHandle},
|
||||||
ui::v_stack,
|
ui::v_stack,
|
||||||
ToolbarItemLocation, ToolbarItemView, Workspace,
|
ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(debug, [OpenSyntaxTreeView]);
|
actions!(debug, [OpenSyntaxTreeView]);
|
||||||
|
@ -37,6 +40,7 @@ pub struct SyntaxTreeView {
|
||||||
list_state: UniformListState,
|
list_state: UniformListState,
|
||||||
selected_descendant_ix: Option<usize>,
|
selected_descendant_ix: Option<usize>,
|
||||||
hovered_descendant_ix: Option<usize>,
|
hovered_descendant_ix: Option<usize>,
|
||||||
|
focus_handle: FocusHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SyntaxTreeToolbarItemView {
|
pub struct SyntaxTreeToolbarItemView {
|
||||||
|
@ -72,6 +76,7 @@ impl SyntaxTreeView {
|
||||||
line_height: None,
|
line_height: None,
|
||||||
hovered_descendant_ix: None,
|
hovered_descendant_ix: None,
|
||||||
selected_descendant_ix: None,
|
selected_descendant_ix: None,
|
||||||
|
focus_handle: cx.focus_handle(),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.workspace_updated(active_item, cx);
|
this.workspace_updated(active_item, cx);
|
||||||
|
@ -229,7 +234,7 @@ impl SyntaxTreeView {
|
||||||
editor.clear_background_highlights::<Self>(cx);
|
editor.clear_background_highlights::<Self>(cx);
|
||||||
editor.highlight_background::<Self>(
|
editor.highlight_background::<Self>(
|
||||||
vec![range],
|
vec![range],
|
||||||
|theme| theme.editor.document_highlight_write_background,
|
|theme| theme.editor_document_highlight_write_background,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -281,10 +286,10 @@ impl SyntaxTreeView {
|
||||||
style: &TextStyle,
|
style: &TextStyle,
|
||||||
editor_theme: &theme::Editor,
|
editor_theme: &theme::Editor,
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> gpui::AnyElement<SyntaxTreeView> {
|
) -> Div {
|
||||||
let node = cursor.node();
|
let node = cursor.node();
|
||||||
let mut range_style = style.clone();
|
let mut range_style = style.clone();
|
||||||
let em_width = style.em_width(cx.font_cache());
|
let em_width = style.em_width(cx.text_system());
|
||||||
let gutter_padding = (em_width * editor_theme.gutter_padding_factor).round();
|
let gutter_padding = (em_width * editor_theme.gutter_padding_factor).round();
|
||||||
|
|
||||||
range_style.color = editor_theme.line_number;
|
range_style.color = editor_theme.line_number;
|
||||||
|
@ -304,64 +309,54 @@ impl SyntaxTreeView {
|
||||||
anonymous_node_style.color = color;
|
anonymous_node_style.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut row = Flex::row();
|
let mut row = h_stack();
|
||||||
if let Some(field_name) = cursor.field_name() {
|
if let Some(field_name) = cursor.field_name() {
|
||||||
let mut field_style = style.clone();
|
let mut field_style = style.clone();
|
||||||
if let Some(color) = property_color {
|
if let Some(color) = property_color {
|
||||||
field_style.color = color;
|
field_style.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
row.add_children([
|
row = row.children([Label::new(field_name), Label::new(": ")]);
|
||||||
Label::new(field_name, field_style),
|
|
||||||
Label::new(": ", style.clone()),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return row
|
return row
|
||||||
.with_child(
|
.child(
|
||||||
if node.is_named() {
|
if node.is_named() {
|
||||||
Label::new(node.kind(), style.clone())
|
Label::new(node.kind())
|
||||||
} else {
|
} else {
|
||||||
Label::new(format!("\"{}\"", node.kind()), anonymous_node_style)
|
Label::new(format!("\"{}\"", node.kind()))
|
||||||
}
|
}, // todo!()
|
||||||
.contained()
|
// .margin(em_width),
|
||||||
.with_margin_right(em_width),
|
|
||||||
)
|
)
|
||||||
.with_child(Label::new(format_node_range(node), range_style))
|
.child(Label::new(format_node_range(node)))
|
||||||
.contained()
|
.text_bg(if selected {
|
||||||
.with_background_color(if selected {
|
|
||||||
editor_theme.selection.selection
|
editor_theme.selection.selection
|
||||||
} else if hovered && list_hovered {
|
} else if hovered && list_hovered {
|
||||||
editor_theme.active_line_background
|
editor_theme.active_line_background
|
||||||
} else {
|
} else {
|
||||||
Default::default()
|
Hsla::default()
|
||||||
})
|
})
|
||||||
.with_padding_left(gutter_padding + depth as f32 * 18.0)
|
// todo!()
|
||||||
.into_any();
|
// .padding(gutter_padding + depth as f32 * 18.0)
|
||||||
|
.border_1()
|
||||||
|
.border_color(red());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for SyntaxTreeView {
|
impl Render for SyntaxTreeView {
|
||||||
type Event = ();
|
// todo!()
|
||||||
}
|
// fn ui_name() -> &'static str {
|
||||||
|
// "SyntaxTreeView"
|
||||||
|
// }
|
||||||
|
|
||||||
impl View for SyntaxTreeView {
|
type Element = Div;
|
||||||
fn ui_name() -> &'static str {
|
|
||||||
"SyntaxTreeView"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement<Self> {
|
fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Div {
|
||||||
let settings = settings::get::<ThemeSettings>(cx);
|
let settings = ThemeSettings::get_global(cx);
|
||||||
let font_family_id = settings.buffer_font_family;
|
let font = settings.buffer_font;
|
||||||
let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
|
|
||||||
let font_properties = Default::default();
|
|
||||||
let font_id = cx
|
|
||||||
.font_cache()
|
|
||||||
.select_font(font_family_id, &font_properties)
|
|
||||||
.unwrap();
|
|
||||||
let font_size = settings.buffer_font_size(cx);
|
let font_size = settings.buffer_font_size(cx);
|
||||||
|
|
||||||
let editor_theme = settings.theme.editor.clone();
|
let editor_theme = settings.active_theme;
|
||||||
let style = TextStyle {
|
let style = TextStyle {
|
||||||
color: editor_theme.text_color,
|
color: editor_theme.text_color,
|
||||||
font_family_name,
|
font_family_name,
|
||||||
|
@ -370,10 +365,16 @@ impl View for SyntaxTreeView {
|
||||||
font_size,
|
font_size,
|
||||||
font_properties: Default::default(),
|
font_properties: Default::default(),
|
||||||
underline: Default::default(),
|
underline: Default::default(),
|
||||||
soft_wrap: false,
|
font_family: todo!(),
|
||||||
|
font_features: todo!(),
|
||||||
|
line_height: todo!(),
|
||||||
|
font_weight: todo!(),
|
||||||
|
font_style: todo!(),
|
||||||
|
background_color: todo!(),
|
||||||
|
white_space: todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let line_height = cx.font_cache().line_height(font_size);
|
let line_height = cx.text_system().line_height(font_size);
|
||||||
if Some(line_height) != self.line_height {
|
if Some(line_height) != self.line_height {
|
||||||
self.line_height = Some(line_height);
|
self.line_height = Some(line_height);
|
||||||
self.hover_state_changed(cx);
|
self.hover_state_changed(cx);
|
||||||
|
@ -387,9 +388,9 @@ impl View for SyntaxTreeView {
|
||||||
{
|
{
|
||||||
let layer = layer.clone();
|
let layer = layer.clone();
|
||||||
let theme = editor_theme.clone();
|
let theme = editor_theme.clone();
|
||||||
return MouseEventHandler::new::<Self, _>(0, cx, move |state, cx| {
|
|
||||||
let list_hovered = state.hovered();
|
let list_hovered = state.hovered();
|
||||||
UniformList::new(
|
uniform_list(
|
||||||
self.list_state.clone(),
|
self.list_state.clone(),
|
||||||
layer.node().descendant_count(),
|
layer.node().descendant_count(),
|
||||||
cx,
|
cx,
|
||||||
|
@ -429,48 +430,53 @@ impl View for SyntaxTreeView {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
|
||||||
.on_move(move |event, this, cx| {
|
.on_move(move |event, this, cx| {
|
||||||
let y = event.position.y() - event.region.origin_y();
|
let y = event.position.y() - event.region.origin_y();
|
||||||
this.mouse_y = Some(y);
|
this.mouse_y = Some(y);
|
||||||
this.hover_state_changed(cx);
|
this.hover_state_changed(cx);
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, move |event, this, cx| {
|
.on_mouse_down(MouseButton::Left, move |event, cx| {
|
||||||
let y = event.position.y() - event.region.origin_y();
|
let y = event.position.y() - event.region.origin_y();
|
||||||
this.handle_click(y, cx);
|
self.handle_click(y, cx);
|
||||||
})
|
});
|
||||||
.contained()
|
|
||||||
.with_background_color(editor_theme.background)
|
|
||||||
.into_any();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Empty::new().into_any()
|
div()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventEmitter<()> for SyntaxTreeView {}
|
||||||
|
|
||||||
|
impl FocusableView for SyntaxTreeView {
|
||||||
|
fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
|
||||||
|
self.focus_handle.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item for SyntaxTreeView {
|
impl Item for SyntaxTreeView {
|
||||||
fn tab_content<V: 'static>(
|
type Event = ();
|
||||||
&self,
|
|
||||||
_: Option<usize>,
|
fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
|
||||||
style: &theme::Tab,
|
|
||||||
_: &AppContext,
|
fn tab_content(&self, _: Option<usize>, _: bool, _: &WindowContext<'_>) -> AnyElement {
|
||||||
) -> gpui::AnyElement<V> {
|
Label::new("Syntax Tree").into_any_element()
|
||||||
Label::new("Syntax Tree", style.label.clone()).into_any()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_on_split(
|
fn clone_on_split(
|
||||||
&self,
|
&self,
|
||||||
_workspace_id: workspace::WorkspaceId,
|
_: workspace::WorkspaceId,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Option<Self>
|
) -> Option<View<Self>>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
Some(cx.build_view(|cx| {
|
||||||
let mut clone = Self::new(self.workspace_handle.clone(), None, cx);
|
let mut clone = Self::new(self.workspace_handle.clone(), None, cx);
|
||||||
if let Some(editor) = &self.editor {
|
if let Some(editor) = &self.editor {
|
||||||
clone.set_editor(editor.editor.clone(), cx)
|
clone.set_editor(editor.editor.clone(), cx)
|
||||||
}
|
}
|
||||||
Some(clone)
|
clone
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,10 +489,7 @@ impl SyntaxTreeToolbarItemView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_menu(
|
fn render_menu(&mut self, cx: &mut ViewContext<'_, Self>) -> Option<Div> {
|
||||||
&mut self,
|
|
||||||
cx: &mut ViewContext<'_, '_, Self>,
|
|
||||||
) -> Option<gpui::AnyElement<Self>> {
|
|
||||||
let theme = cx.theme().clone();
|
let theme = cx.theme().clone();
|
||||||
let tree_view = self.tree_view.as_ref()?;
|
let tree_view = self.tree_view.as_ref()?;
|
||||||
let tree_view = tree_view.read(cx);
|
let tree_view = tree_view.read(cx);
|
||||||
|
@ -496,36 +499,23 @@ impl SyntaxTreeToolbarItemView {
|
||||||
let active_layer = buffer_state.active_layer.clone()?;
|
let active_layer = buffer_state.active_layer.clone()?;
|
||||||
let active_buffer = buffer_state.buffer.read(cx).snapshot();
|
let active_buffer = buffer_state.buffer.read(cx).snapshot();
|
||||||
|
|
||||||
enum Menu {}
|
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
v_stack()
|
v_stack()
|
||||||
.child(Self::render_header(&theme, &active_layer, cx))
|
.child(Self::render_header(&active_layer, cx))
|
||||||
.children(self.menu_open.then(|| {
|
.children(self.menu_open.then(|| {
|
||||||
overlay(
|
overlay().child(
|
||||||
mouse_event_handler::<Menu, _>(0, cx, move |_, cx| {
|
|
||||||
v_stack()
|
v_stack()
|
||||||
.with_children(active_buffer.syntax_layers().enumerate().map(
|
.children(active_buffer.syntax_layers().enumerate().map(
|
||||||
|(ix, layer)| {
|
|(ix, layer)| Self::render_menu_item(&active_layer, layer, ix, cx),
|
||||||
Self::render_menu_item(&theme, &active_layer, layer, ix, cx)
|
|
||||||
},
|
|
||||||
))
|
))
|
||||||
.contained()
|
.on_mouse_down_out(|e, cx| {
|
||||||
.with_style(theme.toolbar_dropdown_menu.container)
|
if e.button == MouseButton::Left {
|
||||||
.constrained()
|
self.menu_open = false;
|
||||||
.with_width(400.)
|
|
||||||
.with_height(400.)
|
|
||||||
})
|
|
||||||
.on_down_out(MouseButton::Left, |_, this, cx| {
|
|
||||||
this.menu_open = false;
|
|
||||||
cx.notify()
|
cx.notify()
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.with_hoverable(true)
|
})),
|
||||||
.with_fit_content()
|
|
||||||
.into_any()
|
|
||||||
}))
|
|
||||||
.into_any(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,71 +539,39 @@ impl SyntaxTreeToolbarItemView {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_header(
|
fn render_header(active_layer: &OwnedSyntaxLayerInfo, cx: &mut ViewContext<Self>) -> Div {
|
||||||
theme: &Arc<Theme>,
|
let view = cx.view().clone();
|
||||||
active_layer: &OwnedSyntaxLayerInfo,
|
h_stack()
|
||||||
cx: &mut ViewContext<Self>,
|
.child(Label::new(active_layer.language.name()))
|
||||||
) -> impl Element<Self> {
|
.child(Label::new(format_node_range(active_layer.node())))
|
||||||
enum ToggleMenu {}
|
.on_mouse_down(MouseButton::Left, move |_, cx| {
|
||||||
MouseEventHandler::new::<ToggleMenu, _>(0, cx, move |state, _| {
|
view.update(cx, |view, cx| view.toggle_menu(cx));
|
||||||
let style = theme.toolbar_dropdown_menu.header.style_for(state);
|
|
||||||
Flex::row()
|
|
||||||
.with_child(
|
|
||||||
Label::new(active_layer.language.name().to_string(), style.text.clone())
|
|
||||||
.contained()
|
|
||||||
.with_margin_right(style.secondary_text_spacing),
|
|
||||||
)
|
|
||||||
.with_child(Label::new(
|
|
||||||
format_node_range(active_layer.node()),
|
|
||||||
style
|
|
||||||
.secondary_text
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| style.text.clone()),
|
|
||||||
))
|
|
||||||
.contained()
|
|
||||||
.with_style(style.container)
|
|
||||||
})
|
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.on_click(MouseButton::Left, move |_, view, cx| {
|
|
||||||
view.toggle_menu(cx);
|
|
||||||
})
|
})
|
||||||
|
.cursor(CursorStyle::PointingHand)
|
||||||
|
.border_1()
|
||||||
|
.border_color(red())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_menu_item(
|
fn render_menu_item(
|
||||||
theme: &Arc<Theme>,
|
|
||||||
active_layer: &OwnedSyntaxLayerInfo,
|
active_layer: &OwnedSyntaxLayerInfo,
|
||||||
layer: SyntaxLayerInfo,
|
layer: SyntaxLayerInfo,
|
||||||
layer_ix: usize,
|
layer_ix: usize,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> impl Element<Self> {
|
) -> Div {
|
||||||
enum ActivateLayer {}
|
// todo!() styling
|
||||||
MouseEventHandler::new::<ActivateLayer, _>(layer_ix, cx, move |state, _| {
|
let _is_selected = layer.node() == active_layer.node();
|
||||||
let is_selected = layer.node() == active_layer.node();
|
let view = cx.view().clone();
|
||||||
let style = theme
|
h_stack()
|
||||||
.toolbar_dropdown_menu
|
.child(Label::new(layer.language.name().to_string()))
|
||||||
.item
|
.child(Label::new(format_node_range(layer.node())))
|
||||||
.in_state(is_selected)
|
.cursor(CursorStyle::PointingHand)
|
||||||
.style_for(state);
|
.on_mouse_down(MouseButton::Left, move |_, cx| {
|
||||||
Flex::row()
|
view.update(cx, |view, cx| {
|
||||||
.with_child(
|
|
||||||
Label::new(layer.language.name().to_string(), style.text.clone())
|
|
||||||
.contained()
|
|
||||||
.with_margin_right(style.secondary_text_spacing),
|
|
||||||
)
|
|
||||||
.with_child(Label::new(
|
|
||||||
format_node_range(layer.node()),
|
|
||||||
style
|
|
||||||
.secondary_text
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| style.text.clone()),
|
|
||||||
))
|
|
||||||
.contained()
|
|
||||||
.with_style(style.container)
|
|
||||||
})
|
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.on_click(MouseButton::Left, move |_, view, cx| {
|
|
||||||
view.select_layer(layer_ix, cx);
|
view.select_layer(layer_ix, cx);
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
.border_1()
|
||||||
|
.border_color(red())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,33 +588,32 @@ fn format_node_range(node: Node) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for SyntaxTreeToolbarItemView {
|
impl Render for SyntaxTreeToolbarItemView {
|
||||||
type Element = Focusable<Div>;
|
type Element = Div;
|
||||||
|
|
||||||
// todo!()
|
// todo!()
|
||||||
// fn ui_name() -> &'static str {
|
// fn ui_name() -> &'static str {
|
||||||
// "SyntaxTreeToolbarItemView"
|
// "SyntaxTreeToolbarItemView"
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<'_, '_, Self>) -> gpui::AnyElement<Self> {
|
fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> Div {
|
||||||
self.render_menu(cx)
|
self.render_menu(cx).unwrap_or_else(|| div())
|
||||||
.unwrap_or_else(|| Empty::new().into_any())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EventEmitter<ToolbarItemEvent> for SyntaxTreeToolbarItemView {}
|
||||||
|
|
||||||
impl ToolbarItemView for SyntaxTreeToolbarItemView {
|
impl ToolbarItemView for SyntaxTreeToolbarItemView {
|
||||||
fn set_active_pane_item(
|
fn set_active_pane_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
active_pane_item: Option<&dyn ItemHandle>,
|
active_pane_item: Option<&dyn ItemHandle>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> workspace::ToolbarItemLocation {
|
) -> ToolbarItemLocation {
|
||||||
self.menu_open = false;
|
self.menu_open = false;
|
||||||
if let Some(item) = active_pane_item {
|
if let Some(item) = active_pane_item {
|
||||||
if let Some(view) = item.downcast::<SyntaxTreeView>() {
|
if let Some(view) = item.downcast::<SyntaxTreeView>() {
|
||||||
self.tree_view = Some(view.clone());
|
self.tree_view = Some(view.clone());
|
||||||
self.subscription = Some(cx.observe(&view, |_, _, cx| cx.notify()));
|
self.subscription = Some(cx.observe(&view, |_, _, cx| cx.notify()));
|
||||||
return ToolbarItemLocation::PrimaryLeft {
|
return ToolbarItemLocation::PrimaryLeft;
|
||||||
flex: Some((1., false)),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.tree_view = None;
|
self.tree_view = None;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue