mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 02:17:35 +03:00
Open symbol outline when clicking on editor breadcrumbs
This commit is contained in:
parent
35b2aceffb
commit
737e2e1b3c
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -785,6 +785,7 @@ dependencies = [
|
|||||||
"gpui",
|
"gpui",
|
||||||
"itertools",
|
"itertools",
|
||||||
"language",
|
"language",
|
||||||
|
"outline",
|
||||||
"project",
|
"project",
|
||||||
"search",
|
"search",
|
||||||
"settings",
|
"settings",
|
||||||
|
@ -18,6 +18,7 @@ search = { path = "../search" }
|
|||||||
settings = { path = "../settings" }
|
settings = { path = "../settings" }
|
||||||
theme = { path = "../theme" }
|
theme = { path = "../theme" }
|
||||||
workspace = { path = "../workspace" }
|
workspace = { path = "../workspace" }
|
||||||
|
outline = { path = "../outline" }
|
||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use gpui::{
|
use gpui::{
|
||||||
elements::*, AppContext, Entity, RenderContext, Subscription, View, ViewContext, ViewHandle,
|
elements::*, AppContext, Entity, MouseButton, RenderContext, Subscription, View, ViewContext,
|
||||||
|
ViewHandle,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use search::ProjectSearchView;
|
use search::ProjectSearchView;
|
||||||
@ -14,6 +15,7 @@ pub enum Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Breadcrumbs {
|
pub struct Breadcrumbs {
|
||||||
|
pane_focused: bool,
|
||||||
active_item: Option<Box<dyn ItemHandle>>,
|
active_item: Option<Box<dyn ItemHandle>>,
|
||||||
project_search: Option<ViewHandle<ProjectSearchView>>,
|
project_search: Option<ViewHandle<ProjectSearchView>>,
|
||||||
subscription: Option<Subscription>,
|
subscription: Option<Subscription>,
|
||||||
@ -22,6 +24,7 @@ pub struct Breadcrumbs {
|
|||||||
impl Breadcrumbs {
|
impl Breadcrumbs {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
pane_focused: false,
|
||||||
active_item: Default::default(),
|
active_item: Default::default(),
|
||||||
subscription: Default::default(),
|
subscription: Default::default(),
|
||||||
project_search: Default::default(),
|
project_search: Default::default(),
|
||||||
@ -39,24 +42,53 @@ impl View for Breadcrumbs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||||
|
let active_item = match &self.active_item {
|
||||||
|
Some(active_item) => active_item,
|
||||||
|
None => return Empty::new().boxed(),
|
||||||
|
};
|
||||||
|
let not_editor = active_item.downcast::<editor::Editor>().is_none();
|
||||||
|
|
||||||
let theme = cx.global::<Settings>().theme.clone();
|
let theme = cx.global::<Settings>().theme.clone();
|
||||||
if let Some(breadcrumbs) = self
|
let style = &theme.workspace.breadcrumbs;
|
||||||
.active_item
|
|
||||||
.as_ref()
|
let breadcrumbs = match active_item.breadcrumbs(&theme, cx) {
|
||||||
.and_then(|item| item.breadcrumbs(&theme, cx))
|
Some(breadcrumbs) => breadcrumbs,
|
||||||
{
|
None => return Empty::new().boxed(),
|
||||||
Flex::row()
|
};
|
||||||
.with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || {
|
|
||||||
Label::new(" 〉 ", theme.breadcrumbs.text.clone()).boxed()
|
let crumbs = Flex::row()
|
||||||
}))
|
.with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || {
|
||||||
.contained()
|
Label::new(" 〉 ", style.default.text.clone()).boxed()
|
||||||
.with_style(theme.breadcrumbs.container)
|
}))
|
||||||
|
.constrained()
|
||||||
|
.with_height(theme.workspace.breadcrumb_height)
|
||||||
|
.contained();
|
||||||
|
|
||||||
|
if not_editor || !self.pane_focused {
|
||||||
|
return crumbs
|
||||||
|
.with_style(style.default.container)
|
||||||
.aligned()
|
.aligned()
|
||||||
.left()
|
.left()
|
||||||
.boxed()
|
.boxed();
|
||||||
} else {
|
|
||||||
Empty::new().boxed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MouseEventHandler::<Breadcrumbs>::new(0, cx, |state, _| {
|
||||||
|
let style = style.style_for(state, false);
|
||||||
|
crumbs.with_style(style.container).boxed()
|
||||||
|
})
|
||||||
|
.on_click(MouseButton::Left, |_, cx| {
|
||||||
|
cx.dispatch_action(outline::Toggle);
|
||||||
|
})
|
||||||
|
.with_tooltip::<Breadcrumbs, _>(
|
||||||
|
0,
|
||||||
|
"Show symbol outline".to_owned(),
|
||||||
|
Some(Box::new(outline::Toggle)),
|
||||||
|
theme.tooltip.clone(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.aligned()
|
||||||
|
.left()
|
||||||
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,4 +135,8 @@ impl ToolbarItemView for Breadcrumbs {
|
|||||||
current_location
|
current_location
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pane_focus_update(&mut self, pane_focused: bool, _: &mut gpui::MutableAppContext) {
|
||||||
|
self.pane_focused = pane_focused;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -747,11 +747,15 @@ impl Item for Editor {
|
|||||||
.map(|path| path.to_string_lossy().to_string())
|
.map(|path| path.to_string_lossy().to_string())
|
||||||
.unwrap_or_else(|| "untitled".to_string());
|
.unwrap_or_else(|| "untitled".to_string());
|
||||||
|
|
||||||
let mut breadcrumbs = vec![Label::new(filename, theme.breadcrumbs.text.clone()).boxed()];
|
let filename_label = Label::new(filename, theme.workspace.breadcrumbs.default.text.clone());
|
||||||
|
let mut breadcrumbs = vec![filename_label.boxed()];
|
||||||
breadcrumbs.extend(symbols.into_iter().map(|symbol| {
|
breadcrumbs.extend(symbols.into_iter().map(|symbol| {
|
||||||
Text::new(symbol.text, theme.breadcrumbs.text.clone())
|
Text::new(
|
||||||
.with_highlights(symbol.highlight_ranges)
|
symbol.text,
|
||||||
.boxed()
|
theme.workspace.breadcrumbs.default.text.clone(),
|
||||||
|
)
|
||||||
|
.with_highlights(symbol.highlight_ranges)
|
||||||
|
.boxed()
|
||||||
}));
|
}));
|
||||||
Some(breadcrumbs)
|
Some(breadcrumbs)
|
||||||
}
|
}
|
||||||
|
@ -612,7 +612,7 @@ impl Item for TerminalView {
|
|||||||
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
|
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
|
||||||
Some(vec![Text::new(
|
Some(vec![Text::new(
|
||||||
self.terminal().read(cx).breadcrumb_text.clone(),
|
self.terminal().read(cx).breadcrumb_text.clone(),
|
||||||
theme.breadcrumbs.text.clone(),
|
theme.workspace.breadcrumbs.default.text.clone(),
|
||||||
)
|
)
|
||||||
.boxed()])
|
.boxed()])
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ pub struct Theme {
|
|||||||
pub editor: Editor,
|
pub editor: Editor,
|
||||||
pub search: Search,
|
pub search: Search,
|
||||||
pub project_diagnostics: ProjectDiagnostics,
|
pub project_diagnostics: ProjectDiagnostics,
|
||||||
pub breadcrumbs: ContainedText,
|
|
||||||
pub shared_screen: ContainerStyle,
|
pub shared_screen: ContainerStyle,
|
||||||
pub contact_notification: ContactNotification,
|
pub contact_notification: ContactNotification,
|
||||||
pub update_notification: UpdateNotification,
|
pub update_notification: UpdateNotification,
|
||||||
@ -62,6 +61,8 @@ pub struct Workspace {
|
|||||||
pub sidebar: Sidebar,
|
pub sidebar: Sidebar,
|
||||||
pub status_bar: StatusBar,
|
pub status_bar: StatusBar,
|
||||||
pub toolbar: Toolbar,
|
pub toolbar: Toolbar,
|
||||||
|
pub breadcrumb_height: f32,
|
||||||
|
pub breadcrumbs: Interactive<ContainedText>,
|
||||||
pub disconnected_overlay: ContainedText,
|
pub disconnected_overlay: ContainedText,
|
||||||
pub modal: ContainerStyle,
|
pub modal: ContainerStyle,
|
||||||
pub notification: ContainerStyle,
|
pub notification: ContainerStyle,
|
||||||
|
@ -1603,6 +1603,10 @@ impl View for Pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
self.toolbar.update(cx, |toolbar, cx| {
|
||||||
|
toolbar.pane_focus_update(true, cx);
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(active_item) = self.active_item() {
|
if let Some(active_item) = self.active_item() {
|
||||||
if cx.is_self_focused() {
|
if cx.is_self_focused() {
|
||||||
// Pane was focused directly. We need to either focus a view inside the active item,
|
// Pane was focused directly. We need to either focus a view inside the active item,
|
||||||
@ -1626,6 +1630,12 @@ impl View for Pane {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
self.toolbar.update(cx, |toolbar, cx| {
|
||||||
|
toolbar.pane_focus_update(false, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
|
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
|
||||||
let mut keymap = Self::default_keymap_context();
|
let mut keymap = Self::default_keymap_context();
|
||||||
if self.docked.is_some() {
|
if self.docked.is_some() {
|
||||||
|
@ -20,6 +20,8 @@ pub trait ToolbarItemView: View {
|
|||||||
) -> ToolbarItemLocation {
|
) -> ToolbarItemLocation {
|
||||||
current_location
|
current_location
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pane_focus_update(&mut self, _pane_focused: bool, _cx: &mut MutableAppContext) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ToolbarItemViewHandle {
|
trait ToolbarItemViewHandle {
|
||||||
@ -30,6 +32,7 @@ trait ToolbarItemViewHandle {
|
|||||||
active_pane_item: Option<&dyn ItemHandle>,
|
active_pane_item: Option<&dyn ItemHandle>,
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
) -> ToolbarItemLocation;
|
) -> ToolbarItemLocation;
|
||||||
|
fn pane_focus_update(&mut self, pane_focused: bool, cx: &mut MutableAppContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
@ -260,6 +263,12 @@ impl Toolbar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pane_focus_update(&mut self, pane_focused: bool, cx: &mut MutableAppContext) {
|
||||||
|
for (toolbar_item, _) in self.items.iter_mut() {
|
||||||
|
toolbar_item.pane_focus_update(pane_focused, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn item_of_type<T: ToolbarItemView>(&self) -> Option<ViewHandle<T>> {
|
pub fn item_of_type<T: ToolbarItemView>(&self) -> Option<ViewHandle<T>> {
|
||||||
self.items
|
self.items
|
||||||
.iter()
|
.iter()
|
||||||
@ -289,6 +298,10 @@ impl<T: ToolbarItemView> ToolbarItemViewHandle for ViewHandle<T> {
|
|||||||
this.set_active_pane_item(active_pane_item, cx)
|
this.set_active_pane_item(active_pane_item, cx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pane_focus_update(&mut self, pane_focused: bool, cx: &mut MutableAppContext) {
|
||||||
|
self.update(cx, |this, cx| this.pane_focus_update(pane_focused, cx));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&dyn ToolbarItemViewHandle> for AnyViewHandle {
|
impl From<&dyn ToolbarItemViewHandle> for AnyViewHandle {
|
||||||
|
@ -44,12 +44,6 @@ export default function app(colorScheme: ColorScheme): Object {
|
|||||||
contactList: contactList(colorScheme),
|
contactList: contactList(colorScheme),
|
||||||
search: search(colorScheme),
|
search: search(colorScheme),
|
||||||
sharedScreen: sharedScreen(colorScheme),
|
sharedScreen: sharedScreen(colorScheme),
|
||||||
breadcrumbs: {
|
|
||||||
...text(colorScheme.highest, "sans", "variant"),
|
|
||||||
padding: {
|
|
||||||
left: 6,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
updateNotification: updateNotification(colorScheme),
|
updateNotification: updateNotification(colorScheme),
|
||||||
simpleMessageNotification: simpleMessageNotification(colorScheme),
|
simpleMessageNotification: simpleMessageNotification(colorScheme),
|
||||||
tooltip: tooltip(colorScheme),
|
tooltip: tooltip(colorScheme),
|
||||||
|
@ -276,9 +276,22 @@ export default function workspace(colorScheme: ColorScheme) {
|
|||||||
},
|
},
|
||||||
padding: { left: 8, right: 8, top: 4, bottom: 4 },
|
padding: { left: 8, right: 8, top: 4, bottom: 4 },
|
||||||
},
|
},
|
||||||
|
breadcrumbHeight: 24,
|
||||||
breadcrumbs: {
|
breadcrumbs: {
|
||||||
...text(layer, "mono", "variant"),
|
...text(colorScheme.highest, "sans", "variant"),
|
||||||
padding: { left: 6 },
|
cornerRadius: 6,
|
||||||
|
padding: {
|
||||||
|
left: 6,
|
||||||
|
right: 6,
|
||||||
|
},
|
||||||
|
hover: {
|
||||||
|
color: foreground(colorScheme.highest, "on", "hovered"),
|
||||||
|
background: background(
|
||||||
|
colorScheme.highest,
|
||||||
|
"on",
|
||||||
|
"hovered"
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
disconnectedOverlay: {
|
disconnectedOverlay: {
|
||||||
...text(layer, "sans"),
|
...text(layer, "sans"),
|
||||||
|
Loading…
Reference in New Issue
Block a user