Account for element's bounds in Editor::bounds_for_range

Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
Max Brunsfeld 2023-11-08 16:02:10 -08:00
parent 1a37d9edc6
commit 7a8f219251
4 changed files with 46 additions and 23 deletions

View file

@ -39,10 +39,10 @@ use futures::FutureExt;
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use git::diff_hunk_to_display; use git::diff_hunk_to_display;
use gpui::{ use gpui::{
action, actions, div, px, relative, AnyElement, AppContext, BackgroundExecutor, ClipboardItem, action, actions, div, point, px, relative, AnyElement, AppContext, BackgroundExecutor, Bounds,
Context, DispatchContext, Div, Element, Entity, EventEmitter, FocusHandle, FontStyle, ClipboardItem, Context, DispatchContext, Div, Element, Entity, EventEmitter, FocusHandle,
FontWeight, HighlightStyle, Hsla, InputHandler, Model, Pixels, PlatformInputHandler, Render, FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, Model, Pixels, PlatformInputHandler,
Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakView, Render, Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakView,
WindowContext, WindowContext,
}; };
use highlight_matching_bracket::refresh_matching_bracket_highlights; use highlight_matching_bracket::refresh_matching_bracket_highlights;
@ -9750,14 +9750,38 @@ impl InputHandler for Editor {
} }
fn bounds_for_range( fn bounds_for_range(
&self, &mut self,
range_utf16: Range<usize>, range_utf16: Range<usize>,
element_bounds: gpui::Bounds<Pixels>, element_bounds: gpui::Bounds<Pixels>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Option<gpui::Bounds<Pixels>> { ) -> Option<gpui::Bounds<Pixels>> {
// todo!() let text_layout_details = self.text_layout_details(cx);
// See how we did it before: `rect_for_range` let style = &text_layout_details.editor_style;
None let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
let font_size = style.text.font_size.to_pixels(cx.rem_size());
let line_height = style.text.line_height_in_pixels(cx.rem_size());
let em_width = cx
.text_system()
.typographic_bounds(font_id, font_size, 'm')
.unwrap()
.size
.width;
let snapshot = self.snapshot(cx);
let scroll_position = snapshot.scroll_position();
let scroll_left = scroll_position.x * em_width;
let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
let end = OffsetUtf16(range_utf16.end).to_display_point(&snapshot);
let start_y = line_height * (start.row() as f32 - scroll_position.y);
let end_y = line_height * (end.row() as f32 - scroll_position.y);
let start_x = snapshot.x_for_point(start, &text_layout_details) - scroll_left;
let end_x = snapshot.x_for_point(end, &text_layout_details) - scroll_left;
Some(Bounds::from_corners(
element_bounds.origin + point(start_x, start_y),
element_bounds.origin + point(end_x, end_y),
))
} }
} }

View file

@ -8,8 +8,7 @@ use crate::{
PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render,
RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow,
SharedString, Size, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline, SharedString, Size, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline,
UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowInputHandler, WindowOptions, UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
SUBPIXEL_VARIANTS,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use collections::HashMap; use collections::HashMap;

View file

@ -159,7 +159,7 @@ pub trait InputHandler: Sized {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
); );
fn bounds_for_range( fn bounds_for_range(
&self, &mut self,
range_utf16: std::ops::Range<usize>, range_utf16: std::ops::Range<usize>,
element_bounds: crate::Bounds<Pixels>, element_bounds: crate::Bounds<Pixels>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,

24
test.rs
View file

@ -10,49 +10,49 @@ use element::Element;
use frame::frame; use frame::frame;
use gpui::{ use gpui::{
geometry::{rect::RectF, vector::vec2f}, geometry::{rect::RectF, vector::vec2f},
platform::WindowOptions, platform::WindowOptions,aa
}; };
use log::LevelFilter; use log::LevelFilter;a
use simplelog::SimpleLogger; use simplelog::SimpleLogger;
use themes::{rose_pine, ThemeColors}; use themes::{rose_pine, ThemeColors};
use view::view; use view::view;a
mod adapter { mod adapter {
use crate::element::AnyElement; use crate::element::AnyElement;
use crate::element::{LayoutContext, PaintContext}; use crate::element::{LayoutContext, PaintContext};
use gpui::{geometry::rect::RectF, LayoutEngine}; use gpui::{geometry::rect::RectF, LayoutEngine};aaaa
use util::ResultExt; use util::ResultExt;
pub struct Adapter<V>(pub(crate) AnyElement<V>); pub struct Adapter<V>(pub(crate) AnyElement<V>);
impl<V: 'static> gpui::Element<V> for Adapter<V> { impl<V: 'static> gpui::Element<V> for Adapter<V> {aa
type LayoutState = Option<LayoutEngine>; type LayoutState = Option<LayaoutEngine>;
type PaintState = (); type PaintState = ();
fn layout( fn layout(
&mut self, &mut self,
constraint: gpui::SizeConstraint, constraint: gpui::SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut LayoutContext<V>, cx: &mut LayoutContext<V>,aa
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
cx.push_layout_engine(LayoutEngine::new()); cx.push_layout_engine(LayoutEngine::new());
let node = self.0.layout(view, cx).log_err(); let node = self.0.layout(view, cx).log_err();a
if let Some(node) = node { if let Some(node) = node {
let layout_engine = cx.layout_engine().unwrap(); let layout_engine = cx.layout_engine().unwrap();
layout_engine.compute_layout(node, constraint.max).log_err(); layout_engine.compute_layout(node, constraint.max).log_err();
} }
let layout_engine = cx.pop_layout_engine(); let layout_engine = cx.pop_layout_engine();
if true { if true {a
if !layout_engine.is_some() { if !layout_engine.is_some() {
::core::panicking::panic("assertion failed: layout_engine.is_some()") ::core::panicking::panic("assertion failed: layout_engine.is_some()")
} }
} }
(constraint.max, layout_engine) (constraint.max, layout_engine)a
} }
fn paint( fn paint(a
&mut self, &mut self,
scene: &mut gpui::SceneBuilder, scene: &mut gpui::SceneBuilder,
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
layout_engine: &mut Option<LayoutEngine>, layout_engine: &mut Option<LayoutEngine>,
view: &mut V, view: &mut V,
legacy_cx: &mut gpui::PaintContext<V>, legacy_cx: &mut gpui::PaintContext<V>,aaa
) -> Self::PaintState { ) -> Self::PaintState {
legacy_cx.push_layout_engine(layout_engine.take().unwrap()); legacy_cx.push_layout_engine(layout_engine.take().unwrap());
let mut cx = PaintContext::new(legacy_cx, scene); let mut cx = PaintContext::new(legacy_cx, scene);