mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 08:32:27 +03:00
Draft inlay hint part hover detection
This commit is contained in:
parent
bc7e9088fe
commit
d34491e822
@ -27,7 +27,7 @@ pub use block_map::{
|
||||
BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock, TransformBlock,
|
||||
};
|
||||
|
||||
pub use self::inlay_map::Inlay;
|
||||
pub use self::inlay_map::{Inlay, InlayOffset, InlayPoint};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum FoldStatus {
|
||||
@ -387,12 +387,25 @@ impl DisplaySnapshot {
|
||||
}
|
||||
|
||||
fn display_point_to_point(&self, point: DisplayPoint, bias: Bias) -> Point {
|
||||
self.inlay_snapshot
|
||||
.to_buffer_point(self.display_point_to_inlay_point(point, bias))
|
||||
}
|
||||
|
||||
pub fn display_point_to_inlay_offset(&self, point: DisplayPoint, bias: Bias) -> InlayOffset {
|
||||
self.inlay_snapshot
|
||||
.to_offset(self.display_point_to_inlay_point(point, bias))
|
||||
}
|
||||
|
||||
pub fn inlay_point_to_inlay_offset(&self, point: InlayPoint) -> InlayOffset {
|
||||
self.inlay_snapshot.to_offset(point)
|
||||
}
|
||||
|
||||
fn display_point_to_inlay_point(&self, point: DisplayPoint, bias: Bias) -> InlayPoint {
|
||||
let block_point = point.0;
|
||||
let wrap_point = self.block_snapshot.to_wrap_point(block_point);
|
||||
let tab_point = self.wrap_snapshot.to_tab_point(wrap_point);
|
||||
let fold_point = self.tab_snapshot.to_fold_point(tab_point, bias).0;
|
||||
let inlay_point = fold_point.to_inlay_point(&self.fold_snapshot);
|
||||
self.inlay_snapshot.to_buffer_point(inlay_point)
|
||||
fold_point.to_inlay_point(&self.fold_snapshot)
|
||||
}
|
||||
|
||||
pub fn max_point(&self) -> DisplayPoint {
|
||||
|
@ -4,7 +4,7 @@ use super::{
|
||||
MAX_LINE_LEN,
|
||||
};
|
||||
use crate::{
|
||||
display_map::{BlockStyle, DisplaySnapshot, FoldStatus, TransformBlock},
|
||||
display_map::{BlockStyle, DisplaySnapshot, FoldStatus, InlayPoint, TransformBlock},
|
||||
editor_settings::ShowScrollbar,
|
||||
git::{diff_hunk_to_display, DisplayDiffHunk},
|
||||
hover_popover::{
|
||||
@ -42,7 +42,7 @@ use language::{
|
||||
};
|
||||
use project::{
|
||||
project_settings::{GitGutterSetting, ProjectSettings},
|
||||
ProjectPath,
|
||||
InlayHintLabelPart, ProjectPath,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
@ -455,11 +455,67 @@ impl EditorElement {
|
||||
) -> bool {
|
||||
// This will be handled more correctly once https://github.com/zed-industries/zed/issues/1218 is completed
|
||||
// Don't trigger hover popover if mouse is hovering over context menu
|
||||
let point = position_to_display_point(position, text_bounds, position_map);
|
||||
|
||||
update_go_to_definition_link(editor, point, cmd, shift, cx);
|
||||
hover_at(editor, point, cx);
|
||||
if text_bounds.contains_point(position) {
|
||||
let (nearest_valid_position, unclipped_position) =
|
||||
position_map.point_for_position(text_bounds, position);
|
||||
if nearest_valid_position == unclipped_position {
|
||||
update_go_to_definition_link(editor, Some(nearest_valid_position), cmd, shift, cx);
|
||||
hover_at(editor, Some(nearest_valid_position), cx);
|
||||
return true;
|
||||
} else {
|
||||
let buffer = editor.buffer().read(cx);
|
||||
let snapshot = buffer.snapshot(cx);
|
||||
let previous_valid_position = position_map
|
||||
.snapshot
|
||||
.clip_point(unclipped_position, Bias::Left)
|
||||
.to_point(&position_map.snapshot.display_snapshot);
|
||||
let previous_valid_anchor = snapshot.anchor_at(previous_valid_position, Bias::Left);
|
||||
let next_valid_position = position_map
|
||||
.snapshot
|
||||
.clip_point(unclipped_position, Bias::Right)
|
||||
.to_point(&position_map.snapshot.display_snapshot);
|
||||
let next_valid_anchor = snapshot.anchor_at(next_valid_position, Bias::Right);
|
||||
if let Some(hovered_hint) = editor
|
||||
.visible_inlay_hints(cx)
|
||||
.into_iter()
|
||||
.skip_while(|hint| hint.position.cmp(&previous_valid_anchor, &snapshot).is_lt())
|
||||
.take_while(|hint| hint.position.cmp(&next_valid_anchor, &snapshot).is_le())
|
||||
.max_by_key(|hint| hint.id)
|
||||
{
|
||||
if let Some(cached_hint) = editor
|
||||
.inlay_hint_cache()
|
||||
.hint_by_id(previous_valid_anchor.excerpt_id, hovered_hint.id)
|
||||
{
|
||||
match &cached_hint.label {
|
||||
project::InlayHintLabel::String(regular_label) => {
|
||||
// TODO kb remove + check for tooltip for hover and resolve, if needed
|
||||
eprintln!("regular string: {regular_label}");
|
||||
}
|
||||
project::InlayHintLabel::LabelParts(label_parts) => {
|
||||
// TODO kb how to properly convert it?
|
||||
let unclipped_inlay_position = InlayPoint::new(
|
||||
unclipped_position.row(),
|
||||
unclipped_position.column(),
|
||||
);
|
||||
if let Some(hovered_hint_part) = find_hovered_hint_part(
|
||||
&position_map.snapshot,
|
||||
&label_parts,
|
||||
previous_valid_position,
|
||||
next_valid_position,
|
||||
unclipped_inlay_position,
|
||||
) {
|
||||
// TODO kb remove + check for tooltip and location and resolve, if needed
|
||||
eprintln!("hint_part: {hovered_hint_part:?}");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
update_go_to_definition_link(editor, None, cmd, shift, cx);
|
||||
hover_at(editor, None, cx);
|
||||
true
|
||||
}
|
||||
|
||||
@ -909,7 +965,7 @@ impl EditorElement {
|
||||
&text,
|
||||
cursor_row_layout.font_size(),
|
||||
&[(
|
||||
text.len(),
|
||||
text.chars().count(),
|
||||
RunStyle {
|
||||
font_id,
|
||||
color: style.background,
|
||||
@ -1804,6 +1860,40 @@ impl EditorElement {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_hovered_hint_part<'a>(
|
||||
snapshot: &EditorSnapshot,
|
||||
label_parts: &'a [InlayHintLabelPart],
|
||||
hint_start: Point,
|
||||
hint_end: Point,
|
||||
hovered_position: InlayPoint,
|
||||
) -> Option<&'a InlayHintLabelPart> {
|
||||
let hint_start_offset =
|
||||
snapshot.display_point_to_inlay_offset(hint_start.to_display_point(&snapshot), Bias::Left);
|
||||
let hint_end_offset =
|
||||
snapshot.display_point_to_inlay_offset(hint_end.to_display_point(&snapshot), Bias::Right);
|
||||
dbg!((
|
||||
"~~~~~~~~~",
|
||||
hint_start,
|
||||
hint_start_offset,
|
||||
hint_end,
|
||||
hint_end_offset,
|
||||
hovered_position
|
||||
));
|
||||
let hovered_offset = snapshot.inlay_point_to_inlay_offset(hovered_position);
|
||||
if hovered_offset >= hint_start_offset && hovered_offset <= hint_end_offset {
|
||||
let mut hovered_character = (hovered_offset - hint_start_offset).0;
|
||||
for part in label_parts {
|
||||
let part_len = part.value.chars().count();
|
||||
if hovered_character >= part_len {
|
||||
hovered_character -= part_len;
|
||||
} else {
|
||||
return Some(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
struct HighlightedChunk<'a> {
|
||||
chunk: &'a str,
|
||||
style: Option<HighlightStyle>,
|
||||
@ -2663,6 +2753,7 @@ impl PositionMap {
|
||||
|
||||
let mut target_point = DisplayPoint::new(row, column);
|
||||
let point = self.snapshot.clip_point(target_point, Bias::Left);
|
||||
// TODO kb looks wrong, need to construct inlay point instead? operate offsets?
|
||||
*target_point.column_mut() += (x_overshoot / self.em_advance) as u32;
|
||||
|
||||
(point, target_point)
|
||||
@ -2919,23 +3010,6 @@ impl HighlightedRange {
|
||||
}
|
||||
}
|
||||
|
||||
fn position_to_display_point(
|
||||
position: Vector2F,
|
||||
text_bounds: RectF,
|
||||
position_map: &PositionMap,
|
||||
) -> Option<DisplayPoint> {
|
||||
if text_bounds.contains_point(position) {
|
||||
let (point, target_point) = position_map.point_for_position(text_bounds, position);
|
||||
if point == target_point {
|
||||
Some(point)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn range_to_bounds(
|
||||
range: &Range<DisplayPoint>,
|
||||
content_origin: Vector2F,
|
||||
|
@ -386,6 +386,17 @@ impl InlayHintCache {
|
||||
self.hints.clear();
|
||||
}
|
||||
|
||||
pub fn hint_by_id(&self, excerpt_id: ExcerptId, hint_id: InlayId) -> Option<InlayHint> {
|
||||
self.hints
|
||||
.get(&excerpt_id)?
|
||||
.read()
|
||||
.hints
|
||||
.iter()
|
||||
.find(|&(id, _)| id == &hint_id)
|
||||
.map(|(_, hint)| hint)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn hints(&self) -> Vec<InlayHint> {
|
||||
let mut hints = Vec::new();
|
||||
for excerpt_hints in self.hints.values() {
|
||||
|
Loading…
Reference in New Issue
Block a user