mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-12 05:27:07 +00:00
127 lines
3.8 KiB
Rust
127 lines
3.8 KiB
Rust
use editor::Editor;
|
||
use gpui::{
|
||
Div, Element, EventEmitter, IntoElement, ParentElement, Render, StyledText, Subscription,
|
||
ViewContext,
|
||
};
|
||
use itertools::Itertools;
|
||
use theme::ActiveTheme;
|
||
use ui::{prelude::*, ButtonLike, ButtonStyle, Label, Tooltip};
|
||
use workspace::{
|
||
item::{ItemEvent, ItemHandle},
|
||
ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView,
|
||
};
|
||
|
||
pub enum Event {
|
||
UpdateLocation,
|
||
}
|
||
|
||
pub struct Breadcrumbs {
|
||
pane_focused: bool,
|
||
active_item: Option<Box<dyn ItemHandle>>,
|
||
subscription: Option<Subscription>,
|
||
}
|
||
|
||
impl Breadcrumbs {
|
||
pub fn new() -> Self {
|
||
Self {
|
||
pane_focused: false,
|
||
active_item: Default::default(),
|
||
subscription: Default::default(),
|
||
}
|
||
}
|
||
}
|
||
|
||
impl EventEmitter<Event> for Breadcrumbs {}
|
||
impl EventEmitter<ToolbarItemEvent> for Breadcrumbs {}
|
||
|
||
impl Render for Breadcrumbs {
|
||
type Element = Div;
|
||
|
||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||
let element = h_stack().text_ui();
|
||
|
||
let Some(active_item) = &self
|
||
.active_item
|
||
.as_ref()
|
||
.filter(|item| item.downcast::<editor::Editor>().is_some())
|
||
else {
|
||
return element;
|
||
};
|
||
|
||
let Some(segments) = active_item.breadcrumbs(cx.theme(), cx) else {
|
||
return element;
|
||
};
|
||
|
||
let highlighted_segments = segments.into_iter().map(|segment| {
|
||
StyledText::new(segment.text)
|
||
.with_highlights(&cx.text_style(), segment.highlights.unwrap_or_default())
|
||
.into_any()
|
||
});
|
||
let breadcrumbs = Itertools::intersperse_with(highlighted_segments, || {
|
||
Label::new("›").into_any_element()
|
||
});
|
||
|
||
let editor = active_item
|
||
.downcast::<Editor>()
|
||
.map(|editor| editor.downgrade());
|
||
|
||
element.child(
|
||
ButtonLike::new("toggle outline view")
|
||
.style(ButtonStyle::Subtle)
|
||
.child(h_stack().gap_1().children(breadcrumbs))
|
||
.on_click(move |_, cx| {
|
||
if let Some(editor) = editor.as_ref().and_then(|editor| editor.upgrade()) {
|
||
outline::toggle(editor, &outline::Toggle, cx)
|
||
}
|
||
})
|
||
.tooltip(|cx| Tooltip::for_action("Show symbol outline", &outline::Toggle, cx)),
|
||
)
|
||
}
|
||
}
|
||
|
||
impl ToolbarItemView for Breadcrumbs {
|
||
fn set_active_pane_item(
|
||
&mut self,
|
||
active_pane_item: Option<&dyn ItemHandle>,
|
||
cx: &mut ViewContext<Self>,
|
||
) -> ToolbarItemLocation {
|
||
cx.notify();
|
||
self.active_item = None;
|
||
if let Some(item) = active_pane_item {
|
||
let this = cx.view().downgrade();
|
||
self.subscription = Some(item.subscribe_to_item_events(
|
||
cx,
|
||
Box::new(move |event, cx| {
|
||
if let ItemEvent::UpdateBreadcrumbs = event {
|
||
this.update(cx, |_, cx| {
|
||
cx.emit(Event::UpdateLocation);
|
||
cx.notify();
|
||
})
|
||
.ok();
|
||
}
|
||
}),
|
||
));
|
||
self.active_item = Some(item.boxed_clone());
|
||
item.breadcrumb_location(cx)
|
||
} else {
|
||
ToolbarItemLocation::Hidden
|
||
}
|
||
}
|
||
|
||
// fn location_for_event(
|
||
// &self,
|
||
// _: &Event,
|
||
// current_location: ToolbarItemLocation,
|
||
// cx: &AppContext,
|
||
// ) -> ToolbarItemLocation {
|
||
// if let Some(active_item) = self.active_item.as_ref() {
|
||
// active_item.breadcrumb_location(cx)
|
||
// } else {
|
||
// current_location
|
||
// }
|
||
// }
|
||
|
||
fn pane_focus_update(&mut self, pane_focused: bool, _: &mut ViewContext<Self>) {
|
||
self.pane_focused = pane_focused;
|
||
}
|
||
}
|