From 1a6e972ed4ba1ba733e9214683e550f40949beb9 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 31 Jan 2022 13:17:42 -0700 Subject: [PATCH] Get basic list of completions rendering without styling Co-Authored-By: Max Brunsfeld --- crates/editor/src/editor.rs | 11 ++++++--- crates/editor/src/element.rs | 48 +++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 3bfddcc48d865c77436cfa94a2755a5b3b40d55d..0f95ef07ac05ac94ce25a2fdb18be89f3b4cdef7 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -289,7 +289,7 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec) { + fn show_completions(&mut self, _: &ShowAutocomplete, cx: &mut ViewContext) { let position = self .newest_selection::(&self.buffer.read(cx).read(cx)) .head(); @@ -1531,6 +1531,10 @@ impl Editor { .detach_and_log_err(cx); } + pub fn has_completions(&self) -> bool { + self.completion_state.is_some() + } + pub fn render_completions(&self) -> Option { self.completion_state.as_ref().map(|state| { let build_settings = self.build_settings.clone(); @@ -1542,7 +1546,8 @@ impl Editor { let settings = build_settings(cx); for completion in &completions[range] { items.push( - Label::new(completion.label().to_string(), settings.style.text.clone()).boxed(), + Label::new(completion.label().to_string(), settings.style.text.clone()) + .boxed(), ); } }, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 5bba59191be63a68c203ca94084e92c1430a80aa..2e01a2758e0d188205cd329d41dc3286fafeb639 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -300,7 +300,7 @@ impl EditorElement { &mut self, bounds: RectF, visible_bounds: RectF, - layout: &LayoutState, + layout: &mut LayoutState, cx: &mut PaintContext, ) { let view = self.view(cx.app); @@ -392,6 +392,28 @@ impl EditorElement { } cx.scene.pop_layer(); + if let Some((position, completions_list)) = layout.completions.as_mut() { + cx.scene.push_stacking_context(None); + + let cursor_row_layout = &layout.line_layouts[(position.row() - start_row) as usize]; + let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left; + let y = (position.row() + 1) as f32 * layout.line_height - scroll_top; + let mut list_origin = content_origin + vec2f(x, y); + let list_height = completions_list.size().y(); + + if list_origin.y() + list_height > bounds.lower_left().y() { + list_origin.set_y(list_origin.y() - layout.line_height - list_height); + } + + completions_list.paint( + list_origin, + RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor + cx, + ); + + cx.scene.pop_stacking_context(); + } + cx.scene.pop_layer(); } @@ -857,9 +879,29 @@ impl Element for EditorElement { snapshot = view.snapshot(cx); } - completions = view.render_completions(); + if view.has_completions() { + let newest_selection_head = view + .newest_selection::(&snapshot.buffer_snapshot) + .head() + .to_display_point(&snapshot); + + if (start_row..end_row).contains(&newest_selection_head.row()) { + let list = view.render_completions().unwrap(); + completions = Some((newest_selection_head, list)); + } + } }); + if let Some((_, completions_list)) = completions.as_mut() { + completions_list.layout( + SizeConstraint { + min: Vector2F::zero(), + max: vec2f(800., (12. * line_height).min((size.y() - line_height) / 2.)), + }, + cx, + ); + } + let blocks = self.layout_blocks( start_row..end_row, &snapshot, @@ -1004,7 +1046,7 @@ pub struct LayoutState { highlighted_ranges: Vec<(Range, Color)>, selections: HashMap>>, text_offset: Vector2F, - completions: Option, + completions: Option<(DisplayPoint, ElementBox)>, } fn layout_line(