forked from lapce/lapce
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
show call hierarchy and jump to location
- Loading branch information
1 parent
0f1aedd
commit b2a74f4
Showing
9 changed files
with
351 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
use std::{ops::AddAssign, rc::Rc}; | ||
|
||
use floem::{ | ||
event::EventPropagation, | ||
reactive::RwSignal, | ||
style::{AlignItems, CursorStyle}, | ||
views::{ | ||
container, label, scroll, stack, svg, virtual_stack, Decorators, | ||
VirtualDirection, VirtualItemSize, VirtualVector, | ||
}, | ||
View, ViewId, | ||
}; | ||
use lsp_types::{CallHierarchyItem, Range}; | ||
|
||
use super::position::PanelPosition; | ||
use crate::{ | ||
command::InternalCommand, | ||
config::{color::LapceColor, icon::LapceIcons}, | ||
editor::location::EditorLocation, | ||
window_tab::CommonData, | ||
window_tab::WindowTabData, | ||
}; | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct CallHierarchyData { | ||
pub root: RwSignal<Option<RwSignal<CallHierarchyItemData>>>, | ||
pub common: Rc<CommonData>, | ||
pub scroll_to_line: RwSignal<Option<f64>>, | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct CallHierarchyItemData { | ||
pub view_id: ViewId, | ||
pub item: Rc<CallHierarchyItem>, | ||
pub from_range: Range, | ||
pub init: bool, | ||
pub open: RwSignal<bool>, | ||
pub children: RwSignal<Vec<RwSignal<CallHierarchyItemData>>>, | ||
} | ||
|
||
impl CallHierarchyItemData { | ||
pub fn child_count(&self) -> usize { | ||
let mut count = 1; | ||
if self.open.get() { | ||
for child in self.children.get_untracked() { | ||
count += child.with(|x| x.child_count()) | ||
} | ||
} | ||
count | ||
} | ||
} | ||
|
||
fn get_children( | ||
data: RwSignal<CallHierarchyItemData>, | ||
next: &mut usize, | ||
min: usize, | ||
max: usize, | ||
level: usize, | ||
) -> Vec<(usize, usize, RwSignal<CallHierarchyItemData>)> { | ||
let mut children = Vec::new(); | ||
if *next >= min && *next < max { | ||
children.push((*next, level, data)); | ||
} else if *next >= max { | ||
return children; | ||
} | ||
next.add_assign(1); | ||
if data.get_untracked().open.get() { | ||
for child in data.get().children.get_untracked() { | ||
let child_children = get_children(child, next, min, max, level + 1); | ||
children.extend(child_children); | ||
if *next > max { | ||
break; | ||
} | ||
} | ||
} | ||
children | ||
} | ||
|
||
pub struct VirtualList { | ||
root: Option<RwSignal<CallHierarchyItemData>>, | ||
} | ||
|
||
impl VirtualList { | ||
pub fn new(root: Option<RwSignal<CallHierarchyItemData>>) -> Self { | ||
Self { root } | ||
} | ||
} | ||
|
||
impl VirtualVector<(usize, usize, RwSignal<CallHierarchyItemData>)> for VirtualList { | ||
fn total_len(&self) -> usize { | ||
if let Some(root) = &self.root { | ||
root.with(|x| x.child_count()) | ||
} else { | ||
0 | ||
} | ||
} | ||
|
||
fn slice( | ||
&mut self, | ||
range: std::ops::Range<usize>, | ||
) -> impl Iterator<Item = (usize, usize, RwSignal<CallHierarchyItemData>)> { | ||
if let Some(root) = &self.root { | ||
let min = range.start; | ||
let max = range.end; | ||
let children = get_children(*root, &mut 0, min, max, 0); | ||
children.into_iter() | ||
} else { | ||
Vec::new().into_iter() | ||
} | ||
} | ||
} | ||
pub fn show_hierarchy_panel( | ||
window_tab_data: Rc<WindowTabData>, | ||
_position: PanelPosition, | ||
) -> impl View { | ||
let call_hierarchy_data = window_tab_data.call_hierarchy_data.clone(); | ||
let config = call_hierarchy_data.common.config; | ||
let ui_line_height = call_hierarchy_data.common.ui_line_height; | ||
let scroll_to_line = call_hierarchy_data.scroll_to_line; | ||
scroll( | ||
virtual_stack( | ||
VirtualDirection::Vertical, | ||
VirtualItemSize::Fixed(Box::new(move || ui_line_height.get())), | ||
move || VirtualList::new(call_hierarchy_data.root.get()), | ||
move |(_, _, item)| item.get_untracked().view_id, | ||
move |(_, level, rw_data)| { | ||
let data = rw_data.get_untracked(); | ||
let open = data.open; | ||
stack(( | ||
svg(move || { | ||
let config = config.get(); | ||
let svg_str = match open.get() { | ||
true => LapceIcons::ITEM_OPENED, | ||
false => LapceIcons::ITEM_CLOSED, | ||
}; | ||
config.ui_svg(svg_str) | ||
}) | ||
.style(move |s| { | ||
let config = config.get(); | ||
let size = config.ui.icon_size() as f32; | ||
s.size(size, size) | ||
.flex_shrink(0.0) | ||
.margin_left(10.0) | ||
.margin_right(6.0) | ||
.color(config.color(LapceColor::LAPCE_ICON_ACTIVE)) | ||
}).on_click_stop({ | ||
let window_tab_data = window_tab_data.clone(); | ||
move |_x| { | ||
open.update(|x| { | ||
*x = !*x; | ||
}); | ||
if !rw_data.get_untracked().init { | ||
window_tab_data.common.internal_command.send( | ||
InternalCommand::CallHierarchyIncoming { | ||
item: rw_data, | ||
}, | ||
); | ||
} | ||
} | ||
}), | ||
container( | ||
label(move || { | ||
format!( | ||
"{} {} {}", | ||
data.item.name, | ||
data.item.detail.as_deref().unwrap_or(""), data.from_range.start.line | ||
) | ||
}) | ||
.style(move |s| { | ||
s.flex_grow(1.0) | ||
.height(ui_line_height.get()) | ||
.selectable(false) | ||
.align_items(AlignItems::Center) | ||
}), | ||
) | ||
.style(|s| s.flex_grow(1.0).padding(0.0).margin(0.0)), | ||
)) | ||
.style(move |s| { | ||
s.padding_right(5.0) | ||
.padding_left((level * 10) as f32) | ||
.align_items(AlignItems::Center) | ||
.hover(|s| { | ||
s.background( | ||
config | ||
.get() | ||
.color(LapceColor::PANEL_HOVERED_BACKGROUND), | ||
) | ||
.cursor(CursorStyle::Pointer) | ||
}) | ||
}) | ||
.on_double_click({ | ||
let window_tab_data = window_tab_data.clone(); | ||
let data = rw_data; | ||
move |_| { | ||
window_tab_data.common.internal_command.send( | ||
InternalCommand::CallHierarchyIncoming { item: rw_data }, | ||
); | ||
let data = data.get_untracked(); | ||
if let Ok(path) = data.item.uri.to_file_path() { | ||
window_tab_data | ||
.common | ||
.internal_command | ||
.send(InternalCommand::GoToLocation { location: EditorLocation { | ||
path, | ||
position: Some(crate::editor::location::EditorPosition::Position(data.from_range.start)), | ||
scroll_offset: None, | ||
ignore_unconfirmed: false, | ||
same_editor_tab: false, | ||
} }); | ||
} | ||
EventPropagation::Stop | ||
} | ||
}) | ||
}, | ||
) | ||
.style(|s| s.flex_col().align_items(AlignItems::Stretch).width_full()), | ||
) | ||
.style(|s| s.size_full()) | ||
.scroll_to(move || { | ||
if let Some(line) = scroll_to_line.get() { | ||
let line_height = ui_line_height.get(); | ||
Some((0.0, line * line_height).into()) | ||
} else { | ||
None | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod call_hierarchy_view; | ||
pub mod data; | ||
pub mod debug_view; | ||
pub mod global_search_view; | ||
|
Oops, something went wrong.