mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
Open symbol outline when clicking on editor breadcrumbs
This commit is contained in:
parent
35b2aceffb
commit
737e2e1b3c
10 changed files with 102 additions and 29 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -785,6 +785,7 @@ dependencies = [
|
|||
"gpui",
|
||||
"itertools",
|
||||
"language",
|
||||
"outline",
|
||||
"project",
|
||||
"search",
|
||||
"settings",
|
||||
|
|
|
@ -18,6 +18,7 @@ search = { path = "../search" }
|
|||
settings = { path = "../settings" }
|
||||
theme = { path = "../theme" }
|
||||
workspace = { path = "../workspace" }
|
||||
outline = { path = "../outline" }
|
||||
itertools = "0.10"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use gpui::{
|
||||
elements::*, AppContext, Entity, RenderContext, Subscription, View, ViewContext, ViewHandle,
|
||||
elements::*, AppContext, Entity, MouseButton, RenderContext, Subscription, View, ViewContext,
|
||||
ViewHandle,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use search::ProjectSearchView;
|
||||
|
@ -14,6 +15,7 @@ pub enum Event {
|
|||
}
|
||||
|
||||
pub struct Breadcrumbs {
|
||||
pane_focused: bool,
|
||||
active_item: Option<Box<dyn ItemHandle>>,
|
||||
project_search: Option<ViewHandle<ProjectSearchView>>,
|
||||
subscription: Option<Subscription>,
|
||||
|
@ -22,6 +24,7 @@ pub struct Breadcrumbs {
|
|||
impl Breadcrumbs {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pane_focused: false,
|
||||
active_item: Default::default(),
|
||||
subscription: Default::default(),
|
||||
project_search: Default::default(),
|
||||
|
@ -39,24 +42,53 @@ impl View for Breadcrumbs {
|
|||
}
|
||||
|
||||
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();
|
||||
if let Some(breadcrumbs) = self
|
||||
.active_item
|
||||
.as_ref()
|
||||
.and_then(|item| item.breadcrumbs(&theme, cx))
|
||||
{
|
||||
Flex::row()
|
||||
.with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || {
|
||||
Label::new(" 〉 ", theme.breadcrumbs.text.clone()).boxed()
|
||||
}))
|
||||
.contained()
|
||||
.with_style(theme.breadcrumbs.container)
|
||||
let style = &theme.workspace.breadcrumbs;
|
||||
|
||||
let breadcrumbs = match active_item.breadcrumbs(&theme, cx) {
|
||||
Some(breadcrumbs) => breadcrumbs,
|
||||
None => return Empty::new().boxed(),
|
||||
};
|
||||
|
||||
let crumbs = Flex::row()
|
||||
.with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || {
|
||||
Label::new(" 〉 ", style.default.text.clone()).boxed()
|
||||
}))
|
||||
.constrained()
|
||||
.with_height(theme.workspace.breadcrumb_height)
|
||||
.contained();
|
||||
|
||||
if not_editor || !self.pane_focused {
|
||||
return crumbs
|
||||
.with_style(style.default.container)
|
||||
.aligned()
|
||||
.left()
|
||||
.boxed()
|
||||
} else {
|
||||
Empty::new().boxed()
|
||||
.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
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
.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| {
|
||||
Text::new(symbol.text, theme.breadcrumbs.text.clone())
|
||||
.with_highlights(symbol.highlight_ranges)
|
||||
.boxed()
|
||||
Text::new(
|
||||
symbol.text,
|
||||
theme.workspace.breadcrumbs.default.text.clone(),
|
||||
)
|
||||
.with_highlights(symbol.highlight_ranges)
|
||||
.boxed()
|
||||
}));
|
||||
Some(breadcrumbs)
|
||||
}
|
||||
|
|
|
@ -612,7 +612,7 @@ impl Item for TerminalView {
|
|||
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
|
||||
Some(vec![Text::new(
|
||||
self.terminal().read(cx).breadcrumb_text.clone(),
|
||||
theme.breadcrumbs.text.clone(),
|
||||
theme.workspace.breadcrumbs.default.text.clone(),
|
||||
)
|
||||
.boxed()])
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ pub struct Theme {
|
|||
pub editor: Editor,
|
||||
pub search: Search,
|
||||
pub project_diagnostics: ProjectDiagnostics,
|
||||
pub breadcrumbs: ContainedText,
|
||||
pub shared_screen: ContainerStyle,
|
||||
pub contact_notification: ContactNotification,
|
||||
pub update_notification: UpdateNotification,
|
||||
|
@ -62,6 +61,8 @@ pub struct Workspace {
|
|||
pub sidebar: Sidebar,
|
||||
pub status_bar: StatusBar,
|
||||
pub toolbar: Toolbar,
|
||||
pub breadcrumb_height: f32,
|
||||
pub breadcrumbs: Interactive<ContainedText>,
|
||||
pub disconnected_overlay: ContainedText,
|
||||
pub modal: ContainerStyle,
|
||||
pub notification: ContainerStyle,
|
||||
|
|
|
@ -1603,6 +1603,10 @@ impl View for Pane {
|
|||
}
|
||||
|
||||
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 cx.is_self_focused() {
|
||||
// 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 {
|
||||
let mut keymap = Self::default_keymap_context();
|
||||
if self.docked.is_some() {
|
||||
|
|
|
@ -20,6 +20,8 @@ pub trait ToolbarItemView: View {
|
|||
) -> ToolbarItemLocation {
|
||||
current_location
|
||||
}
|
||||
|
||||
fn pane_focus_update(&mut self, _pane_focused: bool, _cx: &mut MutableAppContext) {}
|
||||
}
|
||||
|
||||
trait ToolbarItemViewHandle {
|
||||
|
@ -30,6 +32,7 @@ trait ToolbarItemViewHandle {
|
|||
active_pane_item: Option<&dyn ItemHandle>,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> ToolbarItemLocation;
|
||||
fn pane_focus_update(&mut self, pane_focused: bool, cx: &mut MutableAppContext);
|
||||
}
|
||||
|
||||
#[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>> {
|
||||
self.items
|
||||
.iter()
|
||||
|
@ -289,6 +298,10 @@ impl<T: ToolbarItemView> ToolbarItemViewHandle for ViewHandle<T> {
|
|||
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 {
|
||||
|
|
|
@ -44,12 +44,6 @@ export default function app(colorScheme: ColorScheme): Object {
|
|||
contactList: contactList(colorScheme),
|
||||
search: search(colorScheme),
|
||||
sharedScreen: sharedScreen(colorScheme),
|
||||
breadcrumbs: {
|
||||
...text(colorScheme.highest, "sans", "variant"),
|
||||
padding: {
|
||||
left: 6,
|
||||
},
|
||||
},
|
||||
updateNotification: updateNotification(colorScheme),
|
||||
simpleMessageNotification: simpleMessageNotification(colorScheme),
|
||||
tooltip: tooltip(colorScheme),
|
||||
|
|
|
@ -276,9 +276,22 @@ export default function workspace(colorScheme: ColorScheme) {
|
|||
},
|
||||
padding: { left: 8, right: 8, top: 4, bottom: 4 },
|
||||
},
|
||||
breadcrumbHeight: 24,
|
||||
breadcrumbs: {
|
||||
...text(layer, "mono", "variant"),
|
||||
padding: { left: 6 },
|
||||
...text(colorScheme.highest, "sans", "variant"),
|
||||
cornerRadius: 6,
|
||||
padding: {
|
||||
left: 6,
|
||||
right: 6,
|
||||
},
|
||||
hover: {
|
||||
color: foreground(colorScheme.highest, "on", "hovered"),
|
||||
background: background(
|
||||
colorScheme.highest,
|
||||
"on",
|
||||
"hovered"
|
||||
),
|
||||
},
|
||||
},
|
||||
disconnectedOverlay: {
|
||||
...text(layer, "sans"),
|
||||
|
|
Loading…
Reference in a new issue