diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 569b6581ce1b2f0d3b3145d3773a548f2352a05e..0a590fe2fdb8ec8d017461fe36dfd490c714ce49 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2,6 +2,10 @@ use crate::{ display_map::{BlockStyle, DisplaySnapshot, FoldStatus, HighlightedChunk, ToDisplayPoint}, editor_settings::ShowScrollbar, git::{diff_hunk_to_display, DisplayDiffHunk}, + hover_popover::hover_at, + link_go_to_definition::{ + update_go_to_definition_link, update_inlay_link_and_hover_points, GoToDefinitionTrigger, + }, scroll::scroll_amount::ScrollAmount, CursorShape, DisplayPoint, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, HalfPageDown, HalfPageUp, LineDown, LineUp, MoveDown, PageDown, PageUp, Point, Selection, @@ -12,9 +16,9 @@ use collections::{BTreeMap, HashMap}; use gpui::{ black, hsla, point, px, relative, size, transparent_black, Action, AnyElement, BorrowAppContext, BorrowWindow, Bounds, ContentMask, Corners, DispatchContext, DispatchPhase, - Edges, Element, ElementId, Entity, Hsla, KeyDownEvent, KeyListener, KeyMatch, Line, Pixels, - ScrollWheelEvent, ShapedGlyph, Size, StatefulInteraction, Style, TextRun, TextStyle, - TextSystem, ViewContext, WindowContext, + Edges, Element, ElementId, Entity, Hsla, KeyDownEvent, KeyListener, KeyMatch, Line, Modifiers, + MouseMoveEvent, Pixels, ScrollWheelEvent, ShapedGlyph, Size, StatefulInteraction, Style, + TextRun, TextStyle, TextSystem, ViewContext, WindowContext, }; use itertools::Itertools; use language::language_settings::ShowWhitespaceSetting; @@ -423,50 +427,50 @@ impl EditorElement { // } // } - // fn mouse_moved( - // editor: &mut Editor, - // MouseMovedEvent { - // modifiers: Modifiers { shift, cmd, .. }, - // position, - // .. - // }: MouseMovedEvent, - // position_map: &PositionMap, - // text_bounds: Bounds, - // cx: &mut ViewContext, - // ) -> 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 - // if text_bounds.contains_point(position) { - // let point_for_position = position_map.point_for_position(text_bounds, position); - // match point_for_position.as_valid() { - // Some(point) => { - // update_go_to_definition_link( - // editor, - // Some(GoToDefinitionTrigger::Text(point)), - // cmd, - // shift, - // cx, - // ); - // hover_at(editor, Some(point), cx); - // } - // None => { - // update_inlay_link_and_hover_points( - // &position_map.snapshot, - // point_for_position, - // editor, - // cmd, - // shift, - // cx, - // ); - // } - // } - // } else { - // update_go_to_definition_link(editor, None, cmd, shift, cx); - // hover_at(editor, None, cx); - // } + fn mouse_moved( + editor: &mut Editor, + MouseMoveEvent { + modifiers: Modifiers { shift, command, .. }, + position, + .. + }: &MouseMoveEvent, + position_map: &PositionMap, + text_bounds: Bounds, + cx: &mut ViewContext, + ) -> 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 + if text_bounds.contains_point(position) { + let point_for_position = position_map.point_for_position(text_bounds, position.clone()); + match point_for_position.as_valid() { + Some(point) => { + update_go_to_definition_link( + editor, + Some(GoToDefinitionTrigger::Text(point)), + *command, + *shift, + cx, + ); + hover_at(editor, Some(point), cx); + } + None => { + update_inlay_link_and_hover_points( + &position_map.snapshot, + point_for_position, + editor, + *command, + *shift, + cx, + ); + } + } + } else { + update_go_to_definition_link(editor, None, *command, *shift, cx); + hover_at(editor, None, cx); + } - // true - // } + true + } fn scroll( editor: &mut Editor, @@ -2772,6 +2776,18 @@ impl Element for EditorElement { } } }); + cx.on_mouse_event({ + let position_map = layout.position_map.clone(); + move |editor, event: &MouseMoveEvent, phase, cx| { + if phase != DispatchPhase::Bubble { + return; + } + + if Self::mouse_moved(editor, event, &position_map, bounds, cx) { + cx.stop_propagation() + } + } + }); if editor.focus_handle.is_focused(cx) { cx.handle_text_input(); diff --git a/crates/editor2/src/link_go_to_definition.rs b/crates/editor2/src/link_go_to_definition.rs index 9db4061e5096ac3f4b3a221a3bc22f45114b26d2..d36762f3955e126200d7025002d543e9744bce79 100644 --- a/crates/editor2/src/link_go_to_definition.rs +++ b/crates/editor2/src/link_go_to_definition.rs @@ -171,173 +171,170 @@ pub fn update_inlay_link_and_hover_points( shift_held: bool, cx: &mut ViewContext<'_, Editor>, ) { - todo!("old implementation below") -} -// ) { -// let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 { -// Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left)) -// } else { -// None -// }; -// let mut go_to_definition_updated = false; -// let mut hover_updated = false; -// if let Some(hovered_offset) = hovered_offset { -// let buffer_snapshot = editor.buffer().read(cx).snapshot(cx); -// let previous_valid_anchor = buffer_snapshot.anchor_at( -// point_for_position.previous_valid.to_point(snapshot), -// Bias::Left, -// ); -// let next_valid_anchor = buffer_snapshot.anchor_at( -// point_for_position.next_valid.to_point(snapshot), -// Bias::Right, -// ); -// if let Some(hovered_hint) = editor -// .visible_inlay_hints(cx) -// .into_iter() -// .skip_while(|hint| { -// hint.position -// .cmp(&previous_valid_anchor, &buffer_snapshot) -// .is_lt() -// }) -// .take_while(|hint| { -// hint.position -// .cmp(&next_valid_anchor, &buffer_snapshot) -// .is_le() -// }) -// .max_by_key(|hint| hint.id) -// { -// let inlay_hint_cache = editor.inlay_hint_cache(); -// let excerpt_id = previous_valid_anchor.excerpt_id; -// if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) { -// match cached_hint.resolve_state { -// ResolveState::CanResolve(_, _) => { -// if let Some(buffer_id) = previous_valid_anchor.buffer_id { -// inlay_hint_cache.spawn_hint_resolve( -// buffer_id, -// excerpt_id, -// hovered_hint.id, -// cx, -// ); -// } -// } -// ResolveState::Resolved => { -// let mut extra_shift_left = 0; -// let mut extra_shift_right = 0; -// if cached_hint.padding_left { -// extra_shift_left += 1; -// extra_shift_right += 1; -// } -// if cached_hint.padding_right { -// extra_shift_right += 1; -// } -// match cached_hint.label { -// project::InlayHintLabel::String(_) => { -// if let Some(tooltip) = cached_hint.tooltip { -// hover_popover::hover_at_inlay( -// editor, -// InlayHover { -// excerpt: excerpt_id, -// tooltip: match tooltip { -// InlayHintTooltip::String(text) => HoverBlock { -// text, -// kind: HoverBlockKind::PlainText, -// }, -// InlayHintTooltip::MarkupContent(content) => { -// HoverBlock { -// text: content.value, -// kind: content.kind, -// } -// } -// }, -// range: InlayHighlight { -// inlay: hovered_hint.id, -// inlay_position: hovered_hint.position, -// range: extra_shift_left -// ..hovered_hint.text.len() + extra_shift_right, -// }, -// }, -// cx, -// ); -// hover_updated = true; -// } -// } -// project::InlayHintLabel::LabelParts(label_parts) => { -// let hint_start = -// snapshot.anchor_to_inlay_offset(hovered_hint.position); -// if let Some((hovered_hint_part, part_range)) = -// hover_popover::find_hovered_hint_part( -// label_parts, -// hint_start, -// hovered_offset, -// ) -// { -// let highlight_start = -// (part_range.start - hint_start).0 + extra_shift_left; -// let highlight_end = -// (part_range.end - hint_start).0 + extra_shift_right; -// let highlight = InlayHighlight { -// inlay: hovered_hint.id, -// inlay_position: hovered_hint.position, -// range: highlight_start..highlight_end, -// }; -// if let Some(tooltip) = hovered_hint_part.tooltip { -// hover_popover::hover_at_inlay( -// editor, -// InlayHover { -// excerpt: excerpt_id, -// tooltip: match tooltip { -// InlayHintLabelPartTooltip::String(text) => { -// HoverBlock { -// text, -// kind: HoverBlockKind::PlainText, -// } -// } -// InlayHintLabelPartTooltip::MarkupContent( -// content, -// ) => HoverBlock { -// text: content.value, -// kind: content.kind, -// }, -// }, -// range: highlight.clone(), -// }, -// cx, -// ); -// hover_updated = true; -// } -// if let Some((language_server_id, location)) = -// hovered_hint_part.location -// { -// go_to_definition_updated = true; -// update_go_to_definition_link( -// editor, -// Some(GoToDefinitionTrigger::InlayHint( -// highlight, -// location, -// language_server_id, -// )), -// cmd_held, -// shift_held, -// cx, -// ); -// } -// } -// } -// }; -// } -// ResolveState::Resolving => {} -// } -// } -// } -// } + let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 { + Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left)) + } else { + None + }; + let mut go_to_definition_updated = false; + let mut hover_updated = false; + if let Some(hovered_offset) = hovered_offset { + let buffer_snapshot = editor.buffer().read(cx).snapshot(cx); + let previous_valid_anchor = buffer_snapshot.anchor_at( + point_for_position.previous_valid.to_point(snapshot), + Bias::Left, + ); + let next_valid_anchor = buffer_snapshot.anchor_at( + point_for_position.next_valid.to_point(snapshot), + Bias::Right, + ); + if let Some(hovered_hint) = editor + .visible_inlay_hints(cx) + .into_iter() + .skip_while(|hint| { + hint.position + .cmp(&previous_valid_anchor, &buffer_snapshot) + .is_lt() + }) + .take_while(|hint| { + hint.position + .cmp(&next_valid_anchor, &buffer_snapshot) + .is_le() + }) + .max_by_key(|hint| hint.id) + { + let inlay_hint_cache = editor.inlay_hint_cache(); + let excerpt_id = previous_valid_anchor.excerpt_id; + if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) { + match cached_hint.resolve_state { + ResolveState::CanResolve(_, _) => { + if let Some(buffer_id) = previous_valid_anchor.buffer_id { + inlay_hint_cache.spawn_hint_resolve( + buffer_id, + excerpt_id, + hovered_hint.id, + cx, + ); + } + } + ResolveState::Resolved => { + let mut extra_shift_left = 0; + let mut extra_shift_right = 0; + if cached_hint.padding_left { + extra_shift_left += 1; + extra_shift_right += 1; + } + if cached_hint.padding_right { + extra_shift_right += 1; + } + match cached_hint.label { + project::InlayHintLabel::String(_) => { + if let Some(tooltip) = cached_hint.tooltip { + hover_popover::hover_at_inlay( + editor, + InlayHover { + excerpt: excerpt_id, + tooltip: match tooltip { + InlayHintTooltip::String(text) => HoverBlock { + text, + kind: HoverBlockKind::PlainText, + }, + InlayHintTooltip::MarkupContent(content) => { + HoverBlock { + text: content.value, + kind: content.kind, + } + } + }, + range: InlayHighlight { + inlay: hovered_hint.id, + inlay_position: hovered_hint.position, + range: extra_shift_left + ..hovered_hint.text.len() + extra_shift_right, + }, + }, + cx, + ); + hover_updated = true; + } + } + project::InlayHintLabel::LabelParts(label_parts) => { + let hint_start = + snapshot.anchor_to_inlay_offset(hovered_hint.position); + if let Some((hovered_hint_part, part_range)) = + hover_popover::find_hovered_hint_part( + label_parts, + hint_start, + hovered_offset, + ) + { + let highlight_start = + (part_range.start - hint_start).0 + extra_shift_left; + let highlight_end = + (part_range.end - hint_start).0 + extra_shift_right; + let highlight = InlayHighlight { + inlay: hovered_hint.id, + inlay_position: hovered_hint.position, + range: highlight_start..highlight_end, + }; + if let Some(tooltip) = hovered_hint_part.tooltip { + hover_popover::hover_at_inlay( + editor, + InlayHover { + excerpt: excerpt_id, + tooltip: match tooltip { + InlayHintLabelPartTooltip::String(text) => { + HoverBlock { + text, + kind: HoverBlockKind::PlainText, + } + } + InlayHintLabelPartTooltip::MarkupContent( + content, + ) => HoverBlock { + text: content.value, + kind: content.kind, + }, + }, + range: highlight.clone(), + }, + cx, + ); + hover_updated = true; + } + if let Some((language_server_id, location)) = + hovered_hint_part.location + { + go_to_definition_updated = true; + update_go_to_definition_link( + editor, + Some(GoToDefinitionTrigger::InlayHint( + highlight, + location, + language_server_id, + )), + cmd_held, + shift_held, + cx, + ); + } + } + } + }; + } + ResolveState::Resolving => {} + } + } + } + } -// if !go_to_definition_updated { -// update_go_to_definition_link(editor, None, cmd_held, shift_held, cx); -// } -// if !hover_updated { -// hover_popover::hover_at(editor, None, cx); -// } -// } + if !go_to_definition_updated { + update_go_to_definition_link(editor, None, cmd_held, shift_held, cx); + } + if !hover_updated { + hover_popover::hover_at(editor, None, cx); + } +} #[derive(Debug, Clone, Copy, PartialEq)] pub enum LinkDefinitionKind {