From 6ae09634ce61db530dcb0bd5c22945a3a81860d8 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 7 Nov 2023 12:46:31 +0100 Subject: [PATCH] Remove `focused` field and use `FocusHandle` instead in `Editor` --- crates/editor2/src/editor.rs | 14 +- crates/editor2/src/element.rs | 546 ++++++++++---------- crates/editor2/src/items.rs | 16 +- crates/editor2/src/link_go_to_definition.rs | 2 +- crates/theme2/src/default_colors.rs | 24 +- 5 files changed, 300 insertions(+), 302 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 0db0d5dcd5b8f7410907ced0980dfc3e876c627e..0790641b496676a027dca9cb1947c70cde8d0215 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -634,7 +634,6 @@ pub struct Editor { // override_text_style: Option>, project: Option>, collaboration_hub: Option>, - focused: bool, blink_manager: Model, pub show_local_selections: bool, mode: EditorMode, @@ -1940,7 +1939,6 @@ impl Editor { // get_field_editor_theme, collaboration_hub: project.clone().map(|project| Box::new(project) as _), project, - focused: false, blink_manager: blink_manager.clone(), show_local_selections: true, mode, @@ -2211,7 +2209,7 @@ impl Editor { old_cursor_position: &Anchor, cx: &mut ViewContext, ) { - if self.focused && self.leader_peer_id.is_none() { + if self.focus_handle.is_focused(cx) && self.leader_peer_id.is_none() { self.buffer.update(cx, |buffer, cx| { buffer.set_active_selections( &self.selections.disjoint_anchors(), @@ -2458,7 +2456,7 @@ impl Editor { click_count: usize, cx: &mut ViewContext, ) { - if !self.focused { + if !self.focus_handle.is_focused(cx) { cx.focus(&self.focus_handle); } @@ -2524,7 +2522,7 @@ impl Editor { goal_column: u32, cx: &mut ViewContext, ) { - if !self.focused { + if !self.focus_handle.is_focused(cx) { cx.focus(&self.focus_handle); } @@ -3631,7 +3629,7 @@ impl Editor { _ => return, } - if this.focused && menu.is_some() { + if this.focus_handle.is_focused(cx) && menu.is_some() { let menu = menu.unwrap(); *context_menu = Some(ContextMenu::Completions(menu)); drop(context_menu); @@ -8693,8 +8691,8 @@ impl Editor { } } - pub fn show_local_cursors(&self, cx: &AppContext) -> bool { - self.blink_manager.read(cx).visible() && self.focused + pub fn show_local_cursors(&self, cx: &WindowContext) -> bool { + self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx) } fn on_buffer_changed(&mut self, _: Model, cx: &mut ViewContext) { diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 4ad22599d23d8b83307c3b4da541ee214e98ff9d..e1fea4a8e5b3a054c9bb7e9b2655b7a864f3d045 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -774,72 +774,91 @@ impl EditorElement { let line_end_overshoot = 0.15 * layout.position_map.line_height; let whitespace_setting = editor.buffer.read(cx).settings_at(0, cx).show_whitespaces; - cx.with_content_mask(ContentMask { bounds }, |cx| { - // todo!("cursor region") - // cx.scene().push_cursor_region(CursorRegion { - // bounds, - // style: if !editor.link_go_to_definition_state.definitions.is_empty { - // CursorStyle::PointingHand - // } else { - // CursorStyle::IBeam - // }, - // }); - - // todo!("fold ranges") - // let fold_corner_radius = - // self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height; - // for (id, range, color) in layout.fold_ranges.iter() { - // self.paint_highlighted_range( - // range.clone(), - // *color, - // fold_corner_radius, - // fold_corner_radius * 2., - // layout, - // content_origin, - // scroll_top, - // scroll_left, - // bounds, - // cx, - // ); - - // for bound in range_to_bounds( - // &range, - // content_origin, - // scroll_left, - // scroll_top, - // &layout.visible_display_row_range, - // line_end_overshoot, - // &layout.position_map, - // ) { - // cx.scene().push_cursor_region(CursorRegion { - // bounds: bound, - // style: CursorStyle::PointingHand, - // }); - - // let display_row = range.start.row(); - - // let buffer_row = DisplayPoint::new(display_row, 0) - // .to_point(&layout.position_map.snapshot.display_snapshot) - // .row; - - // let view_id = cx.view_id(); - // cx.scene().push_mouse_region( - // MouseRegion::new::(view_id, *id as usize, bound) - // .on_click(MouseButton::Left, move |_, editor: &mut Editor, cx| { - // editor.unfold_at(&UnfoldAt { buffer_row }, cx) - // }) - // .with_notify_on_hover(true) - // .with_notify_on_click(true), - // ) - // } - // } - - for (range, color) in &layout.highlighted_ranges { + // todo!("cursor region") + // cx.scene().push_cursor_region(CursorRegion { + // bounds, + // style: if !editor.link_go_to_definition_state.definitions.is_empty { + // CursorStyle::PointingHand + // } else { + // CursorStyle::IBeam + // }, + // }); + + // todo!("fold ranges") + // let fold_corner_radius = + // self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height; + // for (id, range, color) in layout.fold_ranges.iter() { + // self.paint_highlighted_range( + // range.clone(), + // *color, + // fold_corner_radius, + // fold_corner_radius * 2., + // layout, + // content_origin, + // scroll_top, + // scroll_left, + // bounds, + // cx, + // ); + + // for bound in range_to_bounds( + // &range, + // content_origin, + // scroll_left, + // scroll_top, + // &layout.visible_display_row_range, + // line_end_overshoot, + // &layout.position_map, + // ) { + // cx.scene().push_cursor_region(CursorRegion { + // bounds: bound, + // style: CursorStyle::PointingHand, + // }); + + // let display_row = range.start.row(); + + // let buffer_row = DisplayPoint::new(display_row, 0) + // .to_point(&layout.position_map.snapshot.display_snapshot) + // .row; + + // let view_id = cx.view_id(); + // cx.scene().push_mouse_region( + // MouseRegion::new::(view_id, *id as usize, bound) + // .on_click(MouseButton::Left, move |_, editor: &mut Editor, cx| { + // editor.unfold_at(&UnfoldAt { buffer_row }, cx) + // }) + // .with_notify_on_hover(true) + // .with_notify_on_click(true), + // ) + // } + // } + + for (range, color) in &layout.highlighted_ranges { + self.paint_highlighted_range( + range.clone(), + *color, + Pixels::ZERO, + line_end_overshoot, + layout, + content_origin, + scroll_top, + scroll_left, + bounds, + cx, + ); + } + + let mut cursors = SmallVec::<[Cursor; 32]>::new(); + let corner_radius = 0.15 * layout.position_map.line_height; + let mut invisible_display_ranges = SmallVec::<[Range; 32]>::new(); + + for (selection_style, selections) in &layout.selections { + for selection in selections { self.paint_highlighted_range( - range.clone(), - *color, - Pixels::ZERO, - line_end_overshoot, + selection.range.clone(), + selection_style.selection, + corner_radius, + corner_radius * 2., layout, content_origin, scroll_top, @@ -847,222 +866,205 @@ impl EditorElement { bounds, cx, ); - } - let mut cursors = SmallVec::<[Cursor; 32]>::new(); - let corner_radius = 0.15 * layout.position_map.line_height; - let mut invisible_display_ranges = SmallVec::<[Range; 32]>::new(); - - for (selection_style, selections) in &layout.selections { - for selection in selections { - self.paint_highlighted_range( - selection.range.clone(), - selection_style.selection, - corner_radius, - corner_radius * 2., - layout, - content_origin, - scroll_top, - scroll_left, - bounds, - cx, - ); + if selection.is_local && !selection.range.is_empty() { + invisible_display_ranges.push(selection.range.clone()); + } - if selection.is_local && !selection.range.is_empty() { - invisible_display_ranges.push(selection.range.clone()); - } - if !selection.is_local || editor.show_local_cursors(cx) { - let cursor_position = selection.head; - if layout - .visible_display_row_range - .contains(&cursor_position.row()) - { - let cursor_row_layout = &layout.position_map.line_layouts - [(cursor_position.row() - start_row) as usize] - .line; - let cursor_column = cursor_position.column() as usize; - - let cursor_character_x = cursor_row_layout.x_for_index(cursor_column); - let mut block_width = cursor_row_layout.x_for_index(cursor_column + 1) - - cursor_character_x; - if block_width == Pixels::ZERO { - block_width = layout.position_map.em_width; - } - let block_text = if let CursorShape::Block = selection.cursor_shape { - layout - .position_map - .snapshot - .chars_at(cursor_position) - .next() - .and_then(|(character, _)| { - let text = character.to_string(); - cx.text_system() - .layout_text( - &text, - cursor_row_layout.font_size, - &[TextRun { - len: text.len(), - font: self.style.text.font(), - color: self.style.background, - underline: None, - }], - None, - ) - .unwrap() - .pop() - }) - } else { - None - }; - - let x = cursor_character_x - scroll_left; - let y = cursor_position.row() as f32 * layout.position_map.line_height - - scroll_top; - if selection.is_newest { - editor.pixel_position_of_newest_cursor = Some(point( - bounds.origin.x + x + block_width / 2., - bounds.origin.y + y + layout.position_map.line_height / 2., - )); - } - cursors.push(Cursor { - color: selection_style.cursor, - block_width, - origin: point(x, y), - line_height: layout.position_map.line_height, - shape: selection.cursor_shape, - block_text, - }); + if !selection.is_local || editor.show_local_cursors(cx) { + let cursor_position = selection.head; + if layout + .visible_display_row_range + .contains(&cursor_position.row()) + { + let cursor_row_layout = &layout.position_map.line_layouts + [(cursor_position.row() - start_row) as usize] + .line; + let cursor_column = cursor_position.column() as usize; + + let cursor_character_x = cursor_row_layout.x_for_index(cursor_column); + let mut block_width = + cursor_row_layout.x_for_index(cursor_column + 1) - cursor_character_x; + if block_width == Pixels::ZERO { + block_width = layout.position_map.em_width; + } + let block_text = if let CursorShape::Block = selection.cursor_shape { + layout + .position_map + .snapshot + .chars_at(cursor_position) + .next() + .and_then(|(character, _)| { + let text = character.to_string(); + cx.text_system() + .layout_text( + &text, + cursor_row_layout.font_size, + &[TextRun { + len: text.len(), + font: self.style.text.font(), + color: self.style.background, + underline: None, + }], + None, + ) + .unwrap() + .pop() + }) + } else { + None + }; + + let x = cursor_character_x - scroll_left; + let y = cursor_position.row() as f32 * layout.position_map.line_height + - scroll_top; + if selection.is_newest { + editor.pixel_position_of_newest_cursor = Some(point( + bounds.origin.x + x + block_width / 2., + bounds.origin.y + y + layout.position_map.line_height / 2., + )); } + cursors.push(Cursor { + color: selection_style.cursor, + block_width, + origin: point(x, y), + line_height: layout.position_map.line_height, + shape: selection.cursor_shape, + block_text, + }); } } } + } - for (ix, line_with_invisibles) in layout.position_map.line_layouts.iter().enumerate() { - let row = start_row + ix as u32; - line_with_invisibles.draw( - layout, - row, - scroll_top, - content_origin, - scroll_left, - whitespace_setting, - &invisible_display_ranges, - cx, - ) - } + for (ix, line_with_invisibles) in layout.position_map.line_layouts.iter().enumerate() { + let row = start_row + ix as u32; + line_with_invisibles.draw( + layout, + row, + scroll_top, + content_origin, + scroll_left, + whitespace_setting, + &invisible_display_ranges, + cx, + ) + } - // cx.scene().push_layer(Some(bounds)); + cx.stack(9999, |cx| { for cursor in cursors { cursor.paint(content_origin, cx); } - // cx.scene().pop_layer(); - - // if let Some((position, context_menu)) = layout.context_menu.as_mut() { - // cx.scene().push_stacking_context(None, None); - // let cursor_row_layout = - // &layout.position_map.line_layouts[(position.row() - start_row) as usize].line; - // let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left; - // let y = (position.row() + 1) as f32 * layout.position_map.line_height - scroll_top; - // let mut list_origin = content_origin + point(x, y); - // let list_width = context_menu.size().x; - // let list_height = context_menu.size().y; - - // // Snap the right edge of the list to the right edge of the window if - // // its horizontal bounds overflow. - // if list_origin.x + list_width > cx.window_size().x { - // list_origin.set_x((cx.window_size().x - list_width).max(0.)); - // } - - // if list_origin.y + list_height > bounds.max_y { - // list_origin - // .set_y(list_origin.y - layout.position_map.line_height - list_height); - // } - - // context_menu.paint( - // list_origin, - // Bounds::::from_points( - // gpui::Point::::zero(), - // point(f32::MAX, f32::MAX), - // ), // Let content bleed outside of editor - // editor, - // cx, - // ); - - // cx.scene().pop_stacking_context(); - // } - - // if let Some((position, hover_popovers)) = layout.hover_popovers.as_mut() { - // cx.scene().push_stacking_context(None, None); - - // // This is safe because we check on layout whether the required row is available - // let hovered_row_layout = - // &layout.position_map.line_layouts[(position.row() - start_row) as usize].line; - - // // Minimum required size: Take the first popover, and add 1.5 times the minimum popover - // // height. This is the size we will use to decide whether to render popovers above or below - // // the hovered line. - // let first_size = hover_popovers[0].size(); - // let height_to_reserve = first_size.y - // + 1.5 * MIN_POPOVER_LINE_HEIGHT as f32 * layout.position_map.line_height; - - // // Compute Hovered Point - // let x = hovered_row_layout.x_for_index(position.column() as usize) - scroll_left; - // let y = position.row() as f32 * layout.position_map.line_height - scroll_top; - // let hovered_point = content_origin + point(x, y); - - // if hovered_point.y - height_to_reserve > 0.0 { - // // There is enough space above. Render popovers above the hovered point - // let mut current_y = hovered_point.y; - // for hover_popover in hover_popovers { - // let size = hover_popover.size(); - // let mut popover_origin = point(hovered_point.x, current_y - size.y); - - // let x_out_of_bounds = bounds.max_x - (popover_origin.x + size.x); - // if x_out_of_bounds < 0.0 { - // popover_origin.set_x(popover_origin.x + x_out_of_bounds); - // } - - // hover_popover.paint( - // popover_origin, - // Bounds::::from_points( - // gpui::Point::::zero(), - // point(f32::MAX, f32::MAX), - // ), // Let content bleed outside of editor - // editor, - // cx, - // ); - - // current_y = popover_origin.y - HOVER_POPOVER_GAP; - // } - // } else { - // // There is not enough space above. Render popovers below the hovered point - // let mut current_y = hovered_point.y + layout.position_map.line_height; - // for hover_popover in hover_popovers { - // let size = hover_popover.size(); - // let mut popover_origin = point(hovered_point.x, current_y); - - // let x_out_of_bounds = bounds.max_x - (popover_origin.x + size.x); - // if x_out_of_bounds < 0.0 { - // popover_origin.set_x(popover_origin.x + x_out_of_bounds); - // } - - // hover_popover.paint( - // popover_origin, - // Bounds::::from_points( - // gpui::Point::::zero(), - // point(f32::MAX, f32::MAX), - // ), // Let content bleed outside of editor - // editor, - // cx, - // ); - - // current_y = popover_origin.y + size.y + HOVER_POPOVER_GAP; - // } - // } - - // cx.scene().pop_stacking_context(); - // } - }) + }); + // cx.scene().push_layer(Some(bounds)); + + // cx.scene().pop_layer(); + + // if let Some((position, context_menu)) = layout.context_menu.as_mut() { + // cx.scene().push_stacking_context(None, None); + // let cursor_row_layout = + // &layout.position_map.line_layouts[(position.row() - start_row) as usize].line; + // let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left; + // let y = (position.row() + 1) as f32 * layout.position_map.line_height - scroll_top; + // let mut list_origin = content_origin + point(x, y); + // let list_width = context_menu.size().x; + // let list_height = context_menu.size().y; + + // // Snap the right edge of the list to the right edge of the window if + // // its horizontal bounds overflow. + // if list_origin.x + list_width > cx.window_size().x { + // list_origin.set_x((cx.window_size().x - list_width).max(0.)); + // } + + // if list_origin.y + list_height > bounds.max_y { + // list_origin + // .set_y(list_origin.y - layout.position_map.line_height - list_height); + // } + + // context_menu.paint( + // list_origin, + // Bounds::::from_points( + // gpui::Point::::zero(), + // point(f32::MAX, f32::MAX), + // ), // Let content bleed outside of editor + // editor, + // cx, + // ); + + // cx.scene().pop_stacking_context(); + // } + + // if let Some((position, hover_popovers)) = layout.hover_popovers.as_mut() { + // cx.scene().push_stacking_context(None, None); + + // // This is safe because we check on layout whether the required row is available + // let hovered_row_layout = + // &layout.position_map.line_layouts[(position.row() - start_row) as usize].line; + + // // Minimum required size: Take the first popover, and add 1.5 times the minimum popover + // // height. This is the size we will use to decide whether to render popovers above or below + // // the hovered line. + // let first_size = hover_popovers[0].size(); + // let height_to_reserve = first_size.y + // + 1.5 * MIN_POPOVER_LINE_HEIGHT as f32 * layout.position_map.line_height; + + // // Compute Hovered Point + // let x = hovered_row_layout.x_for_index(position.column() as usize) - scroll_left; + // let y = position.row() as f32 * layout.position_map.line_height - scroll_top; + // let hovered_point = content_origin + point(x, y); + + // if hovered_point.y - height_to_reserve > 0.0 { + // // There is enough space above. Render popovers above the hovered point + // let mut current_y = hovered_point.y; + // for hover_popover in hover_popovers { + // let size = hover_popover.size(); + // let mut popover_origin = point(hovered_point.x, current_y - size.y); + + // let x_out_of_bounds = bounds.max_x - (popover_origin.x + size.x); + // if x_out_of_bounds < 0.0 { + // popover_origin.set_x(popover_origin.x + x_out_of_bounds); + // } + + // hover_popover.paint( + // popover_origin, + // Bounds::::from_points( + // gpui::Point::::zero(), + // point(f32::MAX, f32::MAX), + // ), // Let content bleed outside of editor + // editor, + // cx, + // ); + + // current_y = popover_origin.y - HOVER_POPOVER_GAP; + // } + // } else { + // // There is not enough space above. Render popovers below the hovered point + // let mut current_y = hovered_point.y + layout.position_map.line_height; + // for hover_popover in hover_popovers { + // let size = hover_popover.size(); + // let mut popover_origin = point(hovered_point.x, current_y); + + // let x_out_of_bounds = bounds.max_x - (popover_origin.x + size.x); + // if x_out_of_bounds < 0.0 { + // popover_origin.set_x(popover_origin.x + x_out_of_bounds); + // } + + // hover_popover.paint( + // popover_origin, + // Bounds::::from_points( + // gpui::Point::::zero(), + // point(f32::MAX, f32::MAX), + // ), // Let content bleed outside of editor + // editor, + // cx, + // ); + + // current_y = popover_origin.y + size.y + HOVER_POPOVER_GAP; + // } + // } + + // cx.scene().pop_stacking_context(); + // } } fn scrollbar_left(&self, bounds: &Bounds) -> Pixels { @@ -2543,7 +2545,7 @@ impl Element for EditorElement { fn initialize( &mut self, - view_state: &mut Editor, + editor: &mut Editor, element_state: Option, cx: &mut gpui::ViewContext, ) -> Self::ElementState { @@ -2552,7 +2554,7 @@ impl Element for EditorElement { fn layout( &mut self, - view_state: &mut Editor, + editor: &mut Editor, element_state: &mut Self::ElementState, cx: &mut gpui::ViewContext, ) -> gpui::LayoutId { diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index a4d34ad36f218af6440ac8183d47c4afca1547df..e0b4423f82dec1cc3f732d40743f2e534a3f3477 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -159,16 +159,14 @@ impl FollowableItem for Editor { self.buffer.update(cx, |buffer, cx| { buffer.remove_active_selections(cx); }); - } else { + } else if self.focus_handle.is_focused(cx) { self.buffer.update(cx, |buffer, cx| { - if self.focused { - buffer.set_active_selections( - &self.selections.disjoint_anchors(), - self.selections.line_mode, - self.cursor_shape, - cx, - ); - } + buffer.set_active_selections( + &self.selections.disjoint_anchors(), + self.selections.line_mode, + self.cursor_shape, + cx, + ); }); } cx.notify(); diff --git a/crates/editor2/src/link_go_to_definition.rs b/crates/editor2/src/link_go_to_definition.rs index 8c285c8214c1948435daf7f81e1b38c073be4baa..9db4061e5096ac3f4b3a221a3bc22f45114b26d2 100644 --- a/crates/editor2/src/link_go_to_definition.rs +++ b/crates/editor2/src/link_go_to_definition.rs @@ -581,7 +581,7 @@ fn go_to_fetched_definition_of_kind( let is_correct_kind = cached_definitions_kind == Some(kind); if !cached_definitions.is_empty() && is_correct_kind { - if !editor.focused { + if !editor.focus_handle.is_focused(cx) { cx.focus(&editor.focus_handle); } diff --git a/crates/theme2/src/default_colors.rs b/crates/theme2/src/default_colors.rs index da2608da62f04b37e07773660912a7608d8d7a6c..0df1988ead70d321c9b25b05e80e47538cbae8f6 100644 --- a/crates/theme2/src/default_colors.rs +++ b/crates/theme2/src/default_colors.rs @@ -59,24 +59,24 @@ impl Default for PlayerColors { fn default() -> Self { Self(vec![ PlayerColor { - cursor: hsla(0.0, 0.0, 0.0, 0.0), - background: hsla(0.0, 0.0, 0.0, 0.0), - selection: hsla(0.0, 0.0, 0.0, 0.0), + cursor: hsla(0.0, 0.0, 0.0, 1.0), + background: hsla(0.0, 0.0, 0.0, 1.0), + selection: hsla(0.0, 0.0, 0.0, 1.0), }, PlayerColor { - cursor: hsla(0.0, 0.0, 0.0, 0.0), - background: hsla(0.0, 0.0, 0.0, 0.0), - selection: hsla(0.0, 0.0, 0.0, 0.0), + cursor: hsla(0.0, 0.0, 0.0, 1.0), + background: hsla(0.0, 0.0, 0.0, 1.0), + selection: hsla(0.0, 0.0, 0.0, 1.0), }, PlayerColor { - cursor: hsla(0.0, 0.0, 0.0, 0.0), - background: hsla(0.0, 0.0, 0.0, 0.0), - selection: hsla(0.0, 0.0, 0.0, 0.0), + cursor: hsla(0.0, 0.0, 0.0, 1.0), + background: hsla(0.0, 0.0, 0.0, 1.0), + selection: hsla(0.0, 0.0, 0.0, 1.0), }, PlayerColor { - cursor: hsla(0.0, 0.0, 0.0, 0.0), - background: hsla(0.0, 0.0, 0.0, 0.0), - selection: hsla(0.0, 0.0, 0.0, 0.0), + cursor: hsla(0.0, 0.0, 0.0, 1.0), + background: hsla(0.0, 0.0, 0.0, 1.0), + selection: hsla(0.0, 0.0, 0.0, 1.0), }, ]) }